netty5/codec-memcache/src/main/java/io/netty/handler/codec/memcache/binary/AbstractBinaryMemcacheMessage.java
Fabien Renaud 73dae929e3 codec-memcache: copy metadata in binary full request response (#9160)
Motivations
-----------
Calling `copy()`, `duplicate()` or `replace()` on `FullBinaryMemcacheResponse`
or `FullBinaryMemcacheRequest` instances should copy status, opCode, etc.
that are defined in `AbstractBinaryMemcacheMessage`.

Modifications
-------------
 - Modified duplicate, copy and replace methods in
DefaultFullBinaryMemcacheRequest and DefaultFullBinaryMemcacheResponse
to always copy metadata from parent classes.
 - Unit tests verifying duplicate, copy and replace methods for
DefaultFullBinaryMemcacheRequest and DefaultFullBinaryMemcacheResponse
copy buffers and metadata as expected.

Result
------
Calling copy(), duplicate() or replace() methods on
DefaultFullBinaryMemcacheRequest or DefaultFullBinaryMemcacheResponse
produces valid copies with all expected metadata.

Fixes #9159
2019-05-22 11:06:16 +02:00

252 lines
6.0 KiB
Java

/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.memcache.binary;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.memcache.AbstractMemcacheObject;
import io.netty.util.internal.UnstableApi;
/**
* Default implementation of a {@link BinaryMemcacheMessage}.
*/
@UnstableApi
public abstract class AbstractBinaryMemcacheMessage
extends AbstractMemcacheObject
implements BinaryMemcacheMessage {
/**
* Contains the optional key.
*/
private ByteBuf key;
/**
* Contains the optional extras.
*/
private ByteBuf extras;
private byte magic;
private byte opcode;
private short keyLength;
private byte extrasLength;
private byte dataType;
private int totalBodyLength;
private int opaque;
private long cas;
/**
* Create a new instance with all properties set.
*
* @param key the message key.
* @param extras the message extras.
*/
protected AbstractBinaryMemcacheMessage(ByteBuf key, ByteBuf extras) {
this.key = key;
keyLength = key == null ? 0 : (short) key.readableBytes();
this.extras = extras;
extrasLength = extras == null ? 0 : (byte) extras.readableBytes();
totalBodyLength = keyLength + extrasLength;
}
@Override
public ByteBuf key() {
return key;
}
@Override
public ByteBuf extras() {
return extras;
}
@Override
public BinaryMemcacheMessage setKey(ByteBuf key) {
if (this.key != null) {
this.key.release();
}
this.key = key;
short oldKeyLength = keyLength;
keyLength = key == null ? 0 : (short) key.readableBytes();
totalBodyLength = totalBodyLength + keyLength - oldKeyLength;
return this;
}
@Override
public BinaryMemcacheMessage setExtras(ByteBuf extras) {
if (this.extras != null) {
this.extras.release();
}
this.extras = extras;
short oldExtrasLength = extrasLength;
extrasLength = extras == null ? 0 : (byte) extras.readableBytes();
totalBodyLength = totalBodyLength + extrasLength - oldExtrasLength;
return this;
}
@Override
public byte magic() {
return magic;
}
@Override
public BinaryMemcacheMessage setMagic(byte magic) {
this.magic = magic;
return this;
}
@Override
public long cas() {
return cas;
}
@Override
public BinaryMemcacheMessage setCas(long cas) {
this.cas = cas;
return this;
}
@Override
public int opaque() {
return opaque;
}
@Override
public BinaryMemcacheMessage setOpaque(int opaque) {
this.opaque = opaque;
return this;
}
@Override
public int totalBodyLength() {
return totalBodyLength;
}
@Override
public BinaryMemcacheMessage setTotalBodyLength(int totalBodyLength) {
this.totalBodyLength = totalBodyLength;
return this;
}
@Override
public byte dataType() {
return dataType;
}
@Override
public BinaryMemcacheMessage setDataType(byte dataType) {
this.dataType = dataType;
return this;
}
@Override
public byte extrasLength() {
return extrasLength;
}
/**
* Set the extras length of the message.
* <p/>
* This may be 0, since the extras content is optional.
*
* @param extrasLength the extras length.
*/
BinaryMemcacheMessage setExtrasLength(byte extrasLength) {
this.extrasLength = extrasLength;
return this;
}
@Override
public short keyLength() {
return keyLength;
}
/**
* Set the key length of the message.
* <p/>
* This may be 0, since the key is optional.
*
* @param keyLength the key length to use.
*/
BinaryMemcacheMessage setKeyLength(short keyLength) {
this.keyLength = keyLength;
return this;
}
@Override
public byte opcode() {
return opcode;
}
@Override
public BinaryMemcacheMessage setOpcode(byte opcode) {
this.opcode = opcode;
return this;
}
@Override
public BinaryMemcacheMessage retain() {
super.retain();
return this;
}
@Override
public BinaryMemcacheMessage retain(int increment) {
super.retain(increment);
return this;
}
@Override
protected void deallocate() {
if (key != null) {
key.release();
}
if (extras != null) {
extras.release();
}
}
@Override
public BinaryMemcacheMessage touch() {
super.touch();
return this;
}
@Override
public BinaryMemcacheMessage touch(Object hint) {
if (key != null) {
key.touch(hint);
}
if (extras != null) {
extras.touch(hint);
}
return this;
}
/**
* Copies special metadata hold by this instance to the provided instance
*
* @param dst The instance where to copy the metadata of this instance to
*/
void copyMeta(AbstractBinaryMemcacheMessage dst) {
dst.magic = magic;
dst.opcode = opcode;
dst.keyLength = keyLength;
dst.extrasLength = extrasLength;
dst.dataType = dataType;
dst.totalBodyLength = totalBodyLength;
dst.opaque = opaque;
dst.cas = cas;
}
}