diff --git a/src/main/java/org/jboss/netty/channel/ChannelEvent.java b/src/main/java/org/jboss/netty/channel/ChannelEvent.java index ca566d5022..2ab0b0b851 100644 --- a/src/main/java/org/jboss/netty/channel/ChannelEvent.java +++ b/src/main/java/org/jboss/netty/channel/ChannelEvent.java @@ -71,6 +71,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannel; * {@code "channelOpen"} * {@link ChannelStateEvent}
(state = {@link ChannelState#OPEN OPEN}, value = {@code true}) * a {@link Channel} is open, but not bound nor connected + * Be aware that this event is fired from within the Boss-Thread so you should not execute any heavy operation in there as it will block the dispatching to other workers! * * * {@code "channelClosed"} @@ -81,6 +82,7 @@ import org.jboss.netty.channel.socket.ServerSocketChannel; * {@code "channelBound"} * {@link ChannelStateEvent}
(state = {@link ChannelState#BOUND BOUND}, value = {@link SocketAddress}) * a {@link Channel} is open and bound to a local address, but not connected + * Be aware that this event is fired from within the Boss-Thread so you should not execute any heavy operation in there as it will block the dispatching to other workers! * * * {@code "channelUnbound"} diff --git a/src/main/java/org/jboss/netty/channel/SimpleChannelUpstreamHandler.java b/src/main/java/org/jboss/netty/channel/SimpleChannelUpstreamHandler.java index 189269c46f..c942b8e7d7 100644 --- a/src/main/java/org/jboss/netty/channel/SimpleChannelUpstreamHandler.java +++ b/src/main/java/org/jboss/netty/channel/SimpleChannelUpstreamHandler.java @@ -151,7 +151,9 @@ public class SimpleChannelUpstreamHandler implements ChannelUpstreamHandler { /** * Invoked when a {@link Channel} is open, but not bound nor connected. - */ + *
+ * Be aware that this event is fired from within the Boss-Thread so you should not execute any heavy operation in there as it will block the dispatching to other workers! + */ public void channelOpen( ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { ctx.sendUpstream(e); @@ -160,6 +162,8 @@ public class SimpleChannelUpstreamHandler implements ChannelUpstreamHandler { /** * Invoked when a {@link Channel} is open and bound to a local address, * but not connected. + *
+ * Be aware that this event is fired from within the Boss-Thread so you should not execute any heavy operation in there as it will block the dispatching to other workers! */ public void channelBound( ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/NioAcceptedSocketChannel.java b/src/main/java/org/jboss/netty/channel/socket/nio/NioAcceptedSocketChannel.java index ad7571ba8a..dff5309d8e 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/NioAcceptedSocketChannel.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/NioAcceptedSocketChannel.java @@ -48,6 +48,5 @@ final class NioAcceptedSocketChannel extends NioSocketChannel { setConnected(); fireChannelOpen(this); fireChannelBound(this, getLocalAddress()); - fireChannelConnected(this, getRemoteAddress()); } } diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java b/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java index 0bf1dc51c9..2fedb57256 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java @@ -782,6 +782,11 @@ class NioWorker implements Runnable { } fireChannelConnected(channel, remoteAddress); } + + // Handle the channelConnected in the worker thread + if (channel instanceof NioAcceptedSocketChannel) { + fireChannelConnected(channel, channel.getRemoteAddress()); + } } } } diff --git a/src/main/java/org/jboss/netty/channel/socket/nio/SocketSendBufferPool.java b/src/main/java/org/jboss/netty/channel/socket/nio/SocketSendBufferPool.java index ba1ab5de83..4c29ee79b3 100644 --- a/src/main/java/org/jboss/netty/channel/socket/nio/SocketSendBufferPool.java +++ b/src/main/java/org/jboss/netty/channel/socket/nio/SocketSendBufferPool.java @@ -306,7 +306,8 @@ final class SocketSendBufferPool { @Override public void release() { - // Unpooled. + // Make sure the FileRegion resource are released otherwise it may cause a FD leak or something similar + file.releaseExternalResources(); } } diff --git a/src/main/java/org/jboss/netty/channel/socket/oio/OioAcceptedSocketChannel.java b/src/main/java/org/jboss/netty/channel/socket/oio/OioAcceptedSocketChannel.java index d42cb6f0e7..16781e5c1c 100644 --- a/src/main/java/org/jboss/netty/channel/socket/oio/OioAcceptedSocketChannel.java +++ b/src/main/java/org/jboss/netty/channel/socket/oio/OioAcceptedSocketChannel.java @@ -63,7 +63,6 @@ class OioAcceptedSocketChannel extends OioSocketChannel { fireChannelOpen(this); fireChannelBound(this, getLocalAddress()); - fireChannelConnected(this, getRemoteAddress()); } @Override diff --git a/src/main/java/org/jboss/netty/channel/socket/oio/OioWorker.java b/src/main/java/org/jboss/netty/channel/socket/oio/OioWorker.java index 945927f178..82fac7509d 100644 --- a/src/main/java/org/jboss/netty/channel/socket/oio/OioWorker.java +++ b/src/main/java/org/jboss/netty/channel/socket/oio/OioWorker.java @@ -20,12 +20,15 @@ import static org.jboss.netty.channel.Channels.*; import java.io.OutputStream; import java.io.PushbackInputStream; import java.net.SocketException; +import java.nio.channels.Channels; import java.nio.channels.ClosedChannelException; +import java.nio.channels.WritableByteChannel; import java.util.regex.Pattern; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.FileRegion; /** * @@ -50,8 +53,13 @@ class OioWorker implements Runnable { public void run() { channel.workerThread = Thread.currentThread(); final PushbackInputStream in = channel.getInputStream(); + boolean fireOpen = channel instanceof OioAcceptedSocketChannel; while (channel.isOpen()) { + if (fireOpen) { + fireOpen = false; + fireChannelConnected(channel, channel.getRemoteAddress()); + } synchronized (channel.interestOpsLock) { while (!channel.isReadable()) { try { @@ -114,13 +122,39 @@ class OioWorker implements Runnable { } try { - ChannelBuffer a = (ChannelBuffer) message; - int length = a.readableBytes(); - synchronized (out) { - a.getBytes(a.readerIndex(), out, length); + int length = 0; + + // Add support to write a FileRegion. This in fact will not give any performance gain but at least it not fail and + // we did the best to emulate it + if (message instanceof FileRegion) { + FileRegion fr = (FileRegion) message; + try { + synchronized (out) { + WritableByteChannel bchannel = Channels.newChannel(out); + + long i = 0; + while ((i = fr.transferTo(bchannel, length)) > 0) { + length += i; + if (length >= fr.getCount()) { + break; + } + } + } + } finally { + fr.releaseExternalResources(); + + } + } else { + ChannelBuffer a = (ChannelBuffer) message; + length = a.readableBytes(); + synchronized (out) { + a.getBytes(a.readerIndex(), out, length); + } } + fireWriteComplete(channel, length); future.setSuccess(); + } catch (Throwable t) { // Convert 'SocketException: Socket closed' to // ClosedChannelException.