Add CompositeByteBuf.consolidate()

- also added test cases that test automatic / full / ranged
  consolidation
This commit is contained in:
Trustin Lee 2012-08-05 18:32:30 +09:00
parent a442789f7a
commit 728306b64f
3 changed files with 77 additions and 9 deletions

View File

@ -37,6 +37,7 @@ public interface CompositeByteBuf extends ByteBuf, Iterable<ByteBuf> {
ByteBuf componentAtOffset(int offset); ByteBuf componentAtOffset(int offset);
void discardReadComponents(); void discardReadComponents();
void consolidate();
void consolidate(int cIndex, int numComponents); void consolidate(int cIndex, int numComponents);
int toComponentIndex(int offset); int toComponentIndex(int offset);

View File

@ -321,9 +321,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
@Override @Override
public void removeComponents(int cIndex, int numComponents) { public void removeComponents(int cIndex, int numComponents) {
checkComponentIndex(cIndex, numComponents); checkComponentIndex(cIndex, numComponents);
for (int i = 0; i < numComponents; i ++) { components.subList(cIndex, cIndex + numComponents).clear();
components.remove(cIndex);
}
updateComponentOffsets(cIndex); updateComponentOffsets(cIndex);
} }
@ -1045,6 +1043,28 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
} }
} }
@Override
public void consolidate() {
final int numComponents = numComponents();
if (numComponents <= 1) {
return;
}
final Component last = components.get(numComponents - 1);
final int capacity = last.endOffset;
final ByteBuf consolidated = last.buf.unsafe().newBuffer(capacity);
for (int i = 0; i < numComponents; i ++) {
ByteBuf b = components.get(i).buf;
consolidated.writeBytes(b);
b.unsafe().release();
}
components.clear();
components.add(new Component(consolidated));
updateComponentOffsets(0);
}
@Override @Override
public void consolidate(int cIndex, int numComponents) { public void consolidate(int cIndex, int numComponents) {
checkComponentIndex(cIndex, numComponents); checkComponentIndex(cIndex, numComponents);
@ -1063,10 +1083,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
b.unsafe().release(); b.unsafe().release();
} }
for (int i = numComponents - 1; i > 0; i --) { components.subList(cIndex + 1, endCIndex).clear();
components.remove(cIndex);
}
components.set(cIndex, new Component(consolidated)); components.set(cIndex, new Component(consolidated));
updateComponentOffsets(cIndex); updateComponentOffsets(cIndex);
} }
@ -1093,8 +1110,9 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
// Remove read components. // Remove read components.
int firstComponentId = toComponentIndex(readerIndex); int firstComponentId = toComponentIndex(readerIndex);
for (int i = 0; i < firstComponentId; i ++) { for (int i = 0; i < firstComponentId; i ++) {
components.remove(0).buf.unsafe().release(); components.get(i).buf.unsafe().release();
} }
components.subList(0, firstComponentId).clear();
// Update indexes and markers. // Update indexes and markers.
Component first = components.get(0); Component first = components.get(0);
@ -1125,8 +1143,9 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit
// Remove read components. // Remove read components.
int firstComponentId = toComponentIndex(readerIndex); int firstComponentId = toComponentIndex(readerIndex);
for (int i = 0; i < firstComponentId; i ++) { for (int i = 0; i < firstComponentId; i ++) {
components.remove(0).buf.unsafe().release(); components.get(i).buf.unsafe().release();
} }
components.subList(0, firstComponentId).clear();
// Replace the first readable component with a new slice. // Replace the first readable component with a new slice.
Component c = components.get(0); Component c = components.get(0);

View File

@ -155,6 +155,53 @@ public abstract class AbstractCompositeChannelBufferTest extends
assertTrue(ByteBufUtil.equals(a, b)); assertTrue(ByteBufUtil.equals(a, b));
} }
@Test
public void testAutoConsolidation() {
CompositeByteBuf buf = compositeBuffer(2);
buf.addComponent(wrappedBuffer(new byte[] { 1 }));
assertEquals(1, buf.numComponents());
buf.addComponent(wrappedBuffer(new byte[] { 2, 3 }));
assertEquals(2, buf.numComponents());
buf.addComponent(wrappedBuffer(new byte[] { 4, 5, 6 }));
assertEquals(1, buf.numComponents());
assertTrue(buf.hasArray());
assertNotNull(buf.array());
assertEquals(0, buf.arrayOffset());
}
@Test
public void testFullConsolidation() {
CompositeByteBuf buf = compositeBuffer(Integer.MAX_VALUE);
buf.addComponent(wrappedBuffer(new byte[] { 1 }));
buf.addComponent(wrappedBuffer(new byte[] { 2, 3 }));
buf.addComponent(wrappedBuffer(new byte[] { 4, 5, 6 }));
buf.consolidate();
assertEquals(1, buf.numComponents());
assertTrue(buf.hasArray());
assertNotNull(buf.array());
assertEquals(0, buf.arrayOffset());
}
@Test
public void testRangedConsolidation() {
CompositeByteBuf buf = compositeBuffer(Integer.MAX_VALUE);
buf.addComponent(wrappedBuffer(new byte[] { 1 }));
buf.addComponent(wrappedBuffer(new byte[] { 2, 3 }));
buf.addComponent(wrappedBuffer(new byte[] { 4, 5, 6 }));
buf.addComponent(wrappedBuffer(new byte[] { 7, 8, 9, 10 }));
buf.consolidate(1, 2);
assertEquals(3, buf.numComponents());
assertEquals(wrappedBuffer(new byte[] { 1 }), buf.component(0));
assertEquals(wrappedBuffer(new byte[] { 2, 3, 4, 5, 6 }), buf.component(1));
assertEquals(wrappedBuffer(new byte[] { 7, 8, 9, 10 }), buf.component(2));
}
@Test @Test
public void testCompositeWrappedBuffer() { public void testCompositeWrappedBuffer() {
ByteBuf header = buffer(12).order(order); ByteBuf header = buffer(12).order(order);
@ -232,6 +279,7 @@ public abstract class AbstractCompositeChannelBufferTest extends
wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 6, 5).order(order)); wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 6, 5).order(order));
assertFalse(ByteBufUtil.equals(a, b)); assertFalse(ByteBufUtil.equals(a, b));
} }
@Test @Test
public void testWrappedBuffer() { public void testWrappedBuffer() {