use of io.netty.handler.codec.memcache.MemcacheContent in project netty by netty.
the class AbstractBinaryMemcacheDecoder method invalidChunk.
/**
* Helper method to create a content chunk indicating a invalid decoding result.
*
* @param cause the cause of the decoding failure.
* @return a valid content chunk indicating failure.
*/
private MemcacheContent invalidChunk(Exception cause) {
state = State.BAD_MESSAGE;
MemcacheContent chunk = new DefaultLastMemcacheContent(Unpooled.EMPTY_BUFFER);
chunk.setDecoderResult(DecoderResult.failure(cause));
return chunk;
}
use of io.netty.handler.codec.memcache.MemcacheContent in project netty by netty.
the class BinaryMemcacheDecoderTest method shouldDecodeSeparatedValues.
@Test
public void shouldDecodeSeparatedValues() {
String msgBody = "Not found";
channel = new EmbeddedChannel(new BinaryMemcacheResponseDecoder());
channel.writeInbound(Unpooled.buffer().writeBytes(GET_RESPONSE_CHUNK_1));
channel.writeInbound(Unpooled.buffer().writeBytes(GET_RESPONSE_CHUNK_2));
// First message
BinaryMemcacheResponse response = channel.readInbound();
assertThat(response.status(), is(BinaryMemcacheResponseStatus.KEY_ENOENT));
assertThat(response.totalBodyLength(), is(msgBody.length()));
response.release();
// First message first content chunk
MemcacheContent content = channel.readInbound();
assertThat(content, instanceOf(LastMemcacheContent.class));
assertThat(content.content().toString(CharsetUtil.UTF_8), is(msgBody));
content.release();
// Second message
response = channel.readInbound();
assertThat(response.status(), is(BinaryMemcacheResponseStatus.KEY_ENOENT));
assertThat(response.totalBodyLength(), is(msgBody.length()));
response.release();
// Second message first content chunk
content = channel.readInbound();
assertThat(content, instanceOf(MemcacheContent.class));
assertThat(content.content().toString(CharsetUtil.UTF_8), is(msgBody.substring(0, 7)));
content.release();
// Second message second content chunk
content = channel.readInbound();
assertThat(content, instanceOf(LastMemcacheContent.class));
assertThat(content.content().toString(CharsetUtil.UTF_8), is(msgBody.substring(7, 9)));
content.release();
// Third message
response = channel.readInbound();
assertThat(response.status(), is(BinaryMemcacheResponseStatus.KEY_ENOENT));
assertThat(response.totalBodyLength(), is(msgBody.length()));
response.release();
// Third message first content chunk
content = channel.readInbound();
assertThat(content, instanceOf(LastMemcacheContent.class));
assertThat(content.content().toString(CharsetUtil.UTF_8), is(msgBody));
content.release();
}
use of io.netty.handler.codec.memcache.MemcacheContent in project netty by netty.
the class BinaryMemcacheDecoderTest method shouldHandleNonUniformNetworkBatches.
/**
* This test makes sure that even when the decoder is confronted with various chunk
* sizes in the middle of decoding, it can recover and decode all the time eventually.
*/
@Test
public void shouldHandleNonUniformNetworkBatches() {
ByteBuf incoming = Unpooled.copiedBuffer(SET_REQUEST_WITH_CONTENT);
while (incoming.isReadable()) {
channel.writeInbound(incoming.readBytes(5));
}
incoming.release();
BinaryMemcacheRequest request = channel.readInbound();
assertThat(request, notNullValue());
assertThat(request.key(), notNullValue());
assertThat(request.extras(), nullValue());
request.release();
MemcacheContent content1 = channel.readInbound();
MemcacheContent content2 = channel.readInbound();
assertThat(content1, instanceOf(MemcacheContent.class));
assertThat(content2, instanceOf(LastMemcacheContent.class));
assertThat(content1.content().readableBytes(), is(3));
assertThat(content2.content().readableBytes(), is(5));
content1.release();
content2.release();
}
use of io.netty.handler.codec.memcache.MemcacheContent in project netty by netty.
the class BinaryMemcacheDecoderTest method shouldDecodeRequestWithChunkedContent.
/**
* This test makes sure that large content is emitted in chunks.
*/
@Test
public void shouldDecodeRequestWithChunkedContent() {
int smallBatchSize = 2;
channel = new EmbeddedChannel(new BinaryMemcacheRequestDecoder(smallBatchSize));
ByteBuf incoming = Unpooled.buffer();
incoming.writeBytes(SET_REQUEST_WITH_CONTENT);
channel.writeInbound(incoming);
BinaryMemcacheRequest request = channel.readInbound();
assertThat(request, notNullValue());
assertThat(request.key(), notNullValue());
assertThat(request.extras(), nullValue());
assertThat(request.keyLength(), is((short) 3));
assertThat(request.extrasLength(), is((byte) 0));
assertThat(request.totalBodyLength(), is(11));
request.release();
int expectedContentChunks = 4;
for (int i = 1; i <= expectedContentChunks; i++) {
MemcacheContent content = channel.readInbound();
if (i < expectedContentChunks) {
assertThat(content, instanceOf(MemcacheContent.class));
} else {
assertThat(content, instanceOf(LastMemcacheContent.class));
}
assertThat(content.content().readableBytes(), is(2));
content.release();
}
assertThat(channel.readInbound(), nullValue());
}
use of io.netty.handler.codec.memcache.MemcacheContent in project netty by netty.
the class AbstractBinaryMemcacheDecoder method decode.
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
switch(state) {
case READ_HEADER:
try {
if (in.readableBytes() < 24) {
return;
}
resetDecoder();
currentMessage = decodeHeader(in);
state = State.READ_EXTRAS;
} catch (Exception e) {
resetDecoder();
out.add(invalidMessage(e));
return;
}
case READ_EXTRAS:
try {
byte extrasLength = currentMessage.extrasLength();
if (extrasLength > 0) {
if (in.readableBytes() < extrasLength) {
return;
}
currentMessage.setExtras(in.readRetainedSlice(extrasLength));
}
state = State.READ_KEY;
} catch (Exception e) {
resetDecoder();
out.add(invalidMessage(e));
return;
}
case READ_KEY:
try {
short keyLength = currentMessage.keyLength();
if (keyLength > 0) {
if (in.readableBytes() < keyLength) {
return;
}
currentMessage.setKey(in.readRetainedSlice(keyLength));
}
out.add(currentMessage.retain());
state = State.READ_CONTENT;
} catch (Exception e) {
resetDecoder();
out.add(invalidMessage(e));
return;
}
case READ_CONTENT:
try {
int valueLength = currentMessage.totalBodyLength() - currentMessage.keyLength() - currentMessage.extrasLength();
int toRead = in.readableBytes();
if (valueLength > 0) {
if (toRead == 0) {
return;
}
if (toRead > chunkSize) {
toRead = chunkSize;
}
int remainingLength = valueLength - alreadyReadChunkSize;
if (toRead > remainingLength) {
toRead = remainingLength;
}
ByteBuf chunkBuffer = in.readRetainedSlice(toRead);
MemcacheContent chunk;
if ((alreadyReadChunkSize += toRead) >= valueLength) {
chunk = new DefaultLastMemcacheContent(chunkBuffer);
} else {
chunk = new DefaultMemcacheContent(chunkBuffer);
}
out.add(chunk);
if (alreadyReadChunkSize < valueLength) {
return;
}
} else {
out.add(LastMemcacheContent.EMPTY_LAST_CONTENT);
}
resetDecoder();
state = State.READ_HEADER;
return;
} catch (Exception e) {
resetDecoder();
out.add(invalidChunk(e));
return;
}
case BAD_MESSAGE:
in.skipBytes(actualReadableBytes());
return;
default:
throw new Error("Unknown state reached: " + state);
}
}
Aggregations