diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java index 5390d535de..bfdf4204a9 100644 --- a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java @@ -28,7 +28,6 @@ import io.netty.util.internal.logging.InternalLoggerFactory; import java.net.SocketAddress; import java.util.ArrayList; -import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -60,9 +59,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { final AbstractChannelHandlerContext head; final AbstractChannelHandlerContext tail; - private final Map name2ctx = - new HashMap(4); - final Map childExecutors = new IdentityHashMap(); @@ -94,13 +90,13 @@ final class DefaultChannelPipeline implements ChannelPipeline { synchronized (this) { checkDuplicateName(name); AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addFirst0(name, newCtx); + addFirst0(newCtx); } return this; } - private void addFirst0(String name, AbstractChannelHandlerContext newCtx) { + private void addFirst0(AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); AbstractChannelHandlerContext nextCtx = head.next; @@ -109,8 +105,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { head.next = newCtx; nextCtx.prev = newCtx; - name2ctx.put(name, newCtx); - callHandlerAdded(newCtx); } @@ -125,13 +119,13 @@ final class DefaultChannelPipeline implements ChannelPipeline { checkDuplicateName(name); AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addLast0(name, newCtx); + addLast0(newCtx); } return this; } - private void addLast0(final String name, AbstractChannelHandlerContext newCtx) { + private void addLast0(AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); AbstractChannelHandlerContext prev = tail.prev; @@ -140,8 +134,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { prev.next = newCtx; tail.prev = newCtx; - name2ctx.put(name, newCtx); - callHandlerAdded(newCtx); } @@ -157,13 +149,12 @@ final class DefaultChannelPipeline implements ChannelPipeline { AbstractChannelHandlerContext ctx = getContextOrDie(baseName); checkDuplicateName(name); AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addBefore0(name, ctx, newCtx); + addBefore0(ctx, newCtx); } return this; } - private void addBefore0( - final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { + private void addBefore0(AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); newCtx.prev = ctx.prev; @@ -171,8 +162,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { ctx.prev.next = newCtx; ctx.prev = newCtx; - name2ctx.put(name, newCtx); - callHandlerAdded(newCtx); } @@ -189,14 +178,13 @@ final class DefaultChannelPipeline implements ChannelPipeline { checkDuplicateName(name); AbstractChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler); - addAfter0(name, ctx, newCtx); + addAfter0(ctx, newCtx); } return this; } - private void addAfter0(final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkDuplicateName(name); + private void addAfter0(AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); newCtx.prev = ctx; @@ -204,8 +192,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { ctx.next.prev = newCtx; ctx.next = newCtx; - name2ctx.put(name, newCtx); - callHandlerAdded(newCtx); } @@ -271,11 +257,11 @@ final class DefaultChannelPipeline implements ChannelPipeline { synchronized (this) { // It's not very likely for a user to put more than one handler of the same type, but make sure to avoid // any name conflicts. Note that we don't cache the names generated here. - if (name2ctx.containsKey(name)) { + if (context0(name) != null) { String baseName = name.substring(0, name.length() - 1); // Strip the trailing '0'. for (int i = 1;; i ++) { String newName = baseName + i; - if (!name2ctx.containsKey(newName)) { + if (context0(newName) == null) { name = newName; break; } @@ -343,7 +329,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { AbstractChannelHandlerContext next = ctx.next; prev.next = next; next.prev = prev; - name2ctx.remove(ctx.name()); callHandlerRemoved(ctx); } @@ -398,14 +383,14 @@ final class DefaultChannelPipeline implements ChannelPipeline { new DefaultChannelHandlerContext(this, ctx.executor, newName, newHandler); if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) { - replace0(ctx, newName, newCtx); + replace0(ctx, newCtx); return ctx.handler(); } else { future = newCtx.executor().submit(new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { - replace0(ctx, newName, newCtx); + replace0(ctx, newCtx); } } }); @@ -420,8 +405,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { return ctx.handler(); } - private void replace0(AbstractChannelHandlerContext oldCtx, String newName, - AbstractChannelHandlerContext newCtx) { + private void replace0(AbstractChannelHandlerContext oldCtx, AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); AbstractChannelHandlerContext prev = oldCtx.prev; @@ -436,11 +420,6 @@ final class DefaultChannelPipeline implements ChannelPipeline { prev.next = newCtx; next.prev = newCtx; - if (!oldCtx.name().equals(newName)) { - name2ctx.remove(oldCtx.name()); - } - name2ctx.put(newName, newCtx); - // update the reference to the replacement so forward of buffered content will work correctly oldCtx.prev = newCtx; oldCtx.next = newCtx; @@ -618,9 +597,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { throw new NullPointerException("name"); } - synchronized (this) { - return name2ctx.get(name); - } + return context0(name); } @Override @@ -745,8 +722,8 @@ final class DefaultChannelPipeline implements ChannelPipeline { * Removes all handlers from the pipeline one by one from tail (exclusive) to head (exclusive) to trigger * handlerRemoved(). * - * Note that we traverse up the pipeline ({@link #destroyUp(AbstractChannelHandlerContext)}) - * before traversing down ({@link #destroyDown(Thread, AbstractChannelHandlerContext)}) so that + * Note that we traverse up the pipeline ({@link #destroyUp(AbstractChannelHandlerContext, boolean)}) + * before traversing down ({@link #destroyDown(Thread, AbstractChannelHandlerContext, boolean)}) so that * the handlers are removed after all events are handled. * * See: https://github.com/netty/netty/issues/3156 @@ -953,11 +930,22 @@ final class DefaultChannelPipeline implements ChannelPipeline { } private void checkDuplicateName(String name) { - if (name2ctx.containsKey(name)) { + if (context0(name) != null) { throw new IllegalArgumentException("Duplicate handler name: " + name); } } + private AbstractChannelHandlerContext context0(String name) { + AbstractChannelHandlerContext context = head.next; + while (context != tail) { + if (context.name().equals(name)) { + return context; + } + context = context.next; + } + return null; + } + private AbstractChannelHandlerContext getContextOrDie(String name) { AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(name); if (ctx == null) {