Retain ByteBuf extras when aggregating

Motivation:

BinaryMemcacheObjectAggregator doesn't retain ByteBuf `extras`. So `io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1` will be thrown when aggregating a message containing `extras`. See the unit test for an example.

Modifications:

`ratain` extras to fix IllegalReferenceCountException.

Result:

`extras` is retained.
This commit is contained in:
Xiaoyan Lin 2016-01-28 11:25:54 -08:00 committed by Norman Maurer
parent 11bcb8790c
commit 501c35afff
2 changed files with 45 additions and 2 deletions

View File

@ -53,8 +53,9 @@ public class BinaryMemcacheObjectAggregator extends AbstractMemcacheObjectAggreg
}
private static FullBinaryMemcacheRequest toFullRequest(BinaryMemcacheRequest request, ByteBuf content) {
ByteBuf extras = request.extras() == null ? null : request.extras().retain();
FullBinaryMemcacheRequest fullRequest =
new DefaultFullBinaryMemcacheRequest(request.key(), request.extras(), content);
new DefaultFullBinaryMemcacheRequest(request.key(), extras, content);
fullRequest.setMagic(request.magic());
fullRequest.setOpcode(request.opcode());
@ -70,8 +71,9 @@ public class BinaryMemcacheObjectAggregator extends AbstractMemcacheObjectAggreg
}
private static FullBinaryMemcacheResponse toFullResponse(BinaryMemcacheResponse response, ByteBuf content) {
ByteBuf extras = response.extras() == null ? null : response.extras().retain();
FullBinaryMemcacheResponse fullResponse =
new DefaultFullBinaryMemcacheResponse(response.key(), response.extras(), content);
new DefaultFullBinaryMemcacheResponse(response.key(), extras, content);
fullResponse.setMagic(response.magic());
fullResponse.setOpcode(response.opcode());

View File

@ -18,12 +18,17 @@ package io.netty.handler.codec.memcache.binary;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.memcache.DefaultLastMemcacheContent;
import io.netty.handler.codec.memcache.DefaultMemcacheContent;
import io.netty.util.CharsetUtil;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Verifies the correct functionality of the {@link BinaryMemcacheObjectAggregator}.
@ -73,4 +78,40 @@ public class BinaryMemcacheObjectAggregatorTest {
channel.finish();
}
@Test
public void shouldRetainByteBufWhenAggregating() {
channel = new EmbeddedChannel(
new BinaryMemcacheRequestEncoder(),
new BinaryMemcacheRequestDecoder(),
new BinaryMemcacheObjectAggregator(MAX_CONTENT_SIZE));
String key = "Netty";
ByteBuf extras = Unpooled.copiedBuffer("extras", CharsetUtil.UTF_8);
BinaryMemcacheRequest request = new DefaultBinaryMemcacheRequest(key, extras);
request.setKeyLength((short) key.length());
request.setExtrasLength((byte) extras.readableBytes());
DefaultMemcacheContent content1 =
new DefaultMemcacheContent(Unpooled.copiedBuffer("Netty", CharsetUtil.UTF_8));
DefaultLastMemcacheContent content2 =
new DefaultLastMemcacheContent(Unpooled.copiedBuffer(" Rocks!", CharsetUtil.UTF_8));
int totalBodyLength = key.length() + extras.readableBytes() +
content1.content().readableBytes() + content2.content().readableBytes();
request.setTotalBodyLength(totalBodyLength);
assertTrue(channel.writeOutbound(request, content1, content2));
assertThat(channel.outboundMessages().size(), is(3));
assertTrue(channel.writeInbound(channel.readOutbound(), channel.readOutbound(), channel.readOutbound()));
FullBinaryMemcacheRequest read = channel.readInbound();
assertThat(read, notNullValue());
assertThat(read.key(), is("Netty"));
assertThat(read.extras().toString(CharsetUtil.UTF_8), is("extras"));
assertThat(read.content().toString(CharsetUtil.UTF_8), is("Netty Rocks!"));
read.release();
assertFalse(channel.finish());
}
}