HBASE-13931 Move Unsafe based operations to UnsafeAccess.
This commit is contained in:
parent
db08013ebe
commit
04c25e0f35
|
@ -331,19 +331,13 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
}
|
||||
length = Math.min(length, fuzzyKeyBytes.length);
|
||||
int numWords = length / Bytes.SIZEOF_LONG;
|
||||
int offsetAdj = offset + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
|
||||
int j = numWords << 3; // numWords * SIZEOF_LONG;
|
||||
|
||||
for (int i = 0; i < j; i += Bytes.SIZEOF_LONG) {
|
||||
|
||||
long fuzzyBytes =
|
||||
UnsafeAccess.theUnsafe.getLong(fuzzyKeyBytes, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) i);
|
||||
long fuzzyMeta =
|
||||
UnsafeAccess.theUnsafe.getLong(fuzzyKeyMeta, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) i);
|
||||
long rowValue = UnsafeAccess.theUnsafe.getLong(row, offsetAdj + (long) i);
|
||||
long fuzzyBytes = UnsafeAccess.toLong(fuzzyKeyBytes, i);
|
||||
long fuzzyMeta = UnsafeAccess.toLong(fuzzyKeyMeta, i);
|
||||
long rowValue = UnsafeAccess.toLong(row, offset + i);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
return SatisfiesCode.NEXT_EXISTS;
|
||||
|
@ -353,13 +347,9 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
int off = j;
|
||||
|
||||
if (length - off >= Bytes.SIZEOF_INT) {
|
||||
int fuzzyBytes =
|
||||
UnsafeAccess.theUnsafe.getInt(fuzzyKeyBytes, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) off);
|
||||
int fuzzyMeta =
|
||||
UnsafeAccess.theUnsafe.getInt(fuzzyKeyMeta, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) off);
|
||||
int rowValue = UnsafeAccess.theUnsafe.getInt(row, offsetAdj + (long) off);
|
||||
int fuzzyBytes = UnsafeAccess.toInt(fuzzyKeyBytes, off);
|
||||
int fuzzyMeta = UnsafeAccess.toInt(fuzzyKeyMeta, off);
|
||||
int rowValue = UnsafeAccess.toInt(row, offset + off);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
return SatisfiesCode.NEXT_EXISTS;
|
||||
|
@ -368,13 +358,9 @@ public class FuzzyRowFilter extends FilterBase {
|
|||
}
|
||||
|
||||
if (length - off >= Bytes.SIZEOF_SHORT) {
|
||||
short fuzzyBytes =
|
||||
UnsafeAccess.theUnsafe.getShort(fuzzyKeyBytes, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) off);
|
||||
short fuzzyMeta =
|
||||
UnsafeAccess.theUnsafe.getShort(fuzzyKeyMeta, UnsafeAccess.BYTE_ARRAY_BASE_OFFSET
|
||||
+ (long) off);
|
||||
short rowValue = UnsafeAccess.theUnsafe.getShort(row, offsetAdj + (long) off);
|
||||
short fuzzyBytes = UnsafeAccess.toShort(fuzzyKeyBytes, off);
|
||||
short fuzzyMeta = UnsafeAccess.toShort(fuzzyKeyMeta, off);
|
||||
short rowValue = UnsafeAccess.toShort(row, offset + off);
|
||||
if ((rowValue & fuzzyMeta) != (fuzzyBytes)) {
|
||||
// We always return NEXT_EXISTS
|
||||
// even if it does not (in this case getNextForFuzzyRule
|
||||
|
|
|
@ -28,8 +28,6 @@ import org.apache.hadoop.hbase.classification.InterfaceStability;
|
|||
import org.apache.hadoop.io.IOUtils;
|
||||
import org.apache.hadoop.io.WritableUtils;
|
||||
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
/**
|
||||
* Utility functions for working with byte buffers, such as reading/writing
|
||||
* variable-length long numbers.
|
||||
|
@ -519,26 +517,12 @@ public final class ByteBufferUtils {
|
|||
*/
|
||||
public static short toShort(ByteBuffer buffer, int offset) {
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return toShortUnsafe(buffer, offset);
|
||||
return UnsafeAccess.toShort(buffer, offset);
|
||||
} else {
|
||||
return buffer.getShort(offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static short toShortUnsafe(ByteBuffer buf, long offset) {
|
||||
short ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = UnsafeAccess.theUnsafe.getShort(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = UnsafeAccess.theUnsafe.getShort(buf.array(),
|
||||
UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
return Short.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int value at the given buffer's offset.
|
||||
* @param buffer
|
||||
|
@ -547,26 +531,12 @@ public final class ByteBufferUtils {
|
|||
*/
|
||||
public static int toInt(ByteBuffer buffer, int offset) {
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return toIntUnsafe(buffer, offset);
|
||||
return UnsafeAccess.toInt(buffer, offset);
|
||||
} else {
|
||||
return buffer.getInt(offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static int toIntUnsafe(ByteBuffer buf, long offset) {
|
||||
int ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = UnsafeAccess.theUnsafe.getInt(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = UnsafeAccess.theUnsafe.getInt(buf.array(),
|
||||
UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
return Integer.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a long value at the given buffer's offset.
|
||||
* @param buffer
|
||||
|
@ -575,26 +545,12 @@ public final class ByteBufferUtils {
|
|||
*/
|
||||
public static long toLong(ByteBuffer buffer, int offset) {
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return toLongUnsafe(buffer, offset);
|
||||
return UnsafeAccess.toLong(buffer, offset);
|
||||
} else {
|
||||
return buffer.getLong(offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static long toLongUnsafe(ByteBuffer buf, long offset) {
|
||||
long ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = UnsafeAccess.theUnsafe.getLong(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = UnsafeAccess.theUnsafe.getLong(buf.array(),
|
||||
UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
return Long.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the bytes from given array's offset to length part into the given buffer. Puts the bytes
|
||||
* to buffer's current position. This also advances the position in the 'out' buffer by 'length'
|
||||
|
@ -609,7 +565,7 @@ public final class ByteBufferUtils {
|
|||
// Move the position in out by length
|
||||
out.position(out.position() + length);
|
||||
} else if (UnsafeAccess.isAvailable()) {
|
||||
copyUnsafe(in, inOffset, out, out.position(), length);
|
||||
UnsafeAccess.copy(in, inOffset, out, out.position(), length);
|
||||
// Move the position in out by length
|
||||
out.position(out.position() + length);
|
||||
} else {
|
||||
|
@ -617,32 +573,6 @@ public final class ByteBufferUtils {
|
|||
}
|
||||
}
|
||||
|
||||
static void copyUnsafe(byte[] src, int srcOffset, ByteBuffer dest, int destOffset, int length) {
|
||||
long destAddress = destOffset;
|
||||
Object destBase = null;
|
||||
if (dest.isDirect()) {
|
||||
destAddress = destAddress + ((DirectBuffer) dest).address();
|
||||
} else {
|
||||
destAddress = destAddress + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
|
||||
destBase = dest.array();
|
||||
}
|
||||
long srcAddress = srcOffset + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
UnsafeAccess.theUnsafe.copyMemory(src, srcAddress, destBase, destAddress, length);
|
||||
}
|
||||
|
||||
static void copyUnsafe(ByteBuffer src, int srcOffset, byte[] dest, int destOffset, int length) {
|
||||
long srcAddress = srcOffset;
|
||||
Object srcBase = null;
|
||||
if (src.isDirect()) {
|
||||
srcAddress = srcAddress + ((DirectBuffer) src).address();
|
||||
} else {
|
||||
srcAddress = srcAddress + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET + src.arrayOffset();
|
||||
srcBase = src.array();
|
||||
}
|
||||
long destAddress = destOffset + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
UnsafeAccess.theUnsafe.copyMemory(srcBase, srcAddress, dest, destAddress, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies specified number of bytes from given offset of 'in' ByteBuffer to the array.
|
||||
* @param out
|
||||
|
@ -656,7 +586,7 @@ public final class ByteBufferUtils {
|
|||
if (in.hasArray()) {
|
||||
System.arraycopy(in.array(), sourceOffset + in.arrayOffset(), out, destinationOffset, length);
|
||||
} else if (UnsafeAccess.isAvailable()) {
|
||||
copyUnsafe(in, sourceOffset, out, destinationOffset, length);
|
||||
UnsafeAccess.copy(in, sourceOffset, out, destinationOffset, length);
|
||||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
out[destinationOffset + i] = in.get(sourceOffset + i);
|
||||
|
|
|
@ -24,14 +24,10 @@ import static com.google.common.base.Preconditions.checkPositionIndex;
|
|||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -57,8 +53,6 @@ import sun.misc.Unsafe;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.apache.hadoop.hbase.util.Bytes.LexicographicalComparerHolder.UnsafeComparer;
|
||||
|
||||
/**
|
||||
* Utility class that handles byte arrays, conversions to/from other types,
|
||||
* comparisons, hash code generation, manufacturing keys for HashMaps or
|
||||
|
@ -795,8 +789,8 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_LONG || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
|
||||
}
|
||||
if (UnsafeComparer.isAvailable()) {
|
||||
return toLongUnsafe(bytes, offset);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.toLong(bytes, offset);
|
||||
} else {
|
||||
long l = 0;
|
||||
for(int i = offset; i < offset + length; i++) {
|
||||
|
@ -836,8 +830,8 @@ 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 (UnsafeComparer.isAvailable()) {
|
||||
return putLongUnsafe(bytes, offset, val);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.putLong(bytes, offset, val);
|
||||
} else {
|
||||
for(int i = offset + 7; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
|
@ -854,15 +848,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param offset position in the array
|
||||
* @param val long to write out
|
||||
* @return incremented offset
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
public static int putLongUnsafe(byte[] bytes, int offset, long val)
|
||||
{
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
val = Long.reverseBytes(val);
|
||||
}
|
||||
UnsafeComparer.theUnsafe.putLong(bytes, (long) offset +
|
||||
UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
|
||||
return offset + SIZEOF_LONG;
|
||||
@Deprecated
|
||||
public static int putLongUnsafe(byte[] bytes, int offset, long val) {
|
||||
return UnsafeAccess.putLong(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -991,8 +981,8 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_INT || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
|
||||
}
|
||||
if (UnsafeComparer.isAvailable()) {
|
||||
return toIntUnsafe(bytes, offset);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.toInt(bytes, offset);
|
||||
} else {
|
||||
int n = 0;
|
||||
for(int i = offset; i < (offset + length); i++) {
|
||||
|
@ -1008,15 +998,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the int value
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int toIntUnsafe(byte[] bytes, int offset) {
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
return Integer.reverseBytes(UnsafeComparer.theUnsafe.getInt(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return UnsafeComparer.theUnsafe.getInt(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
return UnsafeAccess.toInt(bytes, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1024,15 +1010,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the short value
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
@Deprecated
|
||||
public static short toShortUnsafe(byte[] bytes, int offset) {
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
return Short.reverseBytes(UnsafeComparer.theUnsafe.getShort(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return UnsafeComparer.theUnsafe.getShort(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
return UnsafeAccess.toShort(bytes, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1040,15 +1022,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the long value
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
@Deprecated
|
||||
public static long toLongUnsafe(byte[] bytes, int offset) {
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
return Long.reverseBytes(UnsafeComparer.theUnsafe.getLong(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return UnsafeComparer.theUnsafe.getLong(bytes,
|
||||
(long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
return UnsafeAccess.toLong(bytes, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1087,8 +1065,8 @@ 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 (UnsafeComparer.isAvailable()) {
|
||||
return putIntUnsafe(bytes, offset, val);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.putInt(bytes, offset, val);
|
||||
} else {
|
||||
for(int i= offset + 3; i > offset; i--) {
|
||||
bytes[i] = (byte) val;
|
||||
|
@ -1105,15 +1083,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param offset position in the array
|
||||
* @param val int to write out
|
||||
* @return incremented offset
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
public static int putIntUnsafe(byte[] bytes, int offset, int val)
|
||||
{
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
val = Integer.reverseBytes(val);
|
||||
}
|
||||
UnsafeComparer.theUnsafe.putInt(bytes, (long) offset +
|
||||
UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
|
||||
return offset + SIZEOF_INT;
|
||||
@Deprecated
|
||||
public static int putIntUnsafe(byte[] bytes, int offset, int val) {
|
||||
return UnsafeAccess.putInt(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1161,8 +1135,8 @@ public class Bytes implements Comparable<Bytes> {
|
|||
if (length != SIZEOF_SHORT || offset + length > bytes.length) {
|
||||
throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
|
||||
}
|
||||
if (UnsafeComparer.isAvailable()) {
|
||||
return toShortUnsafe(bytes, offset);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.toShort(bytes, offset);
|
||||
} else {
|
||||
short n = 0;
|
||||
n ^= bytes[offset] & 0xFF;
|
||||
|
@ -1199,8 +1173,8 @@ 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 (UnsafeComparer.isAvailable()) {
|
||||
return putShortUnsafe(bytes, offset, val);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
return UnsafeAccess.putShort(bytes, offset, val);
|
||||
} else {
|
||||
bytes[offset+1] = (byte) val;
|
||||
val >>= 8;
|
||||
|
@ -1215,15 +1189,11 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* @param offset position in the array
|
||||
* @param val short to write out
|
||||
* @return incremented offset
|
||||
* @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0.
|
||||
*/
|
||||
public static int putShortUnsafe(byte[] bytes, int offset, short val)
|
||||
{
|
||||
if (UnsafeComparer.littleEndian) {
|
||||
val = Short.reverseBytes(val);
|
||||
}
|
||||
UnsafeComparer.theUnsafe.putShort(bytes, (long) offset +
|
||||
UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
|
||||
return offset + SIZEOF_SHORT;
|
||||
@Deprecated
|
||||
public static int putShortUnsafe(byte[] bytes, int offset, short val) {
|
||||
return UnsafeAccess.putShort(bytes, offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1506,30 +1476,14 @@ public class Bytes implements Comparable<Bytes> {
|
|||
INSTANCE;
|
||||
|
||||
static final Unsafe theUnsafe;
|
||||
|
||||
/** The offset to the first element in a byte array. */
|
||||
static final int BYTE_ARRAY_BASE_OFFSET;
|
||||
|
||||
static {
|
||||
theUnsafe = (Unsafe) AccessController.doPrivileged(
|
||||
new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
f.setAccessible(true);
|
||||
return f.get(null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// It doesn't matter what we throw;
|
||||
// it's swallowed in getBestComparer().
|
||||
throw new Error();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
|
||||
if (UnsafeAccess.isAvailable()) {
|
||||
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) {
|
||||
|
@ -1537,9 +1491,6 @@ public class Bytes implements Comparable<Bytes> {
|
|||
}
|
||||
}
|
||||
|
||||
static final boolean littleEndian =
|
||||
ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
/**
|
||||
* Returns true if x1 is less than x2, when both values are treated as
|
||||
* unsigned long.
|
||||
|
@ -1548,7 +1499,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* Big Endian format.
|
||||
*/
|
||||
static boolean lessThanUnsignedLong(long x1, long x2) {
|
||||
if (littleEndian) {
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
x1 = Long.reverseBytes(x1);
|
||||
x2 = Long.reverseBytes(x2);
|
||||
}
|
||||
|
@ -1563,7 +1514,7 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* Big Endian format.
|
||||
*/
|
||||
static boolean lessThanUnsignedInt(int x1, int x2) {
|
||||
if (littleEndian) {
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
x1 = Integer.reverseBytes(x1);
|
||||
x2 = Integer.reverseBytes(x2);
|
||||
}
|
||||
|
@ -1578,22 +1529,13 @@ public class Bytes implements Comparable<Bytes> {
|
|||
* Big Endian format.
|
||||
*/
|
||||
static boolean lessThanUnsignedShort(short x1, short x2) {
|
||||
if (littleEndian) {
|
||||
if (UnsafeAccess.littleEndian) {
|
||||
x1 = Short.reverseBytes(x1);
|
||||
x2 = Short.reverseBytes(x2);
|
||||
}
|
||||
return (x1 & 0xffff) < (x2 & 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Unsafe is available
|
||||
* @return true, if available, false - otherwise
|
||||
*/
|
||||
public static boolean isAvailable()
|
||||
{
|
||||
return theUnsafe != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexicographically compare two arrays.
|
||||
*
|
||||
|
@ -1617,8 +1559,8 @@ public class Bytes implements Comparable<Bytes> {
|
|||
}
|
||||
final int minLength = Math.min(length1, length2);
|
||||
final int minWords = minLength / SIZEOF_LONG;
|
||||
final long offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
|
||||
final long offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
|
||||
final long offset1Adj = offset1 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
final long offset2Adj = offset2 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET;
|
||||
|
||||
/*
|
||||
* Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.hadoop.hbase.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
@ -28,6 +29,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
|||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
@InterfaceAudience.Private
|
||||
@InterfaceStability.Evolving
|
||||
|
@ -35,10 +37,13 @@ public final class UnsafeAccess {
|
|||
|
||||
private static final Log LOG = LogFactory.getLog(UnsafeAccess.class);
|
||||
|
||||
public static final Unsafe theUnsafe;
|
||||
static final Unsafe theUnsafe;
|
||||
|
||||
/** The offset to the first element in a byte array. */
|
||||
public static final int BYTE_ARRAY_BASE_OFFSET;
|
||||
static final long BYTE_ARRAY_BASE_OFFSET;
|
||||
|
||||
static final boolean littleEndian = ByteOrder.nativeOrder()
|
||||
.equals(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
static {
|
||||
theUnsafe = (Unsafe) AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
|
@ -63,11 +68,203 @@ public final class UnsafeAccess {
|
|||
}
|
||||
|
||||
private UnsafeAccess(){}
|
||||
|
||||
|
||||
/**
|
||||
* @return true when the running JVM is having sun's Unsafe package available in it.
|
||||
*/
|
||||
public static boolean isAvailable() {
|
||||
return theUnsafe != null;
|
||||
}
|
||||
|
||||
public static final boolean littleEndian = ByteOrder.nativeOrder()
|
||||
.equals(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// APIs to read primitive data from a byte[] using Unsafe way
|
||||
/**
|
||||
* Converts a byte array to a short value.
|
||||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the short value
|
||||
*/
|
||||
public static short toShort(byte[] bytes, int offset) {
|
||||
if (littleEndian) {
|
||||
return Short.reverseBytes(theUnsafe.getShort(bytes, offset + BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return theUnsafe.getShort(bytes, offset + BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array to an int value.
|
||||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the int value
|
||||
*/
|
||||
public static int toInt(byte[] bytes, int offset) {
|
||||
if (littleEndian) {
|
||||
return Integer.reverseBytes(theUnsafe.getInt(bytes, offset + BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return theUnsafe.getInt(bytes, offset + BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array to a long value.
|
||||
* @param bytes byte array
|
||||
* @param offset offset into array
|
||||
* @return the long value
|
||||
*/
|
||||
public static long toLong(byte[] bytes, int offset) {
|
||||
if (littleEndian) {
|
||||
return Long.reverseBytes(theUnsafe.getLong(bytes, offset + BYTE_ARRAY_BASE_OFFSET));
|
||||
} else {
|
||||
return theUnsafe.getLong(bytes, offset + BYTE_ARRAY_BASE_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
// APIs to write primitive data to a byte[] using Unsafe way
|
||||
/**
|
||||
* Put a short value out to the specified byte array position.
|
||||
* @param bytes the byte array
|
||||
* @param offset position in the array
|
||||
* @param val short to write out
|
||||
* @return incremented offset
|
||||
*/
|
||||
public static int putShort(byte[] bytes, int offset, short val) {
|
||||
if (littleEndian) {
|
||||
val = Short.reverseBytes(val);
|
||||
}
|
||||
theUnsafe.putShort(bytes, offset + BYTE_ARRAY_BASE_OFFSET, val);
|
||||
return offset + Bytes.SIZEOF_SHORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an int value out to the specified byte array position.
|
||||
* @param bytes the byte array
|
||||
* @param offset position in the array
|
||||
* @param val int to write out
|
||||
* @return incremented offset
|
||||
*/
|
||||
public static int putInt(byte[] bytes, int offset, int val) {
|
||||
if (littleEndian) {
|
||||
val = Integer.reverseBytes(val);
|
||||
}
|
||||
theUnsafe.putInt(bytes, offset + BYTE_ARRAY_BASE_OFFSET, val);
|
||||
return offset + Bytes.SIZEOF_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a long value out to the specified byte array position.
|
||||
* @param bytes the byte array
|
||||
* @param offset position in the array
|
||||
* @param val long to write out
|
||||
* @return incremented offset
|
||||
*/
|
||||
public static int putLong(byte[] bytes, int offset, long val) {
|
||||
if (littleEndian) {
|
||||
val = Long.reverseBytes(val);
|
||||
}
|
||||
theUnsafe.putLong(bytes, offset + BYTE_ARRAY_BASE_OFFSET, val);
|
||||
return offset + Bytes.SIZEOF_LONG;
|
||||
}
|
||||
|
||||
// APIs to read primitive data from a ByteBuffer using Unsafe way
|
||||
/**
|
||||
* Reads a short value at the given buffer's offset.
|
||||
* @param buf
|
||||
* @param offset
|
||||
* @return short value at offset
|
||||
*/
|
||||
public static short toShort(ByteBuffer buf, int offset) {
|
||||
short ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = theUnsafe.getShort(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = theUnsafe.getShort(buf.array(), BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (littleEndian) {
|
||||
return Short.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int value at the given buffer's offset.
|
||||
* @param buf
|
||||
* @param offset
|
||||
* @return int value at offset
|
||||
*/
|
||||
public static int toInt(ByteBuffer buf, int offset) {
|
||||
int ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = theUnsafe.getInt(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = theUnsafe.getInt(buf.array(), BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (littleEndian) {
|
||||
return Integer.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a long value at the given buffer's offset.
|
||||
* @param buf
|
||||
* @param offset
|
||||
* @return long value at offset
|
||||
*/
|
||||
public static long toLong(ByteBuffer buf, int offset) {
|
||||
long ret;
|
||||
if (buf.isDirect()) {
|
||||
ret = theUnsafe.getLong(((DirectBuffer) buf).address() + offset);
|
||||
} else {
|
||||
ret = theUnsafe.getLong(buf.array(), BYTE_ARRAY_BASE_OFFSET + buf.arrayOffset() + offset);
|
||||
}
|
||||
if (littleEndian) {
|
||||
return Long.reverseBytes(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// APIs to copy data. This will be direct memory location copy and will be much faster
|
||||
/**
|
||||
* Copies the bytes from given array's offset to length part into the given buffer. Puts the bytes
|
||||
* to buffer's current position.
|
||||
* @param src
|
||||
* @param srcOffset
|
||||
* @param dest
|
||||
* @param destOffset
|
||||
* @param length
|
||||
*/
|
||||
public static void copy(byte[] src, int srcOffset, ByteBuffer dest, int destOffset, int length) {
|
||||
long destAddress = destOffset;
|
||||
Object destBase = null;
|
||||
if (dest.isDirect()) {
|
||||
destAddress = destAddress + ((DirectBuffer) dest).address();
|
||||
} else {
|
||||
destAddress = destAddress + BYTE_ARRAY_BASE_OFFSET + dest.arrayOffset();
|
||||
destBase = dest.array();
|
||||
}
|
||||
long srcAddress = srcOffset + BYTE_ARRAY_BASE_OFFSET;
|
||||
theUnsafe.copyMemory(src, srcAddress, destBase, destAddress, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies specified number of bytes from given offset of 'in' ByteBuffer to the array.
|
||||
* @param src
|
||||
* @param srcOffset
|
||||
* @param dest
|
||||
* @param destOffset
|
||||
* @param length
|
||||
*/
|
||||
public static void copy(ByteBuffer src, int srcOffset, byte[] dest, int destOffset,
|
||||
int length) {
|
||||
long srcAddress = srcOffset;
|
||||
Object srcBase = null;
|
||||
if (src.isDirect()) {
|
||||
srcAddress = srcAddress + ((DirectBuffer) src).address();
|
||||
} else {
|
||||
srcAddress = srcAddress + BYTE_ARRAY_BASE_OFFSET + src.arrayOffset();
|
||||
srcBase = src.array();
|
||||
}
|
||||
long destAddress = destOffset + BYTE_ARRAY_BASE_OFFSET;
|
||||
theUnsafe.copyMemory(srcBase, srcAddress, dest, destAddress, length);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue