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);
+  }
 }