Use unsigned short in ValueAccessor.sliceWithShortLength

Patch by Blake Eggleston; Reviewed by Caleb Rackliffe and David Capwell for CASSANDRA-16147
This commit is contained in:
Blake Eggleston 2020-09-29 14:20:05 -07:00
parent 79e693e16e
commit 8be1cbe9ab
10 changed files with 247 additions and 62 deletions

View File

@ -3,10 +3,10 @@ jobs:
j8_jvm_upgrade_dtests:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
parallelism: 2
steps:
- attach_workspace:
at: /home/cassandra
@ -94,10 +94,10 @@ jobs:
j8_cqlsh-dtests-py2-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -171,10 +171,10 @@ jobs:
j11_unit_tests:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -263,10 +263,10 @@ jobs:
j8_cqlsh-dtests-py38-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -340,10 +340,10 @@ jobs:
j11_cqlsh-dtests-py3-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -418,10 +418,10 @@ jobs:
j11_cqlsh-dtests-py3-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -496,10 +496,10 @@ jobs:
j11_cqlsh-dtests-py38-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -574,10 +574,10 @@ jobs:
j8_cqlsh-dtests-py3-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -651,10 +651,10 @@ jobs:
j8_cqlsh-dtests-py2-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -728,10 +728,10 @@ jobs:
j11_cqlsh-dtests-py2-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -806,10 +806,10 @@ jobs:
j11_dtests-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -887,10 +887,10 @@ jobs:
j8_dtests-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -945,10 +945,10 @@ jobs:
j8_upgradetests-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1044,7 +1044,7 @@ jobs:
utests_stress:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
@ -1089,10 +1089,10 @@ jobs:
j8_unit_tests:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1180,10 +1180,10 @@ jobs:
j11_jvm_dtests:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
parallelism: 2
steps:
- attach_workspace:
at: /home/cassandra
@ -1353,10 +1353,10 @@ jobs:
j11_cqlsh-dtests-py2-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1431,10 +1431,10 @@ jobs:
j8_dtests-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1489,10 +1489,10 @@ jobs:
j11_cqlsh-dtests-py38-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1567,10 +1567,10 @@ jobs:
j8_jvm_dtests:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
parallelism: 5
steps:
- attach_workspace:
at: /home/cassandra
@ -1738,10 +1738,10 @@ jobs:
j8_cqlsh-dtests-py3-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1815,10 +1815,10 @@ jobs:
j8_cqlsh-dtests-py38-with-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -1892,7 +1892,7 @@ jobs:
utests_long:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
@ -1937,7 +1937,7 @@ jobs:
utests_fqltool:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 1
@ -1982,10 +1982,10 @@ jobs:
j11_dtests-no-vnodes:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra
@ -2063,10 +2063,10 @@ jobs:
utests_compression:
docker:
- image: nastra/cassandra-testing-ubuntu1910-java11-w-dependencies:20200603
resource_class: medium
resource_class: xlarge
working_directory: ~/
shell: /bin/bash -eo pipefail -l
parallelism: 4
parallelism: 100
steps:
- attach_workspace:
at: /home/cassandra

View File

@ -1,4 +1,5 @@
4.0-beta3
* Use unsigned short in ValueAccessor.sliceWithShortLength (CASSANDRA-16147)
* Abort repairs when getting a truncation request (CASSANDRA-15854)
* Remove bad assert when getting active compactions for an sstable (CASSANDRA-15457)
* Avoid failing compactions with very large partitions (CASSANDRA-15164)

View File

@ -43,49 +43,58 @@ public class ByteArrayAccessor implements ValueAccessor<byte[]>
private ByteArrayAccessor() {}
@Override
public int size(byte[] value)
{
return value.length;
}
@Override
public byte[][] createArray(int length)
{
return new byte[length][];
}
@Override
public void write(byte[] value, DataOutputPlus out) throws IOException
{
out.write(value);
}
@Override
public void write(byte[] value, ByteBuffer out)
{
out.put(value);
}
@Override
public <V2> int copyTo(byte[] src, int srcOffset, V2 dst, ValueAccessor<V2> dstAccessor, int dstOffset, int size)
{
dstAccessor.copyByteArrayTo(src, srcOffset, dst, dstOffset, size);
return size;
}
@Override
public int copyByteArrayTo(byte[] src, int srcOffset, byte[] dst, int dstOffset, int size)
{
FastByteOperations.copy(src, srcOffset, dst, dstOffset, size);
return size;
}
@Override
public int copyByteBufferTo(ByteBuffer src, int srcOffset, byte[] dst, int dstOffset, int size)
{
FastByteOperations.copy(src, src.position() + srcOffset, dst, dstOffset, size);
return size;
}
@Override
public void digest(byte[] value, int offset, int size, Digest digest)
{
digest.update(value, offset, size);
}
@Override
public byte[] read(DataInputPlus in, int length) throws IOException
{
byte[] b = new byte[length];
@ -93,26 +102,31 @@ public class ByteArrayAccessor implements ValueAccessor<byte[]>
return b;
}
@Override
public byte[] slice(byte[] input, int offset, int length)
{
return Arrays.copyOfRange(input, offset, offset + length);
}
@Override
public <V2> int compare(byte[] left, V2 right, ValueAccessor<V2> accessorR)
{
return accessorR.compareByteArrayTo(left, right);
}
@Override
public int compareByteArrayTo(byte[] left, byte[] right)
{
return ByteArrayUtil.compareUnsigned(left, right);
}
@Override
public int compareByteBufferTo(ByteBuffer left, byte[] right)
{
return ByteBufferUtil.compare(left, right);
}
@Override
public ByteBuffer toBuffer(byte[] value)
{
if (value == null)
@ -120,11 +134,13 @@ public class ByteArrayAccessor implements ValueAccessor<byte[]>
return ByteBuffer.wrap(value);
}
@Override
public byte[] toArray(byte[] value)
{
return value;
}
@Override
public byte[] toArray(byte[] value, int offset, int length)
{
if (value == null)
@ -134,159 +150,196 @@ public class ByteArrayAccessor implements ValueAccessor<byte[]>
return slice(value, offset, length);
}
@Override
public String toString(byte[] value, Charset charset) throws CharacterCodingException
{
return new String(value, charset);
}
@Override
public String toHex(byte[] value)
{
return Hex.bytesToHex(value);
}
@Override
public byte toByte(byte[] value)
{
return value[0];
}
@Override
public byte getByte(byte[] value, int offset)
{
return value[offset];
}
@Override
public short toShort(byte[] value)
{
return getShort(value, 0);
}
@Override
public short getShort(byte[] value, int offset)
{
return ByteArrayUtil.getShort(value, offset);
}
@Override
public int getUnsignedShort(byte[] value, int offset)
{
return ByteArrayUtil.getUnsignedShort(value, offset);
}
@Override
public int toInt(byte[] value)
{
return getInt(value, 0);
}
@Override
public int getInt(byte[] value, int offset)
{
return ByteArrayUtil.getInt(value, offset);
}
@Override
public long toLong(byte[] value)
{
return getLong(value, 0);
}
@Override
public long getLong(byte[] value, int offset)
{
return ByteArrayUtil.getLong(value, offset);
}
@Override
public float toFloat(byte[] value)
{
return ByteArrayUtil.getFloat(value, 0);
}
@Override
public double toDouble(byte[] value)
{
return ByteArrayUtil.getDouble(value, 0);
}
@Override
public UUID toUUID(byte[] value)
{
return new UUID(getLong(value, 0), getLong(value, 8));
}
@Override
public int putShort(byte[] dst, int offset, short value)
{
ByteArrayUtil.putShort(dst, offset, value);
return TypeSizes.SHORT_SIZE;
}
@Override
public int putInt(byte[] dst, int offset, int value)
{
ByteArrayUtil.putInt(dst, offset, value);
return TypeSizes.INT_SIZE;
}
@Override
public int putLong(byte[] dst, int offset, long value)
{
ByteArrayUtil.putLong(dst, offset, value);
return TypeSizes.LONG_SIZE;
}
@Override
public byte[] empty()
{
return EMPTY;
}
@Override
public byte[] valueOf(byte[] bytes)
{
return bytes;
}
@Override
public byte[] valueOf(ByteBuffer bytes)
{
return ByteBufferUtil.getArray(bytes);
}
@Override
public byte[] valueOf(String s, Charset charset)
{
return ByteArrayUtil.bytes(s, charset);
}
@Override
public byte[] valueOf(UUID v)
{
return UUIDGen.decompose(v);
}
@Override
public byte[] valueOf(boolean v)
{
return v ? new byte[] {1} : new byte[] {0};
}
@Override
public byte[] valueOf(byte v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public byte[] valueOf(short v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public byte[] valueOf(int v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public byte[] valueOf(long v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public byte[] valueOf(float v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public byte[] valueOf(double v)
{
return ByteArrayUtil.bytes(v);
}
@Override
public <V2> byte[] convert(V2 src, ValueAccessor<V2> accessor)
{
return accessor.toArray(src);
}
@Override
public byte[] allocate(int size)
{
return new byte[size];
}
@Override
public ObjectFactory<byte[]> factory()
{
return factory;

View File

@ -42,54 +42,64 @@ public class ByteBufferAccessor implements ValueAccessor<ByteBuffer>
private ByteBufferAccessor() {}
@Override
public int size(ByteBuffer value)
{
return value.remaining();
}
@Override
public ByteBuffer[] createArray(int length)
{
return new ByteBuffer[length];
}
@Override
public void write(ByteBuffer value, DataOutputPlus out) throws IOException
{
out.write(value);
}
@Override
public void write(ByteBuffer value, ByteBuffer out)
{
out.put(value.duplicate());
}
@Override
public <V2> int copyTo(ByteBuffer src, int srcOffset, V2 dst, ValueAccessor<V2> dstAccessor, int dstOffset, int size)
{
dstAccessor.copyByteBufferTo(src, srcOffset, dst, dstOffset, size);
return size;
}
@Override
public int copyByteArrayTo(byte[] src, int srcOffset, ByteBuffer dst, int dstOffset, int size)
{
FastByteOperations.copy(src, srcOffset, dst, dst.position() + dstOffset, size);
return size;
}
@Override
public int copyByteBufferTo(ByteBuffer src, int srcOffset, ByteBuffer dst, int dstOffset, int size)
{
FastByteOperations.copy(src, src.position() + srcOffset, dst, dst.position() + dstOffset, size);
return size;
}
@Override
public void digest(ByteBuffer value, int offset, int size, Digest digest)
{
digest.update(value, value.position() + offset, size);
}
@Override
public ByteBuffer read(DataInputPlus in, int length) throws IOException
{
return ByteBufferUtil.read(in, length);
}
@Override
public ByteBuffer slice(ByteBuffer input, int offset, int length)
{
ByteBuffer copy = input.duplicate();
@ -98,26 +108,31 @@ public class ByteBufferAccessor implements ValueAccessor<ByteBuffer>
return copy;
}
@Override
public <V2> int compare(ByteBuffer left, V2 right, ValueAccessor<V2> accessorR)
{
return accessorR.compareByteBufferTo(left, right);
}
@Override
public int compareByteArrayTo(byte[] left, ByteBuffer right)
{
return ByteBufferUtil.compare(left, right);
}
@Override
public int compareByteBufferTo(ByteBuffer left, ByteBuffer right)
{
return ByteBufferUtil.compareUnsigned(left, right);
}
@Override
public ByteBuffer toBuffer(ByteBuffer value)
{
return value;
}
@Override
public byte[] toArray(ByteBuffer value)
{
if (value == null)
@ -125,6 +140,7 @@ public class ByteBufferAccessor implements ValueAccessor<ByteBuffer>
return ByteBufferUtil.getArray(value);
}
@Override
public byte[] toArray(ByteBuffer value, int offset, int length)
{
if (value == null)
@ -132,159 +148,196 @@ public class ByteBufferAccessor implements ValueAccessor<ByteBuffer>
return ByteBufferUtil.getArray(value, value.position() + offset, length);
}
@Override
public String toString(ByteBuffer value, Charset charset) throws CharacterCodingException
{
return ByteBufferUtil.string(value, charset);
}
@Override
public ByteBuffer valueOf(UUID v)
{
return UUIDGen.toByteBuffer(v);
}
@Override
public String toHex(ByteBuffer value)
{
return ByteBufferUtil.bytesToHex(value);
}
@Override
public byte toByte(ByteBuffer value)
{
return ByteBufferUtil.toByte(value);
}
@Override
public byte getByte(ByteBuffer value, int offset)
{
return value.get(value.position() + offset);
}
@Override
public short toShort(ByteBuffer value)
{
return ByteBufferUtil.toShort(value);
}
@Override
public short getShort(ByteBuffer value, int offset)
{
return value.getShort(value.position() + offset);
}
@Override
public int getUnsignedShort(ByteBuffer value, int offset)
{
return ByteBufferUtil.getUnsignedShort(value, offset);
}
@Override
public int toInt(ByteBuffer value)
{
return ByteBufferUtil.toInt(value);
}
@Override
public int getInt(ByteBuffer value, int offset)
{
return value.getInt(value.position() + offset);
}
@Override
public long toLong(ByteBuffer value)
{
return ByteBufferUtil.toLong(value);
}
@Override
public long getLong(ByteBuffer value, int offset)
{
return value.getLong(value.position() + offset);
}
@Override
public float toFloat(ByteBuffer value)
{
return ByteBufferUtil.toFloat(value);
}
@Override
public double toDouble(ByteBuffer value)
{
return ByteBufferUtil.toDouble(value);
}
@Override
public UUID toUUID(ByteBuffer value)
{
return UUIDGen.getUUID(value);
}
@Override
public int putShort(ByteBuffer dst, int offset, short value)
{
dst.putShort(dst.position() + offset, value);
return TypeSizes.SHORT_SIZE;
}
@Override
public int putInt(ByteBuffer dst, int offset, int value)
{
dst.putInt(dst.position() + offset, value);
return TypeSizes.INT_SIZE;
}
@Override
public int putLong(ByteBuffer dst, int offset, long value)
{
dst.putLong(dst.position() + offset, value);
return TypeSizes.LONG_SIZE;
}
@Override
public ByteBuffer empty()
{
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
}
@Override
public ByteBuffer valueOf(byte[] bytes)
{
return ByteBuffer.wrap(bytes);
}
@Override
public ByteBuffer valueOf(ByteBuffer bytes)
{
return bytes;
}
@Override
public ByteBuffer valueOf(String v, Charset charset)
{
return ByteBufferUtil.bytes(v, charset);
}
@Override
public ByteBuffer valueOf(boolean v)
{
return v ? ByteBuffer.wrap(new byte[] {1}) : ByteBuffer.wrap(new byte[] {0});
}
@Override
public ByteBuffer valueOf(byte v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public ByteBuffer valueOf(short v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public ByteBuffer valueOf(int v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public ByteBuffer valueOf(long v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public ByteBuffer valueOf(float v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public ByteBuffer valueOf(double v)
{
return ByteBufferUtil.bytes(v);
}
@Override
public <V2> ByteBuffer convert(V2 src, ValueAccessor<V2> accessor)
{
return accessor.toBuffer(src);
}
@Override
public ByteBuffer allocate(int size)
{
return ByteBuffer.allocate(size);
}
@Override
public ObjectFactory<ByteBuffer> factory()
{
return ByteBufferObjectFactory.instance;

View File

@ -247,7 +247,7 @@ public class CompositeType extends AbstractCompositeType
public static <V> boolean isStaticName(V value, ValueAccessor<V> accessor)
{
return accessor.size(value) >= 2 && (accessor.getShortLength(value, 0) & 0xFFFF) == STATIC_MARKER;
return accessor.size(value) >= 2 && (accessor.getUnsignedShort(value, 0) & 0xFFFF) == STATIC_MARKER;
}
@Override

View File

@ -216,23 +216,15 @@ public interface ValueAccessor<V>
V slice(V input, int offset, int length);
/**
* same as {@link ValueAccessor#slice(Object, int, int)}, except the length is taked from the first
* same as {@link ValueAccessor#slice(Object, int, int)}, except the length is taken from the first
* 2 bytes from the given offset (and not included in the return value)
*/
default V sliceWithShortLength(V input, int offset)
{
int size = getShort(input, offset);
int size = getUnsignedShort(input, offset);
return slice(input, offset + 2, size);
}
/**
* @return a short length prefix starting at {@param offset}
*/
default int getShortLength(V v, int offset)
{
return getShort(v, offset);
}
/**
* lexicographically compare {@param left} to {@param right}
* @param <VR> backing type of
@ -311,6 +303,8 @@ public interface ValueAccessor<V>
short toShort(V value);
/** returns a short from offset {@param offset} */
short getShort(V value, int offset);
/** returns an unsigned short from offset {@param offset} */
int getUnsignedShort(V value, int offset);
/** returns an int from offset 0 */
int toInt(V value);
/** returns an int from offset {@param offset} */

View File

@ -111,6 +111,10 @@ public class ByteArrayUtil
(b[off] << 8));
}
public static int getUnsignedShort(byte[] b, int off) {
return ((b[off] & 0xFF) << 8) | (b[off + 1] & 0xFF);
}
public static int getInt(byte[] b, int off) {
return ((b[off + 3] & 0xFF) ) +
((b[off + 2] & 0xFF) << 8) +

View File

@ -701,11 +701,15 @@ public class ByteBufferUtil
return false;
}
public static int getUnsignedShort(ByteBuffer bb, int position)
{
return ((bb.get(position) & 0xFF) << 8) | (bb.get(position + 1) & 0xFF);
}
// Doesn't change bb position
public static int getShortLength(ByteBuffer bb, int position)
{
int length = (bb.get(position) & 0xFF) << 8;
return length | (bb.get(position + 1) & 0xFF);
return getUnsignedShort(bb, position);
}
// changes bb position

View File

@ -22,6 +22,8 @@ import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.*;
import com.google.common.collect.Lists;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.fail;
@ -321,4 +323,24 @@ public class CompositeTypeTest
bb.rewind();
return bb;
}
private static <V> void testToFromString(ByteBuffer bytes, ValueAccessor<V> accessor, CompositeType type)
{
V value = accessor.valueOf(bytes);
String s = type.getString(value, accessor);
ByteBuffer fromString = type.fromString(s);
Assert.assertEquals(bytes, fromString);
}
@Test
public void testLargeValues()
{
CompositeType type = CompositeType.getInstance(Lists.newArrayList(BytesType.instance));
ByteBuffer expected = ByteBuffer.allocate(0xFFFE);
new Random(0).nextBytes(expected.array());
ByteBuffer serialized = CompositeType.build(ByteBufferAccessor.instance, expected);
for (ValueAccessor<?> accessor : ValueAccessors.ACCESSORS)
testToFromString(serialized, accessor, type);
}
}

View File

@ -18,6 +18,7 @@
package org.apache.cassandra.db.marshal;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
@ -26,10 +27,15 @@ import com.google.common.primitives.Shorts;
import org.junit.Assert;
import org.junit.Test;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.ByteArrayUtil;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.assertj.core.api.Assertions;
import org.quicktheories.core.Gen;
import org.quicktheories.generators.SourceDSL;
import static org.apache.cassandra.db.marshal.ValueAccessors.ACCESSORS;
import static org.quicktheories.QuickTheory.qt;
public class ValueAccessorTest
{
@ -129,4 +135,52 @@ public class ValueAccessorTest
testTypeConversion(i, accessor, random);
}
}
private static <V> void testReadWriteWithShortLength(ValueAccessor<V> accessor, int size) throws IOException
{
Random random = new Random(size);
byte[] bytes = new byte[size];
random.nextBytes(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
try (DataOutputBuffer out = new DataOutputBuffer(size + 2))
{
ByteBufferUtil.writeWithShortLength(buffer, out);
V flushed = accessor.valueOf(out.toByteArray());
V value = accessor.sliceWithShortLength(flushed, 0);
Assert.assertArrayEquals(bytes, accessor.toArray(value));
}
}
@Test
public void testReadWriteWithShortLength() throws IOException
{
int[] lengths = new int[]{0, 1, 2, 256, 0x8001, 0xFFFF};
for (int length : lengths)
{
for (ValueAccessor<?> accessor: ACCESSORS)
testReadWriteWithShortLength(accessor, length);
}
}
@Test
public void testUnsignedShort()
{
Gen<Integer> gen = SourceDSL.integers().between(0, Short.MAX_VALUE * 2 + 1);
qt().forAll(gen).checkAssert(jint -> {
int size = jint;
for (ValueAccessor<Object> accessor: ACCESSORS)
{
Object value = accessor.allocate(5);
for (int offset : Arrays.asList(0, 3))
{
accessor.putShort(value, offset, (short) size); // testing signed
Assertions.assertThat(accessor.getUnsignedShort(value, offset))
.as("getUnsignedShort(putShort(unsigned_short)) != unsigned_short for %s", accessor.getClass())
.isEqualTo(size);
}
}
});
}
}