[#1907] LengthFieldPrepender should better extend MessageToMessageEncoder for less memory copies
This commit is contained in:
parent
16bf687aec
commit
42cce12498
@ -19,6 +19,8 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* An encoder that prepends the length of the message. The length value is
|
||||
@ -47,7 +49,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
* </pre>
|
||||
*/
|
||||
@Sharable
|
||||
public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
public class LengthFieldPrepender extends MessageToMessageEncoder<ByteBuf> {
|
||||
|
||||
private final int lengthFieldLength;
|
||||
private final boolean lengthIncludesLengthFieldLength;
|
||||
@ -128,7 +130,7 @@ public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
|
||||
int length = msg.readableBytes() + lengthAdjustment;
|
||||
if (lengthIncludesLengthFieldLength) {
|
||||
length += lengthFieldLength;
|
||||
@ -145,32 +147,31 @@ public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
throw new IllegalArgumentException(
|
||||
"length does not fit into a byte: " + length);
|
||||
}
|
||||
out.writeByte((byte) length);
|
||||
out.add(ctx.alloc().buffer(1).writeByte((byte) length));
|
||||
break;
|
||||
case 2:
|
||||
if (length >= 65536) {
|
||||
throw new IllegalArgumentException(
|
||||
"length does not fit into a short integer: " + length);
|
||||
}
|
||||
out.writeShort((short) length);
|
||||
out.add(ctx.alloc().buffer(2).writeShort((short) length));
|
||||
break;
|
||||
case 3:
|
||||
if (length >= 16777216) {
|
||||
throw new IllegalArgumentException(
|
||||
"length does not fit into a medium integer: " + length);
|
||||
}
|
||||
out.writeMedium(length);
|
||||
out.add(ctx.alloc().buffer(3).writeMedium(length));
|
||||
break;
|
||||
case 4:
|
||||
out.writeInt(length);
|
||||
out.add(ctx.alloc().buffer(4).writeInt(length));
|
||||
break;
|
||||
case 8:
|
||||
out.writeLong(length);
|
||||
out.add(ctx.alloc().buffer(8).writeLong(length));
|
||||
break;
|
||||
default:
|
||||
throw new Error("should not reach here");
|
||||
}
|
||||
|
||||
out.writeBytes(msg, msg.readerIndex(), msg.readableBytes());
|
||||
out.add(msg.retain());
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class LengthFieldPrependerTest {
|
||||
@ -40,8 +39,13 @@ public class LengthFieldPrependerTest {
|
||||
public void testPrependLength() throws Exception {
|
||||
final EmbeddedChannel ch = new EmbeddedChannel(new LengthFieldPrepender(4));
|
||||
ch.writeOutbound(msg);
|
||||
final ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertThat(buf, is(wrappedBuffer(new byte[]{0, 0, 0, 1, 'A'})));
|
||||
ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertEquals(4, buf.readableBytes());
|
||||
assertEquals(msg.readableBytes(), buf.readInt());
|
||||
buf.release();
|
||||
|
||||
buf = (ByteBuf) ch.readOutbound();
|
||||
assertSame(buf, msg);
|
||||
buf.release();
|
||||
}
|
||||
|
||||
@ -49,8 +53,13 @@ public class LengthFieldPrependerTest {
|
||||
public void testPrependLengthIncludesLengthFieldLength() throws Exception {
|
||||
final EmbeddedChannel ch = new EmbeddedChannel(new LengthFieldPrepender(4, true));
|
||||
ch.writeOutbound(msg);
|
||||
final ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertThat(buf, is(wrappedBuffer(new byte[]{0, 0, 0, 5, 'A'})));
|
||||
ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertEquals(4, buf.readableBytes());
|
||||
assertEquals(5, buf.readInt());
|
||||
buf.release();
|
||||
|
||||
buf = (ByteBuf) ch.readOutbound();
|
||||
assertSame(buf, msg);
|
||||
buf.release();
|
||||
}
|
||||
|
||||
@ -58,8 +67,13 @@ public class LengthFieldPrependerTest {
|
||||
public void testPrependAdjustedLength() throws Exception {
|
||||
final EmbeddedChannel ch = new EmbeddedChannel(new LengthFieldPrepender(4, -1));
|
||||
ch.writeOutbound(msg);
|
||||
final ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertThat(buf, is(wrappedBuffer(new byte[]{0, 0, 0, 0, 'A'})));
|
||||
ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertEquals(4, buf.readableBytes());
|
||||
assertEquals(msg.readableBytes() - 1, buf.readInt());
|
||||
buf.release();
|
||||
|
||||
buf = (ByteBuf) ch.readOutbound();
|
||||
assertSame(buf, msg);
|
||||
buf.release();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user