* Fixed an infiniloop in NioDatagramWorker which is triggered when a user writes an empty buffer.

* Reduced system calls on empty buffer
This commit is contained in:
Trustin Lee 2010-06-07 02:11:04 +00:00
parent c032708ed7
commit 5097009f8c
2 changed files with 44 additions and 2 deletions

View File

@ -547,7 +547,7 @@ class NioDatagramWorker implements Runnable {
} }
} }
if (localWrittenBytes > 0) { if (localWrittenBytes > 0 || buf.finished()) {
// Successful write - proceed to the next message. // Successful write - proceed to the next message.
buf.release(); buf.release();
ChannelFuture future = evt.getFuture(); ChannelFuture future = evt.getFuture();

View File

@ -32,6 +32,8 @@ import org.jboss.netty.channel.FileRegion;
*/ */
final class SocketSendBufferPool { final class SocketSendBufferPool {
private static final SendBuffer EMPTY_BUFFER = new EmptySendBuffer();
private static final int DEFAULT_PREALLOCATION_SIZE = 65536; private static final int DEFAULT_PREALLOCATION_SIZE = 65536;
private static final int ALIGN_SHIFT = 4; private static final int ALIGN_SHIFT = 4;
private static final int ALIGN_MASK = 15; private static final int ALIGN_MASK = 15;
@ -59,10 +61,18 @@ final class SocketSendBufferPool {
} }
private final SendBuffer acquire(FileRegion src) { private final SendBuffer acquire(FileRegion src) {
if (src.getCount() == 0) {
return EMPTY_BUFFER;
}
return new FileSendBuffer(src); return new FileSendBuffer(src);
} }
private final SendBuffer acquire(ChannelBuffer src) { private final SendBuffer acquire(ChannelBuffer src) {
final int size = src.readableBytes();
if (size == 0) {
return EMPTY_BUFFER;
}
if (src.isDirect()) { if (src.isDirect()) {
return new UnpooledSendBuffer(src.toByteBuffer()); return new UnpooledSendBuffer(src.toByteBuffer());
} }
@ -70,7 +80,6 @@ final class SocketSendBufferPool {
return new UnpooledSendBuffer(src.toByteBuffer()); return new UnpooledSendBuffer(src.toByteBuffer());
} }
final int size = src.readableBytes();
Preallocation current = this.current; Preallocation current = this.current;
ByteBuffer buffer = current.buffer; ByteBuffer buffer = current.buffer;
int remaining = buffer.remaining(); int remaining = buffer.remaining();
@ -172,6 +181,7 @@ final class SocketSendBufferPool {
} }
class UnpooledSendBuffer implements SendBuffer { class UnpooledSendBuffer implements SendBuffer {
final ByteBuffer buffer; final ByteBuffer buffer;
final int initialPos; final int initialPos;
@ -206,6 +216,7 @@ final class SocketSendBufferPool {
} }
final class PooledSendBuffer implements SendBuffer { final class PooledSendBuffer implements SendBuffer {
private final Preallocation parent; private final Preallocation parent;
final ByteBuffer buffer; final ByteBuffer buffer;
final int initialPos; final int initialPos;
@ -284,4 +295,35 @@ final class SocketSendBufferPool {
// Unpooled. // Unpooled.
} }
} }
static final class EmptySendBuffer implements SendBuffer {
EmptySendBuffer() {
super();
}
public final boolean finished() {
return true;
}
public final long writtenBytes() {
return 0;
}
public final long totalBytes() {
return 0;
}
public final long transferTo(WritableByteChannel ch) throws IOException {
return 0;
}
public final long transferTo(DatagramChannel ch, SocketAddress raddr) throws IOException {
return 0;
}
public void release() {
// Unpooled.
}
}
} }