HBASE-20716: Changes the bytes[] conversion done in Bytes and ByteBufferUtils. Instead of doing check unsafe_aligned available everytime, choose the best converter at startup.
This commit is contained in:
parent
c744dd84cc
commit
b972b9a2d9
|
@ -34,7 +34,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos;
|
|||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.BytesBytesPair;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.util.Pair;
|
||||
import org.apache.hadoop.hbase.util.UnsafeAccess;
|
||||
import org.apache.hadoop.hbase.util.UnsafeAvailChecker;
|
||||
|
||||
import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -351,9 +350,9 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
int j = numWords << 3; // numWords * SIZEOF_LONG;
|
||||
|
||||
for (int i = 0; i < j; i += Bytes.SIZEOF_LONG) {
|
||||
long fuzzyBytes = UnsafeAccess.toLong(fuzzyKeyBytes, i);
|
||||
long fuzzyMeta = UnsafeAccess.toLong(fuzzyKeyMeta, i);
|
||||
long rowValue = UnsafeAccess.toLong(row, offset + i);
|
||||
long fuzzyBytes = Bytes.toLong(fuzzyKeyBytes, i);
|
||||
long fuzzyMeta = Bytes.toLong(fuzzyKeyMeta, i);
|
||||
long rowValue = Bytes.toLong(row, offset + i);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
return SatisfiesCode.NEXT_EXISTS;
|
||||
|
@ -363,9 +362,9 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
int off = j;
|
||||
|
||||
if (length - off >= Bytes.SIZEOF_INT) {
|
||||
int fuzzyBytes = UnsafeAccess.toInt(fuzzyKeyBytes, off);
|
||||
int fuzzyMeta = UnsafeAccess.toInt(fuzzyKeyMeta, off);
|
||||
int rowValue = UnsafeAccess.toInt(row, offset + off);
|
||||
int fuzzyBytes = Bytes.toInt(fuzzyKeyBytes, off);
|
||||
int fuzzyMeta = Bytes.toInt(fuzzyKeyMeta, off);
|
||||
int rowValue = Bytes.toInt(row, offset + off);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
return SatisfiesCode.NEXT_EXISTS;
|
||||
|
@ -374,9 +373,9 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
}
|
||||
|
||||
if (length - off >= Bytes.SIZEOF_SHORT) {
|
||||
short fuzzyBytes = UnsafeAccess.toShort(fuzzyKeyBytes, off);
|
||||
short fuzzyMeta = UnsafeAccess.toShort(fuzzyKeyMeta, off);
|
||||
short rowValue = UnsafeAccess.toShort(row, offset + off);
|
||||
short fuzzyBytes = Bytes.toShort(fuzzyKeyBytes, off);
|
||||
short fuzzyMeta = Bytes.toShort(fuzzyKeyMeta, off);
|
||||
short rowValue = Bytes.toShort(row, offset + off);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
// even if it does not (in this case getNextForFuzzyRule
|
||||
|
|
|
@ -55,7 +55,267 @@ public final class ByteBufferUtils {
|
|||
private ByteBufferUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
static abstract class Comparer {
|
||||
abstract int compareTo(byte [] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2);
|
||||
abstract int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2);
|
||||
}
|
||||
|
||||
static abstract class Converter {
|
||||
abstract short toShort(ByteBuffer buffer, int offset);
|
||||
abstract int toInt(ByteBuffer buffer);
|
||||
abstract int toInt(ByteBuffer buffer, int offset);
|
||||
abstract long toLong(ByteBuffer buffer, int offset);
|
||||
abstract void putInt(ByteBuffer buffer, int val);
|
||||
abstract int putInt(ByteBuffer buffer, int index, int val);
|
||||
abstract void putShort(ByteBuffer buffer, short val);
|
||||
abstract int putShort(ByteBuffer buffer, int index, short val);
|
||||
abstract void putLong(ByteBuffer buffer, long val);
|
||||
abstract int putLong(ByteBuffer buffer, int index, long val);
|
||||
}
|
||||
|
||||
static class ComparerHolder {
|
||||
static final String UNSAFE_COMPARER_NAME = ComparerHolder.class.getName() + "$UnsafeComparer";
|
||||
|
||||
static final Comparer BEST_COMPARER = getBestComparer();
|
||||
|
||||
static Comparer getBestComparer() {
|
||||
try {
|
||||
Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Comparer comparer = (Comparer) theClass.getConstructor().newInstance();
|
||||
return comparer;
|
||||
} catch (Throwable t) { // ensure we really catch *everything*
|
||||
return PureJavaComparer.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
static final class PureJavaComparer extends Comparer {
|
||||
static final PureJavaComparer INSTANCE = new PureJavaComparer();
|
||||
|
||||
private PureJavaComparer() {}
|
||||
|
||||
@Override
|
||||
public int compareTo(byte [] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
int end1 = o1 + l1;
|
||||
int end2 = o2 + l2;
|
||||
for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
|
||||
int a = buf1[i] & 0xFF;
|
||||
int b = buf2.get(j) & 0xFF;
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
int end1 = o1 + l1;
|
||||
int end2 = o2 + l2;
|
||||
for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
|
||||
int a = buf1.get(i) & 0xFF;
|
||||
int b = buf2.get(j) & 0xFF;
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
}
|
||||
}
|
||||
|
||||
static final class UnsafeComparer extends Comparer {
|
||||
|
||||
public UnsafeComparer() {}
|
||||
|
||||
static {
|
||||
if(!UNSAFE_UNALIGNED) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(byte[] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
long offset2Adj;
|
||||
Object refObj2 = null;
|
||||
if (buf2.isDirect()) {
|
||||
offset2Adj = o2 + ((DirectBuffer)buf2).address();
|
||||
} else {
|
||||
offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj2 = buf2.array();
|
||||
}
|
||||
return compareToUnsafe(buf1, o1 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET, l1,
|
||||
refObj2, offset2Adj, l2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
long offset1Adj, offset2Adj;
|
||||
Object refObj1 = null, refObj2 = null;
|
||||
if (buf1.isDirect()) {
|
||||
offset1Adj = o1 + ((DirectBuffer) buf1).address();
|
||||
} else {
|
||||
offset1Adj = o1 + buf1.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj1 = buf1.array();
|
||||
}
|
||||
if (buf2.isDirect()) {
|
||||
offset2Adj = o2 + ((DirectBuffer) buf2).address();
|
||||
} else {
|
||||
offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj2 = buf2.array();
|
||||
}
|
||||
return compareToUnsafe(refObj1, offset1Adj, l1, refObj2, offset2Adj, l2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ConverterHolder {
|
||||
static final String UNSAFE_CONVERTER_NAME =
|
||||
ConverterHolder.class.getName() + "$UnsafeConverter";
|
||||
static final Converter BEST_CONVERTER = getBestConverter();
|
||||
|
||||
static Converter getBestConverter() {
|
||||
try {
|
||||
Class<?> theClass = Class.forName(UNSAFE_CONVERTER_NAME);
|
||||
|
||||
// yes, UnsafeComparer does implement Comparer<byte[]>
|
||||
@SuppressWarnings("unchecked")
|
||||
Converter converter = (Converter) theClass.getConstructor().newInstance();
|
||||
return converter;
|
||||
} catch (Throwable t) { // ensure we really catch *everything*
|
||||
return PureJavaConverter.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
static final class PureJavaConverter extends Converter {
|
||||
static final PureJavaConverter INSTANCE = new PureJavaConverter();
|
||||
|
||||
private PureJavaConverter() {}
|
||||
|
||||
@Override
|
||||
short toShort(ByteBuffer buffer, int offset) {
|
||||
return buffer.getShort(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(ByteBuffer buffer) {
|
||||
return buffer.getInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(ByteBuffer buffer, int offset) {
|
||||
return buffer.getInt(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
long toLong(ByteBuffer buffer, int offset) {
|
||||
return buffer.getLong(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
void putInt(ByteBuffer buffer, int val) {
|
||||
buffer.putInt(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putInt(ByteBuffer buffer, int index, int val) {
|
||||
buffer.putInt(index, val);
|
||||
return index + Bytes.SIZEOF_INT;
|
||||
}
|
||||
|
||||
@Override
|
||||
void putShort(ByteBuffer buffer, short val) {
|
||||
buffer.putShort(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putShort(ByteBuffer buffer, int index, short val) {
|
||||
buffer.putShort(index, val);
|
||||
return index + Bytes.SIZEOF_SHORT;
|
||||
}
|
||||
|
||||
@Override
|
||||
void putLong(ByteBuffer buffer, long val) {
|
||||
buffer.putLong(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putLong(ByteBuffer buffer, int index, long val) {
|
||||
buffer.putLong(index, val);
|
||||
return index + Bytes.SIZEOF_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
static final class UnsafeConverter extends Converter {
|
||||
|
||||
public UnsafeConverter() {}
|
||||
|
||||
static {
|
||||
if(!UNSAFE_UNALIGNED) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
short toShort(ByteBuffer buffer, int offset) {
|
||||
return UnsafeAccess.toShort(buffer, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(ByteBuffer buffer) {
|
||||
int i = UnsafeAccess.toInt(buffer, buffer.position());
|
||||
buffer.position(buffer.position() + Bytes.SIZEOF_INT);
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(ByteBuffer buffer, int offset) {
|
||||
return UnsafeAccess.toInt(buffer, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
long toLong(ByteBuffer buffer, int offset) {
|
||||
return UnsafeAccess.toLong(buffer, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
void putInt(ByteBuffer buffer, int val) {
|
||||
int newPos = UnsafeAccess.putInt(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putInt(ByteBuffer buffer, int index, int val) {
|
||||
return UnsafeAccess.putInt(buffer, index, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
void putShort(ByteBuffer buffer, short val) {
|
||||
int newPos = UnsafeAccess.putShort(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putShort(ByteBuffer buffer, int index, short val) {
|
||||
return UnsafeAccess.putShort(buffer, index, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
void putLong(ByteBuffer buffer, long val) {
|
||||
int newPos = UnsafeAccess.putLong(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putLong(ByteBuffer buffer, int index, long val) {
|
||||
return UnsafeAccess.putLong(buffer, index, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link WritableUtils#writeVLong(java.io.DataOutput, long)},
|
||||
* but writes to a {@link ByteBuffer}.
|
||||
*/
|
||||
|
@ -629,35 +889,7 @@ public final class ByteBufferUtils {
|
|||
}
|
||||
|
||||
public static int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
// NOTE: This method is copied over in BBKVComparator!!!!! For perf reasons. If you make
|
||||
// changes here, make them there too!!!!
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
long offset1Adj, offset2Adj;
|
||||
Object refObj1 = null, refObj2 = null;
|
||||
if (buf1.isDirect()) {
|
||||
offset1Adj = o1 + ((DirectBuffer) buf1).address();
|
||||
} else {
|
||||
offset1Adj = o1 + buf1.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj1 = buf1.array();
|
||||
}
|
||||
if (buf2.isDirect()) {
|
||||
offset2Adj = o2 + ((DirectBuffer) buf2).address();
|
||||
} else {
|
||||
offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj2 = buf2.array();
|
||||
}
|
||||
return compareToUnsafe(refObj1, offset1Adj, l1, refObj2, offset2Adj, l2);
|
||||
}
|
||||
int end1 = o1 + l1;
|
||||
int end2 = o2 + l2;
|
||||
for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
|
||||
int a = buf1.get(i) & 0xFF;
|
||||
int b = buf2.get(j) & 0xFF;
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
return ComparerHolder.BEST_COMPARER.compareTo(buf1, o1, l1, buf2, o2, l2);
|
||||
}
|
||||
|
||||
public static boolean equals(ByteBuffer buf1, int o1, int l1, byte[] buf2, int o2, int l2) {
|
||||
|
@ -678,53 +910,11 @@ public final class ByteBufferUtils {
|
|||
// of compiled code via jitwatch).
|
||||
|
||||
public static int compareTo(byte [] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
long offset2Adj;
|
||||
Object refObj2 = null;
|
||||
if (buf2.isDirect()) {
|
||||
offset2Adj = o2 + ((DirectBuffer)buf2).address();
|
||||
} else {
|
||||
offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj2 = buf2.array();
|
||||
}
|
||||
return compareToUnsafe(buf1, o1 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET, l1,
|
||||
refObj2, offset2Adj, l2);
|
||||
}
|
||||
int end1 = o1 + l1;
|
||||
int end2 = o2 + l2;
|
||||
for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
|
||||
int a = buf1[i] & 0xFF;
|
||||
int b = buf2.get(j) & 0xFF;
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
return ComparerHolder.BEST_COMPARER.compareTo(buf1, o1, l1, buf2, o2, l2);
|
||||
}
|
||||
|
||||
public static int compareTo(ByteBuffer buf1, int o1, int l1, byte[] buf2, int o2, int l2) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
long offset1Adj;
|
||||
Object refObj1 = null;
|
||||
if (buf1.isDirect()) {
|
||||
offset1Adj = o1 + ((DirectBuffer) buf1).address();
|
||||
} else {
|
||||
offset1Adj = o1 + buf1.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
refObj1 = buf1.array();
|
||||
}
|
||||
return compareToUnsafe(refObj1, offset1Adj, l1,
|
||||
buf2, o2 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET, l2);
|
||||
}
|
||||
int end1 = o1 + l1;
|
||||
int end2 = o2 + l2;
|
||||
for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
|
||||
int a = buf1.get(i) & 0xFF;
|
||||
int b = buf2[j] & 0xFF;
|
||||
if (a != b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
return compareTo(buf2, o2, l2, buf1, o1, l1)*-1;
|
||||
}
|
||||
|
||||
static int compareToUnsafe(Object obj1, long o1, int l1, Object obj2, long o2, int l2) {
|
||||
|
@ -777,24 +967,14 @@ public final class ByteBufferUtils {
|
|||
* @return short value at offset
|
||||
*/
|
||||
public static short toShort(ByteBuffer buffer, int offset) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toShort(buffer, offset);
|
||||
} else {
|
||||
return buffer.getShort(offset);
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toShort(buffer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int value at the given buffer's current position. Also advances the buffer's position
|
||||
*/
|
||||
public static int toInt(ByteBuffer buffer) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
int i = UnsafeAccess.toInt(buffer, buffer.position());
|
||||
buffer.position(buffer.position() + Bytes.SIZEOF_INT);
|
||||
return i;
|
||||
} else {
|
||||
return buffer.getInt();
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toInt(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -804,11 +984,7 @@ public final class ByteBufferUtils {
|
|||
* @return int value at offset
|
||||
*/
|
||||
public static int toInt(ByteBuffer buffer, int offset) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toInt(buffer, offset);
|
||||
} else {
|
||||
return buffer.getInt(offset);
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toInt(buffer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -841,11 +1017,7 @@ public final class ByteBufferUtils {
|
|||
* @return long value at offset
|
||||
*/
|
||||
public static long toLong(ByteBuffer buffer, int offset) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toLong(buffer, offset);
|
||||
} else {
|
||||
return buffer.getLong(offset);
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toLong(buffer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -855,20 +1027,11 @@ public final class ByteBufferUtils {
|
|||
* @param val int to write out
|
||||
*/
|
||||
public static void putInt(ByteBuffer buffer, int val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
int newPos = UnsafeAccess.putInt(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
} else {
|
||||
buffer.putInt(val);
|
||||
}
|
||||
ConverterHolder.BEST_CONVERTER.putInt(buffer, val);
|
||||
}
|
||||
|
||||
public static int putInt(ByteBuffer buffer, int index, int val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putInt(buffer, index, val);
|
||||
}
|
||||
buffer.putInt(index, val);
|
||||
return index + Bytes.SIZEOF_INT;
|
||||
return ConverterHolder.BEST_CONVERTER.putInt(buffer, index, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -906,20 +1069,11 @@ public final class ByteBufferUtils {
|
|||
* @param val short to write out
|
||||
*/
|
||||
public static void putShort(ByteBuffer buffer, short val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
int newPos = UnsafeAccess.putShort(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
} else {
|
||||
buffer.putShort(val);
|
||||
}
|
||||
ConverterHolder.BEST_CONVERTER.putShort(buffer, val);
|
||||
}
|
||||
|
||||
public static int putShort(ByteBuffer buffer, int index, short val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putShort(buffer, index, val);
|
||||
}
|
||||
buffer.putShort(index, val);
|
||||
return index + Bytes.SIZEOF_SHORT;
|
||||
return ConverterHolder.BEST_CONVERTER.putShort(buffer, index, val);
|
||||
}
|
||||
|
||||
public static int putAsShort(ByteBuffer buf, int index, int val) {
|
||||
|
@ -936,20 +1090,11 @@ public final class ByteBufferUtils {
|
|||
* @param val long to write out
|
||||
*/
|
||||
public static void putLong(ByteBuffer buffer, long val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
int newPos = UnsafeAccess.putLong(buffer, buffer.position(), val);
|
||||
buffer.position(newPos);
|
||||
} else {
|
||||
buffer.putLong(val);
|
||||
}
|
||||
ConverterHolder.BEST_CONVERTER.putLong(buffer, val);
|
||||
}
|
||||
|
||||
public static int putLong(ByteBuffer buffer, int index, long val) {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putLong(buffer, index, val);
|
||||
}
|
||||
buffer.putLong(index, val);
|
||||
return index + Bytes.SIZEOF_LONG;
|
||||
return ConverterHolder.BEST_CONVERTER.putLong(buffer, index, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -812,16 +812,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_LONG || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toLong(bytes, offset);
|
||||
} else {
|
||||
long l = 0;
|
||||
for(int i = offset; i < offset + length; i++) {
|
||||
l <<= 8;
|
||||
l ^= bytes[i] & 0xFF;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toLong(bytes, offset, length);
|
||||
}
|
||||
|
||||
private static IllegalArgumentException
|
||||
|
@ -853,16 +844,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
throw new IllegalArgumentException("Not enough room to put a long at"
|
||||
+ " offset " + offset + " in a " + bytes.length + " byte array");
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putLong(bytes, offset, val);
|
||||
} else {
|
||||
for(int i = offset + 7; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
val >>>= 8;
|
||||
}
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_LONG;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.putLong(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1004,16 +986,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_INT || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toInt(bytes, offset);
|
||||
} else {
|
||||
int n = 0;
|
||||
for(int i = offset; i < (offset + length); i++) {
|
||||
n <<= 8;
|
||||
n ^= bytes[i] & 0xFF;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toInt(bytes, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1088,16 +1061,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
throw new IllegalArgumentException("Not enough room to put an int at"
|
||||
+ " offset " + offset + " in a " + bytes.length + " byte array");
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putInt(bytes, offset, val);
|
||||
} else {
|
||||
for(int i= offset + 3; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
val >>>= 8;
|
||||
}
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_INT;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.putInt(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1158,15 +1122,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_SHORT || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.toShort(bytes, offset);
|
||||
} else {
|
||||
short n = 0;
|
||||
n = (short) (n ^ (bytes[offset] & 0xFF));
|
||||
n = (short) (n << 8);
|
||||
n = (short) (n ^ (bytes[offset + 1] & 0xFF));
|
||||
return n;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.toShort(bytes, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1196,14 +1152,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
throw new IllegalArgumentException("Not enough room to put a short at"
|
||||
+ " offset " + offset + " in a " + bytes.length + " byte array");
|
||||
}
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
return UnsafeAccess.putShort(bytes, offset, val);
|
||||
} else {
|
||||
bytes[offset+1] = (byte) val;
|
||||
val >>= 8;
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_SHORT;
|
||||
}
|
||||
return ConverterHolder.BEST_CONVERTER.putShort(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1432,11 +1381,161 @@ public class Bytes implements Comparable<Bytes> {
|
|||
);
|
||||
}
|
||||
|
||||
static abstract class Converter {
|
||||
abstract long toLong(byte[] bytes, int offset, int length);
|
||||
abstract int putLong(byte[] bytes, int offset, long val);
|
||||
|
||||
abstract int toInt(byte[] bytes, int offset, final int length);
|
||||
abstract int putInt(byte[] bytes, int offset, int val);
|
||||
|
||||
abstract short toShort(byte[] bytes, int offset, final int length);
|
||||
abstract int putShort(byte[] bytes, int offset, short val);
|
||||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Comparer<byte[]> lexicographicalComparerJavaImpl() {
|
||||
return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
|
||||
}
|
||||
|
||||
static class ConverterHolder {
|
||||
static final String UNSAFE_CONVERTER_NAME =
|
||||
ConverterHolder.class.getName() + "$UnsafeConverter";
|
||||
|
||||
static final Converter BEST_CONVERTER = getBestConverter();
|
||||
/**
|
||||
* Returns the Unsafe-using Converter, or falls back to the pure-Java
|
||||
* implementation if unable to do so.
|
||||
*/
|
||||
static Converter getBestConverter() {
|
||||
try {
|
||||
Class<?> theClass = Class.forName(UNSAFE_CONVERTER_NAME);
|
||||
|
||||
// yes, UnsafeComparer does implement Comparer<byte[]>
|
||||
@SuppressWarnings("unchecked")
|
||||
Converter converter = (Converter) theClass.getConstructor().newInstance();
|
||||
return converter;
|
||||
} catch (Throwable t) { // ensure we really catch *everything*
|
||||
return PureJavaConverter.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final class PureJavaConverter extends Converter {
|
||||
static final PureJavaConverter INSTANCE = new PureJavaConverter();
|
||||
|
||||
private PureJavaConverter() {}
|
||||
|
||||
@Override
|
||||
long toLong(byte[] bytes, int offset, int length) {
|
||||
long l = 0;
|
||||
for(int i = offset; i < offset + length; i++) {
|
||||
l <<= 8;
|
||||
l ^= bytes[i] & 0xFF;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
int putLong(byte[] bytes, int offset, long val) {
|
||||
for(int i = offset + 7; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
val >>>= 8;
|
||||
}
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_LONG;
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(byte[] bytes, int offset, int length) {
|
||||
int n = 0;
|
||||
for(int i = offset; i < (offset + length); i++) {
|
||||
n <<= 8;
|
||||
n ^= bytes[i] & 0xFF;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
int putInt(byte[] bytes, int offset, int val) {
|
||||
for(int i= offset + 3; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
val >>>= 8;
|
||||
}
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_INT;
|
||||
}
|
||||
|
||||
@Override
|
||||
short toShort(byte[] bytes, int offset, int length) {
|
||||
short n = 0;
|
||||
n = (short) ((n ^ bytes[offset]) & 0xFF);
|
||||
n = (short) (n << 8);
|
||||
n ^= (short) (bytes[offset+1] & 0xFF);
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
int putShort(byte[] bytes, int offset, short val) {
|
||||
bytes[offset+1] = (byte) val;
|
||||
val >>= 8;
|
||||
bytes[offset] = (byte) val;
|
||||
return offset + SIZEOF_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final class UnsafeConverter extends Converter {
|
||||
|
||||
static final Unsafe theUnsafe;
|
||||
|
||||
public UnsafeConverter() {}
|
||||
|
||||
static {
|
||||
if (UNSAFE_UNALIGNED) {
|
||||
theUnsafe = UnsafeAccess.theUnsafe;
|
||||
} else {
|
||||
// It doesn't matter what we throw;
|
||||
// it's swallowed in getBestComparer().
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
// sanity check - this should never fail
|
||||
if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
long toLong(byte[] bytes, int offset, int length) {
|
||||
return UnsafeAccess.toLong(bytes, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putLong(byte[] bytes, int offset, long val) {
|
||||
return UnsafeAccess.putLong(bytes, offset, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
int toInt(byte[] bytes, int offset, int length) {
|
||||
return UnsafeAccess.toInt(bytes, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putInt(byte[] bytes, int offset, int val) {
|
||||
return UnsafeAccess.putInt(bytes, offset, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
short toShort(byte[] bytes, int offset, int length) {
|
||||
return UnsafeAccess.toShort(bytes, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
int putShort(byte[] bytes, int offset, short val) {
|
||||
return UnsafeAccess.putShort(bytes, offset, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a lexicographical comparer implementation; either a Java
|
||||
* implementation or a faster implementation based on {@link Unsafe}.
|
||||
|
|
Loading…
Reference in New Issue