From e2de807fb034054484b027c3f487516a90ddafe6 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 5 Nov 2013 17:23:22 +0900 Subject: [PATCH] Add AUTO_CLOSE option - Fixes #1952 - If AUTO_CLOSE is turned on, Netty will close the channel immediately and automatically on write failure. The default is false. --- .../rxtx/DefaultRxtxChannelConfig.java | 6 ++++++ .../netty/channel/rxtx/RxtxChannelConfig.java | 3 +++ .../sctp/DefaultSctpChannelConfig.java | 6 ++++++ .../sctp/DefaultSctpServerChannelConfig.java | 6 ++++++ .../netty/channel/sctp/SctpChannelConfig.java | 3 +++ .../channel/sctp/SctpServerChannelConfig.java | 3 +++ .../channel/udt/DefaultUdtChannelConfig.java | 6 ++++++ .../udt/DefaultUdtServerChannelConfig.java | 6 ++++++ .../netty/channel/udt/UdtChannelConfig.java | 3 +++ .../channel/udt/UdtServerChannelConfig.java | 3 +++ .../io/netty/channel/AbstractChannel.java | 2 +- .../java/io/netty/channel/ChannelConfig.java | 12 ++++++++++++ .../java/io/netty/channel/ChannelOption.java | 6 ++++++ .../netty/channel/DefaultChannelConfig.java | 19 ++++++++++++++++++- .../channel/nio/AbstractNioByteChannel.java | 1 + .../channel/socket/DatagramChannelConfig.java | 3 +++ .../socket/DefaultDatagramChannelConfig.java | 6 ++++++ .../socket/DefaultSocketChannelConfig.java | 6 ++++++ .../channel/socket/SocketChannelConfig.java | 3 +++ .../DefaultOioServerSocketChannelConfig.java | 6 ++++++ .../oio/DefaultOioSocketChannelConfig.java | 7 ++++++- .../oio/OioServerSocketChannelConfig.java | 3 +++ .../socket/oio/OioSocketChannelConfig.java | 3 +++ 23 files changed, 119 insertions(+), 3 deletions(-) diff --git a/transport-rxtx/src/main/java/io/netty/channel/rxtx/DefaultRxtxChannelConfig.java b/transport-rxtx/src/main/java/io/netty/channel/rxtx/DefaultRxtxChannelConfig.java index 608af1d60c..a635505b9a 100644 --- a/transport-rxtx/src/main/java/io/netty/channel/rxtx/DefaultRxtxChannelConfig.java +++ b/transport-rxtx/src/main/java/io/netty/channel/rxtx/DefaultRxtxChannelConfig.java @@ -234,6 +234,12 @@ final class DefaultRxtxChannelConfig extends DefaultChannelConfig implements Rxt return this; } + @Override + public RxtxChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public RxtxChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport-rxtx/src/main/java/io/netty/channel/rxtx/RxtxChannelConfig.java b/transport-rxtx/src/main/java/io/netty/channel/rxtx/RxtxChannelConfig.java index 9321198a25..4a63c845e5 100644 --- a/transport-rxtx/src/main/java/io/netty/channel/rxtx/RxtxChannelConfig.java +++ b/transport-rxtx/src/main/java/io/netty/channel/rxtx/RxtxChannelConfig.java @@ -288,6 +288,9 @@ public interface RxtxChannelConfig extends ChannelConfig { @Override RxtxChannelConfig setAutoRead(boolean autoRead); + @Override + RxtxChannelConfig setAutoClose(boolean autoClose); + @Override RxtxChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java index 79f540a833..9bf6e54c6a 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java @@ -209,6 +209,12 @@ public class DefaultSctpChannelConfig extends DefaultChannelConfig implements Sc return this; } + @Override + public SctpChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpServerChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpServerChannelConfig.java index cc13cc9033..aadef72d2d 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpServerChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpServerChannelConfig.java @@ -192,6 +192,12 @@ public class DefaultSctpServerChannelConfig extends DefaultChannelConfig impleme return this; } + @Override + public SctpServerChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public SctpServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java index 8aeb66cc91..5056bfb3f8 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java @@ -115,6 +115,9 @@ public interface SctpChannelConfig extends ChannelConfig { @Override SctpChannelConfig setAutoRead(boolean autoRead); + @Override + SctpChannelConfig setAutoClose(boolean autoClose); + @Override SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerChannelConfig.java index 3375eb1aa3..3120ad3a56 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerChannelConfig.java @@ -110,6 +110,9 @@ public interface SctpServerChannelConfig extends ChannelConfig { @Override SctpServerChannelConfig setAutoRead(boolean autoRead); + @Override + SctpServerChannelConfig setAutoClose(boolean autoClose); + @Override SctpServerChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); diff --git a/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtChannelConfig.java b/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtChannelConfig.java index 33ff685be4..05ca40cc6d 100644 --- a/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtChannelConfig.java +++ b/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtChannelConfig.java @@ -270,6 +270,12 @@ public class DefaultUdtChannelConfig extends DefaultChannelConfig implements return this; } + @Override + public UdtChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public UdtChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); diff --git a/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtServerChannelConfig.java b/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtServerChannelConfig.java index 9315c2acf0..b8f65a0cb8 100644 --- a/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtServerChannelConfig.java +++ b/transport-udt/src/main/java/io/netty/channel/udt/DefaultUdtServerChannelConfig.java @@ -172,6 +172,12 @@ public class DefaultUdtServerChannelConfig extends DefaultUdtChannelConfig return this; } + @Override + public UdtServerChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public UdtServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { super.setWriteBufferLowWaterMark(writeBufferLowWaterMark); diff --git a/transport-udt/src/main/java/io/netty/channel/udt/UdtChannelConfig.java b/transport-udt/src/main/java/io/netty/channel/udt/UdtChannelConfig.java index 00c3ef5b21..99acf4ad67 100644 --- a/transport-udt/src/main/java/io/netty/channel/udt/UdtChannelConfig.java +++ b/transport-udt/src/main/java/io/netty/channel/udt/UdtChannelConfig.java @@ -130,6 +130,9 @@ public interface UdtChannelConfig extends ChannelConfig { @Override UdtChannelConfig setAutoRead(boolean autoRead); + @Override + UdtChannelConfig setAutoClose(boolean autoClose); + @Override UdtChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); diff --git a/transport-udt/src/main/java/io/netty/channel/udt/UdtServerChannelConfig.java b/transport-udt/src/main/java/io/netty/channel/udt/UdtServerChannelConfig.java index e7fbf8cc81..541ba12694 100644 --- a/transport-udt/src/main/java/io/netty/channel/udt/UdtServerChannelConfig.java +++ b/transport-udt/src/main/java/io/netty/channel/udt/UdtServerChannelConfig.java @@ -64,6 +64,9 @@ public interface UdtServerChannelConfig extends UdtChannelConfig { @Override UdtServerChannelConfig setAutoRead(boolean autoRead); + @Override + UdtServerChannelConfig setAutoClose(boolean autoClose); + @Override UdtServerChannelConfig setProtocolReceiveBufferSize(int size); diff --git a/transport/src/main/java/io/netty/channel/AbstractChannel.java b/transport/src/main/java/io/netty/channel/AbstractChannel.java index b8a20f9282..9c67201285 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannel.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannel.java @@ -638,7 +638,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha doWrite(outboundBuffer); } catch (Throwable t) { outboundBuffer.failFlushed(t); - if (t instanceof IOException) { + if (t instanceof IOException && config().isAutoClose()) { close(voidPromise()); } } finally { diff --git a/transport/src/main/java/io/netty/channel/ChannelConfig.java b/transport/src/main/java/io/netty/channel/ChannelConfig.java index 0e465bd592..73889be6ea 100644 --- a/transport/src/main/java/io/netty/channel/ChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/ChannelConfig.java @@ -188,6 +188,18 @@ public interface ChannelConfig { */ ChannelConfig setAutoRead(boolean autoRead); + /** + * Returns {@code true} if and only if the {@link Channel} will be closed automatically and immediately on + * write failure. The default is {@code false}. + */ + boolean isAutoClose(); + + /** + * Sets whether the {@link Channel} should be closed automatically and immediately on write faillure. + * The default is {@code false}. + */ + ChannelConfig setAutoClose(boolean autoClose); + /** * Returns the high water mark of the write buffer. If the number of bytes * queued in the write buffer exceeds this value, {@link Channel#isWritable()} diff --git a/transport/src/main/java/io/netty/channel/ChannelOption.java b/transport/src/main/java/io/netty/channel/ChannelOption.java index 4e47b2ce1d..bbbd46e87c 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOption.java +++ b/transport/src/main/java/io/netty/channel/ChannelOption.java @@ -68,6 +68,12 @@ public final class ChannelOption extends AbstractConstant> { public static final ChannelOption ALLOW_HALF_CLOSURE = valueOf("ALLOW_HALF_CLOSURE"); public static final ChannelOption AUTO_READ = valueOf("AUTO_READ"); + /** + * {@code true} if and only if the {@link Channel} is closed automatically and immediately on write failure. + * The default is {@code false}. + */ + public static final ChannelOption AUTO_CLOSE = valueOf("AUTO_CLOSE"); + public static final ChannelOption SO_BROADCAST = valueOf("SO_BROADCAST"); public static final ChannelOption SO_KEEPALIVE = valueOf("SO_KEEPALIVE"); public static final ChannelOption SO_SNDBUF = valueOf("SO_SNDBUF"); diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelConfig.java b/transport/src/main/java/io/netty/channel/DefaultChannelConfig.java index ac90d70a8d..9c9db2b986 100644 --- a/transport/src/main/java/io/netty/channel/DefaultChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelConfig.java @@ -46,6 +46,7 @@ public class DefaultChannelConfig implements ChannelConfig { private volatile int maxMessagesPerRead; private volatile int writeSpinCount = 16; private volatile boolean autoRead = true; + private volatile boolean autoClose; private volatile int writeBufferHighWaterMark = 64 * 1024; private volatile int writeBufferLowWaterMark = 32 * 1024; @@ -68,7 +69,7 @@ public class DefaultChannelConfig implements ChannelConfig { return getOptions( null, CONNECT_TIMEOUT_MILLIS, MAX_MESSAGES_PER_READ, WRITE_SPIN_COUNT, - ALLOCATOR, AUTO_READ, RCVBUF_ALLOCATOR, WRITE_BUFFER_HIGH_WATER_MARK, + ALLOCATOR, AUTO_READ, AUTO_CLOSE, RCVBUF_ALLOCATOR, WRITE_BUFFER_HIGH_WATER_MARK, WRITE_BUFFER_LOW_WATER_MARK, MESSAGE_SIZE_ESTIMATOR); } @@ -125,6 +126,9 @@ public class DefaultChannelConfig implements ChannelConfig { if (option == AUTO_READ) { return (T) Boolean.valueOf(isAutoRead()); } + if (option == AUTO_CLOSE) { + return (T) Boolean.valueOf(isAutoClose()); + } if (option == WRITE_BUFFER_HIGH_WATER_MARK) { return (T) Integer.valueOf(getWriteBufferHighWaterMark()); } @@ -153,6 +157,8 @@ public class DefaultChannelConfig implements ChannelConfig { setRecvByteBufAllocator((RecvByteBufAllocator) value); } else if (option == AUTO_READ) { setAutoRead((Boolean) value); + } else if (option == AUTO_CLOSE) { + setAutoClose((Boolean) value); } else if (option == WRITE_BUFFER_HIGH_WATER_MARK) { setWriteBufferHighWaterMark((Integer) value); } else if (option == WRITE_BUFFER_LOW_WATER_MARK) { @@ -260,6 +266,17 @@ public class DefaultChannelConfig implements ChannelConfig { return this; } + @Override + public boolean isAutoClose() { + return autoClose; + } + + @Override + public ChannelConfig setAutoClose(boolean autoClose) { + this.autoClose = autoClose; + return this; + } + @Override public int getWriteBufferHighWaterMark() { return writeBufferHighWaterMark; diff --git a/transport/src/main/java/io/netty/channel/nio/AbstractNioByteChannel.java b/transport/src/main/java/io/netty/channel/nio/AbstractNioByteChannel.java index a9577d82bf..05f0a06f6b 100644 --- a/transport/src/main/java/io/netty/channel/nio/AbstractNioByteChannel.java +++ b/transport/src/main/java/io/netty/channel/nio/AbstractNioByteChannel.java @@ -87,6 +87,7 @@ public abstract class AbstractNioByteChannel extends AbstractNioChannel { } } pipeline.fireChannelReadComplete(); + pipeline.fireExceptionCaught(cause); if (close || cause instanceof IOException) { closeOnRead(pipeline); } diff --git a/transport/src/main/java/io/netty/channel/socket/DatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/DatagramChannelConfig.java index 478819461d..54b29d66d7 100644 --- a/transport/src/main/java/io/netty/channel/socket/DatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/DatagramChannelConfig.java @@ -174,6 +174,9 @@ public interface DatagramChannelConfig extends ChannelConfig { @Override DatagramChannelConfig setAutoRead(boolean autoRead); + @Override + DatagramChannelConfig setAutoClose(boolean autoClose); + @Override DatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); } diff --git a/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java index 269446159f..751ad6ec48 100644 --- a/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java @@ -395,6 +395,12 @@ public class DefaultDatagramChannelConfig extends DefaultChannelConfig implement return this; } + @Override + public DatagramChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public DatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport/src/main/java/io/netty/channel/socket/DefaultSocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/DefaultSocketChannelConfig.java index 88f86162ef..ee17cb1e21 100644 --- a/transport/src/main/java/io/netty/channel/socket/DefaultSocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/DefaultSocketChannelConfig.java @@ -315,6 +315,12 @@ public class DefaultSocketChannelConfig extends DefaultChannelConfig return this; } + @Override + public SocketChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public SocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport/src/main/java/io/netty/channel/socket/SocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/SocketChannelConfig.java index 071832f170..2140f8634b 100644 --- a/transport/src/main/java/io/netty/channel/socket/SocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/SocketChannelConfig.java @@ -175,6 +175,9 @@ public interface SocketChannelConfig extends ChannelConfig { @Override SocketChannelConfig setAutoRead(boolean autoRead); + @Override + SocketChannelConfig setAutoClose(boolean autoClose); + @Override SocketChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator); } diff --git a/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java index b62540c2db..ab2fa06ca7 100644 --- a/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioServerSocketChannelConfig.java @@ -145,6 +145,12 @@ public class DefaultOioServerSocketChannelConfig extends DefaultServerSocketChan return this; } + @Override + public OioServerSocketChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public OioServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java index b4ec89bed7..ac9fdf72cf 100644 --- a/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/DefaultOioSocketChannelConfig.java @@ -22,7 +22,6 @@ import io.netty.channel.MessageSizeEstimator; import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.socket.DefaultSocketChannelConfig; import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.SocketChannelConfig; import java.io.IOException; import java.net.Socket; @@ -174,6 +173,12 @@ public class DefaultOioSocketChannelConfig extends DefaultSocketChannelConfig im return this; } + @Override + public OioSocketChannelConfig setAutoClose(boolean autoClose) { + super.setAutoClose(autoClose); + return this; + } + @Override public OioSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { super.setWriteBufferHighWaterMark(writeBufferHighWaterMark); diff --git a/transport/src/main/java/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java index 697c6d2da3..5883eeb878 100644 --- a/transport/src/main/java/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/OioServerSocketChannelConfig.java @@ -81,6 +81,9 @@ public interface OioServerSocketChannelConfig extends ServerSocketChannelConfig @Override OioServerSocketChannelConfig setAutoRead(boolean autoRead); + @Override + OioServerSocketChannelConfig setAutoClose(boolean autoClose); + @Override OioServerSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark); diff --git a/transport/src/main/java/io/netty/channel/socket/oio/OioSocketChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/oio/OioSocketChannelConfig.java index 8bea404a51..e12fe64830 100644 --- a/transport/src/main/java/io/netty/channel/socket/oio/OioSocketChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/oio/OioSocketChannelConfig.java @@ -96,6 +96,9 @@ public interface OioSocketChannelConfig extends SocketChannelConfig { @Override OioSocketChannelConfig setAutoRead(boolean autoRead); + @Override + OioSocketChannelConfig setAutoClose(boolean autoClose); + @Override OioSocketChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark);