You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by an...@apache.org on 2015/06/20 17:22:27 UTC
hbase git commit: HBASE-13931 Move Unsafe based operations to
UnsafeAccess.
Repository: hbase
Updated Branches:
refs/heads/master db08013eb -> 04c25e0f3
HBASE-13931 Move Unsafe based operations to UnsafeAccess.
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/04c25e0f
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/04c25e0f
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/04c25e0f
Branch: refs/heads/master
Commit: 04c25e0f355aaa6ded37b0477ce126a693756b81
Parents: db08013
Author: anoopsjohn <an...@gmail.com>
Authored: Sat Jun 20 20:52:06 2015 +0530
Committer: anoopsjohn <an...@gmail.com>
Committed: Sat Jun 20 20:52:06 2015 +0530
----------------------------------------------------------------------
.../hadoop/hbase/filter/FuzzyRowFilter.java | 32 +--
.../hadoop/hbase/util/ByteBufferUtils.java | 80 +------
.../org/apache/hadoop/hbase/util/Bytes.java | 148 ++++---------
.../apache/hadoop/hbase/util/UnsafeAccess.java | 209 ++++++++++++++++++-
4 files changed, 262 insertions(+), 207 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/04c25e0f/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
index 0510b9c..f208eb2 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java
@@ -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
http://git-wip-us.apache.org/repos/asf/hbase/blob/04c25e0f/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java
index 9d14117..6636679 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ByteBufferUtils.java
@@ -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);
http://git-wip-us.apache.org/repos/asf/hbase/blob/04c25e0f/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
index 683b559..bc245a8 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
@@ -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,7 +1529,7 @@ 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);
}
@@ -1586,15 +1537,6 @@ public class Bytes implements Comparable<Bytes> {
}
/**
- * Checks if Unsafe is available
- * @return true, if available, false - otherwise
- */
- public static boolean isAvailable()
- {
- return theUnsafe != null;
- }
-
- /**
* Lexicographically compare two arrays.
*
* @param buffer1 left operand
@@ -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
http://git-wip-us.apache.org/repos/asf/hbase/blob/04c25e0f/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java
index c9a03d2..51dd643 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAccess.java
@@ -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);
+ }
}