SimpleChannelPool POOL_KEY attribute name is easy to get conflict from user code (#9542) (#9548)

Motivation:

    It is noticed that SimpleChannelPool's POOL_KEY attribute name channelPool is easy to get conflict with user code and throws an exception 'channelPool' is already in use. Being a generic framework - it would be great if we can name the attribute something unique - may be use UUID for the name since the name is not required later.

    Modifications:

    This change make sure that the POOL_KEY used inside SimpleChannelPool is unique by appending the object hashcode in the name.

    Result:

    No unwanted channel attribute name conflict with user code.
This commit is contained in:
Nizar Mankulangara 2019-09-09 00:47:23 -07:00 committed by Norman Maurer
parent 6bc2da6141
commit 572b6a8f19

View File

@ -39,7 +39,8 @@ import static io.netty.util.internal.ObjectUtil.*;
* *
*/ */
public class SimpleChannelPool implements ChannelPool { public class SimpleChannelPool implements ChannelPool {
private static final AttributeKey<SimpleChannelPool> POOL_KEY = AttributeKey.newInstance("channelPool"); private final AttributeKey<SimpleChannelPool> poolKey = AttributeKey.newInstance("channelPool." +
System.identityHashCode(this));
private final Deque<Channel> deque = PlatformDependent.newConcurrentDeque(); private final Deque<Channel> deque = PlatformDependent.newConcurrentDeque();
private final ChannelPoolHandler handler; private final ChannelPoolHandler handler;
private final ChannelHealthChecker healthCheck; private final ChannelHealthChecker healthCheck;
@ -171,7 +172,7 @@ public class SimpleChannelPool implements ChannelPool {
if (ch == null) { if (ch == null) {
// No Channel left in the pool bootstrap a new Channel // No Channel left in the pool bootstrap a new Channel
Bootstrap bs = bootstrap.clone(); Bootstrap bs = bootstrap.clone();
bs.attr(POOL_KEY, this); bs.attr(poolKey, this);
ChannelFuture f = connectChannel(bs); ChannelFuture f = connectChannel(bs);
if (f.isDone()) { if (f.isDone()) {
notifyConnect(f, promise); notifyConnect(f, promise);
@ -237,7 +238,7 @@ public class SimpleChannelPool implements ChannelPool {
if (future.isSuccess()) { if (future.isSuccess()) {
if (future.getNow()) { if (future.getNow()) {
try { try {
ch.attr(POOL_KEY).set(this); ch.attr(poolKey).set(this);
handler.channelAcquired(ch); handler.channelAcquired(ch);
promise.setSuccess(ch); promise.setSuccess(ch);
} catch (Throwable cause) { } catch (Throwable cause) {
@ -293,7 +294,7 @@ public class SimpleChannelPool implements ChannelPool {
private void doReleaseChannel(Channel channel, Promise<Void> promise) { private void doReleaseChannel(Channel channel, Promise<Void> promise) {
assert channel.eventLoop().inEventLoop(); assert channel.eventLoop().inEventLoop();
// Remove the POOL_KEY attribute from the Channel and check if it was acquired from this pool, if not fail. // Remove the POOL_KEY attribute from the Channel and check if it was acquired from this pool, if not fail.
if (channel.attr(POOL_KEY).getAndSet(null) != this) { if (channel.attr(poolKey).getAndSet(null) != this) {
closeAndFail(channel, closeAndFail(channel,
// Better include a stacktrace here as this is an user error. // Better include a stacktrace here as this is an user error.
new IllegalArgumentException( new IllegalArgumentException(
@ -357,12 +358,12 @@ public class SimpleChannelPool implements ChannelPool {
} }
} }
private static void closeChannel(Channel channel) { private void closeChannel(Channel channel) {
channel.attr(POOL_KEY).getAndSet(null); channel.attr(poolKey).getAndSet(null);
channel.close(); channel.close();
} }
private static void closeAndFail(Channel channel, Throwable cause, Promise<?> promise) { private void closeAndFail(Channel channel, Throwable cause, Promise<?> promise) {
closeChannel(channel); closeChannel(channel);
promise.tryFailure(cause); promise.tryFailure(cause);
} }