[#1880] Use ByteBufAllocator when read bytes into new chunks
This commit is contained in:
parent
5a59cb9fb7
commit
1ecd1e01a5
@ -257,6 +257,23 @@ public final class ByteBufUtil {
|
||||
return Long.reverseBytes(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the given amount of bytes into a new {@link ByteBuf} that is allocated from the {@link ByteBufAllocator}.
|
||||
*/
|
||||
public static ByteBuf readBytes(ByteBufAllocator alloc, ByteBuf buffer, int length) {
|
||||
boolean release = true;
|
||||
ByteBuf dst = alloc.buffer(length);
|
||||
try {
|
||||
buffer.readBytes(dst);
|
||||
release = false;
|
||||
return dst;
|
||||
} finally {
|
||||
if (release) {
|
||||
dst.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int firstIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
|
||||
fromIndex = Math.max(fromIndex, 0);
|
||||
if (fromIndex >= toIndex || buffer.capacity() == 0) {
|
||||
|
@ -25,6 +25,8 @@ import io.netty.handler.codec.TooLongFrameException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.buffer.ByteBufUtil.readBytes;
|
||||
|
||||
/**
|
||||
* Decodes {@link ByteBuf}s into {@link HttpMessage}s and
|
||||
* {@link HttpContent}s.
|
||||
@ -278,7 +280,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
toRead = maxChunkSize;
|
||||
}
|
||||
// TODO: Slice
|
||||
out.add(new DefaultHttpContent(buffer.readBytes(toRead)));
|
||||
out.add(new DefaultHttpContent(readBytes(ctx.alloc(), buffer, toRead)));
|
||||
return;
|
||||
}
|
||||
case READ_VARIABLE_LENGTH_CONTENT_AS_CHUNKS: {
|
||||
@ -292,7 +294,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
toRead = maxChunkSize;
|
||||
}
|
||||
// TODO: Slice
|
||||
ByteBuf content = buffer.readBytes(toRead);
|
||||
ByteBuf content = readBytes(ctx.alloc(), buffer, toRead);
|
||||
if (!buffer.isReadable()) {
|
||||
out.add(new DefaultLastHttpContent(content));
|
||||
reset();
|
||||
@ -302,7 +304,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
return;
|
||||
}
|
||||
case READ_FIXED_LENGTH_CONTENT: {
|
||||
readFixedLengthContent(buffer, contentLength(), out);
|
||||
readFixedLengthContent(ctx, buffer, contentLength(), out);
|
||||
return;
|
||||
}
|
||||
case READ_FIXED_LENGTH_CONTENT_AS_CHUNKS: {
|
||||
@ -326,7 +328,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
toRead = (int) chunkSize;
|
||||
}
|
||||
// TODO: Slice
|
||||
ByteBuf content = buffer.readBytes(toRead);
|
||||
ByteBuf content = readBytes(ctx.alloc(), buffer, toRead);
|
||||
if (chunkSize > toRead) {
|
||||
chunkSize -= toRead;
|
||||
} else {
|
||||
@ -377,7 +379,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
return;
|
||||
}
|
||||
// TODO: Slice
|
||||
HttpContent chunk = new DefaultHttpContent(buffer.readBytes((int) chunkSize));
|
||||
HttpContent chunk = new DefaultHttpContent(readBytes(ctx.alloc(), buffer, (int) chunkSize));
|
||||
state = State.READ_CHUNK_DELIMITER;
|
||||
out.add(chunk);
|
||||
return;
|
||||
@ -405,7 +407,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
toRead = chunkSize;
|
||||
}
|
||||
|
||||
HttpContent chunk = new DefaultHttpContent(buffer.readBytes(toRead));
|
||||
HttpContent chunk = new DefaultHttpContent(readBytes(ctx.alloc(), buffer, toRead));
|
||||
if (chunkSize > toRead) {
|
||||
chunkSize -= toRead;
|
||||
} else {
|
||||
@ -500,7 +502,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
if (readable == 0) {
|
||||
out.add(LastHttpContent.EMPTY_LAST_CONTENT);
|
||||
} else {
|
||||
out.add(new DefaultLastHttpContent(in.readBytes(readable)));
|
||||
out.add(new DefaultLastHttpContent(readBytes(ctx.alloc(), in, readable)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -569,7 +571,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void readFixedLengthContent(ByteBuf buffer, long length, List<Object> out) {
|
||||
private void readFixedLengthContent(ChannelHandlerContext ctx, ByteBuf buffer, long length, List<Object> out) {
|
||||
assert length <= Integer.MAX_VALUE;
|
||||
|
||||
//we have a content-length so we just read the correct number of bytes
|
||||
@ -582,7 +584,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
|
||||
contentRead += toRead;
|
||||
// TODO: Slice
|
||||
ByteBuf buf = buffer.readBytes(toRead);
|
||||
ByteBuf buf = readBytes(ctx.alloc(), buffer, toRead);
|
||||
if (contentRead < length) {
|
||||
out.add(new DefaultHttpContent(buf));
|
||||
return;
|
||||
|
@ -82,10 +82,12 @@ public class HttpContentCompressorTest {
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk, is(instanceOf(HttpContent.class)));
|
||||
assertThat(chunk.content().isReadable(), is(true));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk, is(instanceOf(LastHttpContent.class)));
|
||||
assertThat(chunk.content().isReadable(), is(false));
|
||||
chunk.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
@ -67,6 +67,8 @@ public class HttpContentEncoderTest {
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().isReadable(), is(false));
|
||||
assertThat(chunk, is(instanceOf(LastHttpContent.class)));
|
||||
chunk.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
||||
@ -88,8 +90,12 @@ public class HttpContentEncoderTest {
|
||||
HttpContent chunk;
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("3"));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("2"));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("1"));
|
||||
|
||||
@ -97,6 +103,7 @@ public class HttpContentEncoderTest {
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().isReadable(), is(false));
|
||||
assertThat(chunk, is(instanceOf(LastHttpContent.class)));
|
||||
chunk.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
@ -121,16 +128,23 @@ public class HttpContentEncoderTest {
|
||||
HttpContent chunk;
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("3"));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("2"));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("1"));
|
||||
|
||||
assertThat(chunk, is(instanceOf(HttpContent.class)));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().isReadable(), is(false));
|
||||
assertThat(chunk, is(instanceOf(LastHttpContent.class)));
|
||||
assertEquals("Netty", ((LastHttpContent) chunk).trailingHeaders().get("X-Test"));
|
||||
chunk.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
||||
@ -148,8 +162,12 @@ public class HttpContentEncoderTest {
|
||||
HttpContent c = (HttpContent) ch.readOutbound();
|
||||
assertThat(c.content().readableBytes(), is(2));
|
||||
assertThat(c.content().toString(CharsetUtil.US_ASCII), is("42"));
|
||||
c.release();
|
||||
|
||||
LastHttpContent last = (LastHttpContent) ch.readOutbound();
|
||||
assertThat(last.content().readableBytes(), is(0));
|
||||
last.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
||||
@ -169,10 +187,13 @@ public class HttpContentEncoderTest {
|
||||
HttpContent chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("0"));
|
||||
assertThat(chunk, is(instanceOf(HttpContent.class)));
|
||||
chunk.release();
|
||||
|
||||
chunk = (HttpContent) ch.readOutbound();
|
||||
assertThat(chunk.content().isReadable(), is(false));
|
||||
assertThat(chunk, is(instanceOf(LastHttpContent.class)));
|
||||
chunk.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
||||
@ -198,6 +219,7 @@ public class HttpContentEncoderTest {
|
||||
assertThat(res.headers().get(Names.CONTENT_ENCODING), is(nullValue()));
|
||||
assertThat(res.content().readableBytes(), is(0));
|
||||
assertThat(res.content().toString(CharsetUtil.US_ASCII), is(""));
|
||||
res.release();
|
||||
|
||||
assertThat(ch.readOutbound(), is(nullValue()));
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ public class HttpObjectAggregatorTest {
|
||||
// This should be false as we decompose the buffer before to not have deep hierarchy
|
||||
assertFalse(buf instanceof CompositeByteBuf);
|
||||
}
|
||||
aggregatedMessage.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,6 +75,8 @@ public class HttpRequestDecoderTest {
|
||||
LastHttpContent c = (LastHttpContent) channel.readInbound();
|
||||
Assert.assertEquals(8, c.content().readableBytes());
|
||||
Assert.assertEquals(Unpooled.wrappedBuffer(content, content.length - 8, 8), c.content().readBytes(8));
|
||||
c.release();
|
||||
|
||||
Assert.assertFalse(channel.finish());
|
||||
Assert.assertNull(channel.readInbound());
|
||||
}
|
||||
@ -147,10 +149,13 @@ public class HttpRequestDecoderTest {
|
||||
HttpContent c = (HttpContent) channel.readInbound();
|
||||
Assert.assertEquals(1, c.content().readableBytes());
|
||||
Assert.assertEquals(content[content.length - i], c.content().readByte());
|
||||
c.release();
|
||||
}
|
||||
LastHttpContent c = (LastHttpContent) channel.readInbound();
|
||||
Assert.assertEquals(1, c.content().readableBytes());
|
||||
Assert.assertEquals(content[content.length - 1], c.content().readByte());
|
||||
c.release();
|
||||
|
||||
Assert.assertFalse(channel.finish());
|
||||
Assert.assertNull(channel.readInbound());
|
||||
}
|
||||
|
@ -52,12 +52,15 @@ public class HttpResponseDecoderTest {
|
||||
byte[] decodedData = new byte[data.length];
|
||||
content.content().readBytes(decodedData);
|
||||
assertArrayEquals(data, decodedData);
|
||||
content.release();
|
||||
|
||||
assertFalse(ch.writeInbound(Unpooled.copiedBuffer("\r\n", CharsetUtil.US_ASCII)));
|
||||
}
|
||||
assertTrue(ch.finish());
|
||||
|
||||
LastHttpContent content = (LastHttpContent) ch.readInbound();
|
||||
assertFalse(content.content().isReadable());
|
||||
content.release();
|
||||
|
||||
assertNull(ch.readInbound());
|
||||
}
|
||||
@ -93,12 +96,15 @@ public class HttpResponseDecoderTest {
|
||||
content.content().readBytes(decodedData, 32, 32);
|
||||
|
||||
assertArrayEquals(data, decodedData);
|
||||
content.release();
|
||||
|
||||
assertFalse(ch.writeInbound(Unpooled.copiedBuffer("\r\n", CharsetUtil.US_ASCII)));
|
||||
}
|
||||
assertTrue(ch.finish());
|
||||
|
||||
LastHttpContent content = (LastHttpContent) ch.readInbound();
|
||||
assertFalse(content.content().isReadable());
|
||||
content.release();
|
||||
|
||||
assertNull(ch.readInbound());
|
||||
}
|
||||
@ -117,6 +123,7 @@ public class HttpResponseDecoderTest {
|
||||
|
||||
LastHttpContent content = (LastHttpContent) ch.readInbound();
|
||||
assertThat(content.content().isReadable(), is(false));
|
||||
content.release();
|
||||
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
}
|
||||
@ -134,11 +141,13 @@ public class HttpResponseDecoderTest {
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(new byte[1024]));
|
||||
HttpContent content = (HttpContent) ch.readInbound();
|
||||
assertThat(content.content().readableBytes(), is(1024));
|
||||
content.release();
|
||||
|
||||
assertThat(ch.finish(), is(true));
|
||||
|
||||
LastHttpContent lastContent = (LastHttpContent) ch.readInbound();
|
||||
assertThat(lastContent.content().isReadable(), is(false));
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
}
|
||||
@ -159,11 +168,13 @@ public class HttpResponseDecoderTest {
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(new byte[1024]));
|
||||
HttpContent content = (HttpContent) ch.readInbound();
|
||||
assertThat(content.content().readableBytes(), is(1024));
|
||||
content.release();
|
||||
|
||||
assertThat(ch.finish(), is(true));
|
||||
|
||||
LastHttpContent lastContent = (LastHttpContent) ch.readInbound();
|
||||
assertThat(lastContent.content().isReadable(), is(false));
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
}
|
||||
@ -193,6 +204,7 @@ public class HttpResponseDecoderTest {
|
||||
assertEquals(2, values.size());
|
||||
assertTrue(values.contains("t1=t1v1"));
|
||||
assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.finish(), is(false));
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
@ -242,6 +254,7 @@ public class HttpResponseDecoderTest {
|
||||
assertEquals(2, values.size());
|
||||
assertTrue(values.contains("t1=t1v1"));
|
||||
assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.finish(), is(false));
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
@ -265,10 +278,13 @@ public class HttpResponseDecoderTest {
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(data, 0, data.length / 2));
|
||||
HttpContent content = (HttpContent) ch.readInbound();
|
||||
assertEquals(content.content().readableBytes(), 5);
|
||||
content.release();
|
||||
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(data, 5, data.length / 2));
|
||||
LastHttpContent lastContent = (LastHttpContent) ch.readInbound();
|
||||
assertEquals(lastContent.content().readableBytes(), 5);
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.finish(), is(false));
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
}
|
||||
@ -310,10 +326,13 @@ public class HttpResponseDecoderTest {
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(data, 0, data.length / 2));
|
||||
HttpContent content = (HttpContent) ch.readInbound();
|
||||
assertEquals(content.content().readableBytes(), 5);
|
||||
content.release();
|
||||
|
||||
ch.writeInbound(Unpooled.wrappedBuffer(data, 5, data.length / 2));
|
||||
LastHttpContent lastContent = (LastHttpContent) ch.readInbound();
|
||||
assertEquals(lastContent.content().readableBytes(), 5);
|
||||
lastContent.release();
|
||||
|
||||
assertThat(ch.finish(), is(false));
|
||||
assertThat(ch.readInbound(), is(nullValue()));
|
||||
}
|
||||
@ -335,6 +354,7 @@ public class HttpResponseDecoderTest {
|
||||
assertThat(res.getStatus(), is(HttpResponseStatus.SWITCHING_PROTOCOLS));
|
||||
HttpContent content = (HttpContent) ch.readInbound();
|
||||
assertThat(content.content().readableBytes(), is(16));
|
||||
content.release();
|
||||
|
||||
assertThat(ch.finish(), is(false));
|
||||
|
||||
|
@ -57,6 +57,7 @@ public class HttpServerCodecTest {
|
||||
empty = false;
|
||||
totalBytesPolled += httpChunk.content().readableBytes();
|
||||
Assert.assertFalse(httpChunk instanceof LastHttpContent);
|
||||
httpChunk.release();
|
||||
}
|
||||
Assert.assertFalse(empty);
|
||||
Assert.assertEquals(offeredContentLength, totalBytesPolled);
|
||||
|
Loading…
x
Reference in New Issue
Block a user