Skip to content

Commit

Permalink
Fix issue jetty#5499
Browse files Browse the repository at this point in the history
this PR let the ByteAccumulator recyclable. after invoke ByteAccumulator.transferTo method
we can invoke ByteAccumulator.recycle method to reuse byte[] via ByteAccumulator.newByteArray method

Signed-off-by: Baoyi Chen <chen.bao.yi@qq.com>
  • Loading branch information
leonchen83 committed Oct 29, 2020
1 parent 01f5838 commit c04a934
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 52 deletions.
Expand Up @@ -27,22 +27,8 @@

public class ByteAccumulator
{
private class ByteArray
{
private byte[] buf;
private int offset;
private int length;

private ByteArray(byte[] buf, int offset, int length)
{
this.buf = buf;
this.offset = offset;
this.length = length;
}
}

private List<ByteArray> prevChunks = null;
private List<ByteArray> nextChunks = new ArrayList<>();
private List<ByteBuffer> prevChunks = null;
private List<ByteBuffer> nextChunks = new ArrayList<>();
private final int maxSize;
private int length = 0;
private int index;
Expand All @@ -59,7 +45,7 @@ public void copyChunk(byte[] buf, int offset, int length)
String err = String.format("Resulting message size [%,d] is too large for configured max of [%,d]", this.length + length, maxSize);
throw new MessageTooLargeException(err);
}
nextChunks.add(new ByteArray(buf, offset, length));
nextChunks.add(ByteBuffer.wrap(buf, offset, length));
this.length += length;
}

Expand All @@ -68,19 +54,19 @@ public int getLength()
return length;
}

byte[] newByteArray(int size)
ByteBuffer newByteBuffer(int size)
{
byte[] bytes;
ByteBuffer buf;
if (prevChunks != null && prevChunks.size() > index)
{
bytes = prevChunks.get(index).buf;
}
buf = prevChunks.get(index);
}
else
{
bytes = new byte[size];
buf = ByteBuffer.allocate(size);
}
index++;
return bytes;
return buf;
}

public void transferTo(ByteBuffer buffer)
Expand All @@ -92,9 +78,9 @@ public void transferTo(ByteBuffer buffer)
}

int position = buffer.position();
for (ByteArray chunk : nextChunks)
for (ByteBuffer chunk : nextChunks)
{
buffer.put(chunk.buf, chunk.offset, chunk.length);
buffer.put(chunk);
}
BufferUtil.flipToFlush(buffer, position);
}
Expand All @@ -111,7 +97,7 @@ void recycle()
}

// keep prevChunks retain max resize elements
if (prevChunks.size() > resize)
if (prevChunks.size() > resize)
{
prevChunks.subList(resize, prevChunks.size()).clear();
}
Expand Down
Expand Up @@ -208,20 +208,21 @@ protected void decompress(ByteAccumulator accumulator, ByteBuffer buf) throws Da
loop:
while (true)
{
byte[] output = accumulator.newByteArray(DECOMPRESS_BUF_SIZE);
ByteBuffer output = accumulator.newByteBuffer(DECOMPRESS_BUF_SIZE);
int offset = 0;
while (offset < output.length)
while (offset < output.capacity())
{
read = inflater.inflate(output, offset, output.length - offset);
read = inflater.inflate(output.array(), offset, output.capacity() - offset);
if (read <= 0)
{
// last chunk
if (offset > 0)
accumulator.copyChunk(output, 0, offset);
accumulator.copyChunk(output.array(), 0, offset);
break loop;
}
offset += read;
}
accumulator.copyChunk(output, 0, offset);
accumulator.copyChunk(output.array(), 0, offset);
}
}

Expand Down
Expand Up @@ -100,22 +100,22 @@ public void testRecycle()
ByteBuffer out1 = ByteBuffer.allocate(200);
{
// 1
byte[] bytes = accumulator.newByteArray(10);
ByteBuffer buf = accumulator.newByteBuffer(10);
byte[] hello = "Hello".getBytes(UTF_8);
System.arraycopy(hello, 0, bytes, 0, hello.length);
accumulator.copyChunk(bytes, 0, hello.length);
System.arraycopy(hello, 0, buf.array(), 0, hello.length);
accumulator.copyChunk(buf.array(), 0, hello.length);

// 2
bytes = accumulator.newByteArray(10);
buf = accumulator.newByteBuffer(10);
byte[] space = " ".getBytes(UTF_8);
System.arraycopy(space, 0, bytes, 0, space.length);
accumulator.copyChunk(bytes, 0, space.length);
System.arraycopy(space, 0, buf.array(), 0, space.length);
accumulator.copyChunk(buf.array(), 0, space.length);

// 3
bytes = accumulator.newByteArray(10);
buf = accumulator.newByteBuffer(10);
byte[] world = "World".getBytes(UTF_8);
System.arraycopy(world, 0, bytes, 0, world.length);
accumulator.copyChunk(bytes, 0, world.length);
System.arraycopy(world, 0, buf.array(), 0, world.length);
accumulator.copyChunk(buf.array(), 0, world.length);

assertThat("Length", accumulator.getLength(), is(hello.length + space.length + world.length));

Expand All @@ -127,28 +127,28 @@ public void testRecycle()

{
// 1
byte[] bytes = accumulator.newByteArray(10);
ByteBuffer buf = accumulator.newByteBuffer(10);
byte[] olleh = "olleH".getBytes(UTF_8);
System.arraycopy(olleh, 0, bytes, 0, olleh.length);
accumulator.copyChunk(bytes, 0, olleh.length);
System.arraycopy(olleh, 0, buf.array(), 0, olleh.length);
accumulator.copyChunk(buf.array(), 0, olleh.length);

// 2
bytes = accumulator.newByteArray(10);
buf = accumulator.newByteBuffer(10);
byte[] space = " ".getBytes(UTF_8);
System.arraycopy(space, 0, bytes, 0, space.length);
accumulator.copyChunk(bytes, 0, space.length);
System.arraycopy(space, 0, buf.array(), 0, space.length);
accumulator.copyChunk(buf.array(), 0, space.length);

// 3
bytes = accumulator.newByteArray(10);
buf = accumulator.newByteBuffer(10);
byte[] dlrow = "dlroW".getBytes(UTF_8);
System.arraycopy(dlrow, 0, bytes, 0, dlrow.length);
accumulator.copyChunk(bytes, 0, dlrow.length);
System.arraycopy(dlrow, 0, buf.array(), 0, dlrow.length);
accumulator.copyChunk(buf.array(), 0, dlrow.length);

// 4
bytes = accumulator.newByteArray(10);
buf = accumulator.newByteBuffer(10);
byte[] done = " enoD".getBytes(UTF_8);
System.arraycopy(done, 0, bytes, 0, done.length);
accumulator.copyChunk(bytes, 0, done.length);
System.arraycopy(done, 0, buf.array(), 0, done.length);
accumulator.copyChunk(buf.array(), 0, done.length);

assertThat("Length", accumulator.getLength(), is(olleh.length + space.length + dlrow.length + done.length));

Expand Down

0 comments on commit c04a934

Please sign in to comment.