Ensure to release the component when it's removed from CompositeByteBuf / Add tests for reference counting of CompositeByteBuf

This commit is contained in:
Trustin Lee 2013-04-18 16:40:22 +09:00
parent 70eee55a48
commit 9e890f0ab8
2 changed files with 95 additions and 3 deletions

View File

@ -319,7 +319,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
}
private void updateComponentOffsets(int cIndex) {
Component c = components.get(cIndex);
lastAccessed = c;
lastAccessedId = cIndex;
@ -341,7 +340,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf removeComponent(int cIndex) {
checkComponentIndex(cIndex);
components.remove(cIndex);
components.remove(cIndex).freeIfNecessary();
updateComponentOffsets(cIndex);
return this;
}
@ -349,7 +348,13 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf removeComponents(int cIndex, int numComponents) {
checkComponentIndex(cIndex, numComponents);
components.subList(cIndex, cIndex + numComponents).clear();
List<Component> toRemove = components.subList(cIndex, cIndex + numComponents);
for (Component c: toRemove) {
c.freeIfNecessary();
}
toRemove.clear();
updateComponentOffsets(cIndex);
return this;
}

View File

@ -20,9 +20,11 @@ import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static io.netty.buffer.Unpooled.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
@ -430,4 +432,89 @@ public abstract class AbstractCompositeByteBufTest extends
assertEquals(1, buf.readByte());
}
}
@Test
public void testComponentMustBeSlice() {
CompositeByteBuf buf = freeLater(compositeBuffer());
buf.addComponent(buffer(4).setIndex(1, 3));
assertThat(buf.component(0), is(instanceOf(SlicedByteBuf.class)));
assertThat(buf.component(0).capacity(), is(2));
assertThat(buf.component(0).maxCapacity(), is(2));
}
@Test
public void testReferenceCounts1() {
ByteBuf c1 = buffer().writeByte(1);
ByteBuf c2 = buffer().writeByte(2).retain();
ByteBuf c3 = buffer().writeByte(3).retain(2);
CompositeByteBuf buf = freeLater(compositeBuffer());
assertThat(buf.refCnt(), is(1));
buf.addComponents(c1, c2, c3);
assertThat(buf.refCnt(), is(1));
// Ensure that c[123]'s refCount did not change.
assertThat(c1.refCnt(), is(1));
assertThat(c2.refCnt(), is(2));
assertThat(c3.refCnt(), is(3));
assertThat(buf.component(0).refCnt(), is(1));
assertThat(buf.component(1).refCnt(), is(2));
assertThat(buf.component(2).refCnt(), is(3));
c3.release(2);
c2.release();
}
@Test
public void testReferenceCounts2() {
ByteBuf c1 = buffer().writeByte(1);
ByteBuf c2 = buffer().writeByte(2).retain();
ByteBuf c3 = buffer().writeByte(3).retain(2);
CompositeByteBuf bufA = freeLater(compositeBuffer());
bufA.addComponents(c1, c2, c3);
CompositeByteBuf bufB = freeLater(compositeBuffer());
bufB.addComponent(bufA);
// Ensure that bufA has been released.
assertThat(bufA.refCnt(), is(0));
// Ensure that c[123]'s refCnt did not change.
// Internally, it's:
// 1) increased by 1 by addComponent(), and then
// 2) decreased by 1 by bufA.release() which is called by addComponent().
assertThat(c1.refCnt(), is(1));
assertThat(c2.refCnt(), is(2));
assertThat(c3.refCnt(), is(3));
}
@Test
public void testReferenceCounts3() {
ByteBuf c1 = buffer().writeByte(1);
ByteBuf c2 = buffer().writeByte(2).retain();
ByteBuf c3 = buffer().writeByte(3).retain(2);
CompositeByteBuf buf = freeLater(compositeBuffer());
assertThat(buf.refCnt(), is(1));
List<ByteBuf> components = new ArrayList<ByteBuf>();
Collections.addAll(components, c1, c2, c3);
buf.addComponents(components);
// Ensure that c[123]'s refCount did not change.
assertThat(c1.refCnt(), is(1));
assertThat(c2.refCnt(), is(2));
assertThat(c3.refCnt(), is(3));
assertThat(buf.component(0).refCnt(), is(1));
assertThat(buf.component(1).refCnt(), is(2));
assertThat(buf.component(2).refCnt(), is(3));
c3.release(2);
c2.release();
}
}