[#2680] ChannelOutboundBuffer.nioBuffers() should always return non-null array as stated in javadocs

Motivation:

At the moment ChannelOutboundBuffer.nioBuffers() returns null if something is contained in the ChannelOutboundBuffer which is not a ByteBuf. This is a problem for two reasons:
 1 - In the javadocs we state that it will never return null
 2 - We may do a not optimal write as there may be things that could be written via gathering writes

Modifications:

Change ChannelOutboundBuffer.nioBuffers() to never return null but have it contain all ByteBuffer that were found before the non ByteBuf. This way we can do a gathering write and also conform to the javadocs.

Result:

Better speed and also correct implementation in terms of the api.
This commit is contained in:
Norman Maurer 2014-07-20 19:13:48 +02:00
parent dd026eb60a
commit cb2246ee07
3 changed files with 14 additions and 16 deletions

View File

@ -63,7 +63,7 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
private volatile boolean inputShutdown;
private volatile boolean outputShutdown;
EpollSocketChannel(Channel parent, int fd) throws IOException {
EpollSocketChannel(Channel parent, int fd) {
super(parent, fd, Native.EPOLLIN, true);
config = new EpollSocketChannelConfig(this);
// Directly cache the remote and local addresses
@ -135,16 +135,11 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
return done;
} else {
ByteBuffer[] nioBuffers = buf.nioBuffers();
return writeBytesMultiple0(in, 1, nioBuffers, nioBuffers.length, readableBytes);
return writeBytesMultiple(in, 1, nioBuffers, nioBuffers.length, readableBytes);
}
}
private boolean writeBytesMultiple(
ChannelOutboundBuffer in, int msgCount, ByteBuffer[] nioBuffers) throws IOException {
return writeBytesMultiple0(in, msgCount, nioBuffers, in.nioBufferCount(), in.nioBufferSize());
}
private boolean writeBytesMultiple0(
ChannelOutboundBuffer in, int msgCount, ByteBuffer[] nioBuffers,
int nioBufferCnt, long expectedWrittenBytes) throws IOException {
boolean done = false;
@ -189,7 +184,7 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
return done;
}
private void updateOutboundBuffer(ChannelOutboundBuffer in, long writtenBytes, int msgCount,
private static void updateOutboundBuffer(ChannelOutboundBuffer in, long writtenBytes, int msgCount,
boolean done) {
if (done) {
// Release all buffers
@ -274,8 +269,9 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
if (msgCount > 1) {
// Ensure the pending writes are made of ByteBufs only.
ByteBuffer[] nioBuffers = in.nioBuffers();
if (nioBuffers != null) {
if (!writeBytesMultiple(in, msgCount, nioBuffers)) {
int nioBufferCount = in.nioBufferCount();
if (nioBufferCount != 0) {
if (!writeBytesMultiple(in, msgCount, nioBuffers, nioBufferCount, in.nioBufferSize())) {
// was not able to write everything so break here we will get notified later again once
// the network stack can handle more writes.
break;

View File

@ -388,9 +388,9 @@ public final class ChannelOutboundBuffer {
int i = flushed;
while (i != unflushed && (m = buffer[i].msg) != null) {
if (!(m instanceof ByteBuf)) {
this.nioBufferCount = 0;
this.nioBufferSize = 0;
return null;
// Just break out of the loop as we can still use gathering writes for the buffers that we
// found by now.
break;
}
Entry entry = buffer[i];

View File

@ -249,12 +249,14 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
// Ensure the pending writes are made of ByteBufs only.
ByteBuffer[] nioBuffers = in.nioBuffers();
if (nioBuffers == null) {
int nioBufferCnt = in.nioBufferCount();
if (nioBufferCnt == 0) {
// We have something else beside ByteBuffers to write so fallback to normal writes.
super.doWrite(in);
return;
break;
}
int nioBufferCnt = in.nioBufferCount();
long expectedWrittenBytes = in.nioBufferSize();
final SocketChannel ch = javaChannel();