From e157ea1a666142b5a603248dade7b767cc1af95e Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Mon, 9 Jul 2012 01:09:21 +0900 Subject: [PATCH] Allow a user use any type as a ReplayingDecoder state / AIO cleanup - Removed VoidEnum because a user can now specify Void instead - AIO: Prefer discardReadBytes to clear - AIO: Fixed a potential bug where notifyFlushFutures() is not called if flush() was requested with no outbound data --- .../websocketx/WebSocket00FrameDecoder.java | 3 +-- .../netty/handler/codec/ReplayingDecoder.java | 18 +++++++------- .../CompatibleMarshallingDecoder.java | 3 +-- .../handler/codec/ReplayingDecoderTest.java | 3 +-- .../src/main/java/io/netty/util/VoidEnum.java | 24 ------------------- .../channel/socket/aio/AioSocketChannel.java | 12 ++++++---- 6 files changed, 19 insertions(+), 44 deletions(-) delete mode 100644 common/src/main/java/io/netty/util/VoidEnum.java diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java index 4209053456..b18b43e3bf 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java @@ -19,7 +19,6 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; -import io.netty.util.VoidEnum; /** * Decodes {@link ByteBuf}s into {@link WebSocketFrame}s. @@ -30,7 +29,7 @@ import io.netty.util.VoidEnum; * @apiviz.landmark * @apiviz.uses io.netty.handler.codec.http.websocket.WebSocketFrame */ -public class WebSocket00FrameDecoder extends ReplayingDecoder { +public class WebSocket00FrameDecoder extends ReplayingDecoder { static final int DEFAULT_MAX_FRAME_SIZE = 16384; diff --git a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java index 3e0b631f85..07bfc67975 100644 --- a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoder.java @@ -22,7 +22,6 @@ import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.util.Signal; -import io.netty.util.VoidEnum; /** * A specialized variation of {@link ByteToMessageDecoder} which enables implementation @@ -105,7 +104,7 @@ import io.netty.util.VoidEnum; *
  • You must keep in mind that {@code decode(..)} method can be called many * times to decode a single message. For example, the following code will * not work: - *
     public class MyDecoder extends {@link ReplayingDecoder}<{@link VoidEnum}> {
    + * 
     public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
      *
      *   private final Queue<Integer> values = new LinkedList<Integer>();
      *
    @@ -125,7 +124,7 @@ import io.netty.util.VoidEnum;
      *      The correct implementation looks like the following, and you can also
      *      utilize the 'checkpoint' feature which is explained in detail in the
      *      next section.
    - * 
     public class MyDecoder extends {@link ReplayingDecoder}<{@link VoidEnum}> {
    + * 
     public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
      *
      *   private final Queue<Integer> values = new LinkedList<Integer>();
      *
    @@ -206,7 +205,7 @@ import io.netty.util.VoidEnum;
      * An alternative way to manage the decoder state is to manage it by yourself.
      * 
      * public class IntegerHeaderFrameDecoder
    - *      extends {@link ReplayingDecoder}<{@link VoidEnum}> {
    + *      extends {@link ReplayingDecoder}<{@link Void}> {
      *
      *   private boolean readLength;
      *   private int length;
    @@ -215,7 +214,7 @@ import io.netty.util.VoidEnum;
      *   protected Object decode({@link ChannelHandlerContext} ctx,
      *                           {@link Channel} channel,
      *                           {@link ByteBuf} buf,
    - *                           {@link VoidEnum} state) throws Exception {
    + *                           {@link Void} state) throws Exception {
      *     if (!readLength) {
      *       length = buf.readInt();
      *       readLength = true;
    @@ -241,7 +240,7 @@ import io.netty.util.VoidEnum;
      * {@link ChannelPipeline#replace(ChannelHandler, String, ChannelHandler)}, but
      * some additional steps are required:
      * 
    - * public class FirstDecoder extends {@link ReplayingDecoder}<{@link VoidEnum}> {
    + * public class FirstDecoder extends {@link ReplayingDecoder}<{@link Void}> {
      *
      *     public FirstDecoder() {
      *         super(true); // Enable unfold
    @@ -251,7 +250,7 @@ import io.netty.util.VoidEnum;
      *     protected Object decode({@link ChannelHandlerContext} ctx,
      *                             {@link Channel} ch,
      *                             {@link ByteBuf} buf,
    - *                             {@link VoidEnum} state) {
    + *                             {@link Void} state) {
      *         ...
      *         // Decode the first message
      *         Object firstMessage = ...;
    @@ -272,12 +271,13 @@ import io.netty.util.VoidEnum;
      *     }
      * 
    * @param - * the state type; use {@link VoidEnum} if state management is unused + * the state type which is usually an {@link Enum}; use {@link Void} if state management is + * unused * * @apiviz.landmark * @apiviz.has io.netty.handler.codec.UnreplayableOperationException oneway - - throws */ -public abstract class ReplayingDecoder> extends ByteToMessageDecoder { +public abstract class ReplayingDecoder extends ByteToMessageDecoder { static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY"); diff --git a/codec/src/main/java/io/netty/handler/codec/marshalling/CompatibleMarshallingDecoder.java b/codec/src/main/java/io/netty/handler/codec/marshalling/CompatibleMarshallingDecoder.java index ee7f459b1c..86d5f9691e 100644 --- a/codec/src/main/java/io/netty/handler/codec/marshalling/CompatibleMarshallingDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/marshalling/CompatibleMarshallingDecoder.java @@ -20,7 +20,6 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; -import io.netty.util.VoidEnum; import java.io.ObjectStreamConstants; @@ -32,7 +31,7 @@ import org.jboss.marshalling.Unmarshaller; * * If you can you should use {@link MarshallingDecoder}. */ -public class CompatibleMarshallingDecoder extends ReplayingDecoder { +public class CompatibleMarshallingDecoder extends ReplayingDecoder { protected final UnmarshallerProvider provider; protected final int maxObjectSize; diff --git a/codec/src/test/java/io/netty/handler/codec/ReplayingDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/ReplayingDecoderTest.java index 529767dade..900a255730 100644 --- a/codec/src/test/java/io/netty/handler/codec/ReplayingDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/ReplayingDecoderTest.java @@ -21,7 +21,6 @@ import io.netty.buffer.ByteBufIndexFinder; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.embedded.EmbeddedByteChannel; -import io.netty.util.VoidEnum; import org.junit.Test; @@ -48,7 +47,7 @@ public class ReplayingDecoderTest { assertNull(ch.readInbound()); } - private static final class LineDecoder extends ReplayingDecoder { + private static final class LineDecoder extends ReplayingDecoder { LineDecoder() { } diff --git a/common/src/main/java/io/netty/util/VoidEnum.java b/common/src/main/java/io/netty/util/VoidEnum.java deleted file mode 100644 index e851b3551e..0000000000 --- a/common/src/main/java/io/netty/util/VoidEnum.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.util; - - -/** - * A place holder {@link Enum} which has no constant. - */ -public enum VoidEnum { - // No state is defined. -} diff --git a/transport/src/main/java/io/netty/channel/socket/aio/AioSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/aio/AioSocketChannel.java index 42aae74c00..431b9b8d9a 100644 --- a/transport/src/main/java/io/netty/channel/socket/aio/AioSocketChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/aio/AioSocketChannel.java @@ -153,22 +153,24 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne @Override protected void doFlushByteBuffer(ByteBuf buf) throws Exception { - if (!buf.readable()) { - notifyFlushFutures(); + if (flushing) { return; } - if (!flushing) { - flushing = true; + flushing = true; + if (buf.readable()) { buf.discardReadBytes(); javaChannel().write(buf.nioBuffer(), this, WRITE_HANDLER); + } else { + notifyFlushFutures(); + flushing = false; } } private void beginRead() { ByteBuf byteBuf = pipeline().inboundByteBuffer(); if (!byteBuf.readable()) { - byteBuf.clear(); + byteBuf.discardReadBytes(); } else { expandReadBuffer(byteBuf); }