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 2016/03/11 05:07:25 UTC

hbase git commit: HBASE-15322 Operations using Unsafe path broken for platforms not having sun.misc.Unsafe.

Repository: hbase
Updated Branches:
  refs/heads/master bb5bfe82f -> 6628d2df1


HBASE-15322 Operations using Unsafe path broken for platforms not having sun.misc.Unsafe.


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/6628d2df
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/6628d2df
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/6628d2df

Branch: refs/heads/master
Commit: 6628d2df1183974a4e7d1ac72d73ce0810f5183e
Parents: bb5bfe8
Author: anoopsjohn <an...@gmail.com>
Authored: Fri Mar 11 09:37:00 2016 +0530
Committer: anoopsjohn <an...@gmail.com>
Committed: Fri Mar 11 09:37:00 2016 +0530

----------------------------------------------------------------------
 .../hadoop/hbase/filter/FuzzyRowFilter.java     |  8 +-
 .../apache/hadoop/hbase/nio/SingleByteBuff.java |  5 +-
 .../hadoop/hbase/util/ByteBufferUtils.java      | 10 +--
 .../org/apache/hadoop/hbase/util/Bytes.java     | 15 ++--
 .../apache/hadoop/hbase/util/UnsafeAccess.java  | 29 -------
 .../hadoop/hbase/util/UnsafeAvailChecker.java   | 86 ++++++++++++++++++++
 6 files changed, 107 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/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 0f01fb7..500d01d 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
@@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.util.ByteStringer;
 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 com.google.common.annotations.VisibleForTesting;
 import com.google.protobuf.InvalidProtocolBufferException;
@@ -60,6 +61,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
 @InterfaceAudience.Public
 @InterfaceStability.Evolving
 public class FuzzyRowFilter extends FilterBase {
+  private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
   private List<Pair<byte[], byte[]>> fuzzyKeysData;
   private boolean done = false;
 
@@ -94,7 +96,7 @@ public class FuzzyRowFilter extends FilterBase {
   }
 
   private void preprocessSearchKey(Pair<byte[], byte[]> p) {
-    if (UnsafeAccess.unaligned() == false) {
+    if (!UNSAFE_UNALIGNED) {
       // do nothing
       return;
     }
@@ -113,7 +115,7 @@ public class FuzzyRowFilter extends FilterBase {
    * @return mask array
    */
   private byte[] preprocessMask(byte[] mask) {
-    if (UnsafeAccess.unaligned() == false) {
+    if (!UNSAFE_UNALIGNED) {
       // do nothing
       return mask;
     }
@@ -318,7 +320,7 @@ public class FuzzyRowFilter extends FilterBase {
   static SatisfiesCode satisfies(boolean reverse, byte[] row, int offset, int length,
       byte[] fuzzyKeyBytes, byte[] fuzzyKeyMeta) {
 
-    if (UnsafeAccess.unaligned() == false) {
+    if (!UNSAFE_UNALIGNED) {
       return satisfiesNoUnsafe(reverse, row, offset, length, fuzzyKeyBytes, fuzzyKeyMeta);
     }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java
index 227216a..946962b 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/nio/SingleByteBuff.java
@@ -23,6 +23,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.util.ByteBufferUtils;
 import org.apache.hadoop.hbase.util.ObjectIntPair;
 import org.apache.hadoop.hbase.util.UnsafeAccess;
+import org.apache.hadoop.hbase.util.UnsafeAvailChecker;
 
 import sun.nio.ch.DirectBuffer;
 
@@ -33,8 +34,8 @@ import sun.nio.ch.DirectBuffer;
 @InterfaceAudience.Private
 public class SingleByteBuff extends ByteBuff {
 
-  private static final boolean UNSAFE_AVAIL = UnsafeAccess.isAvailable();
-  private static final boolean UNSAFE_UNALIGNED = UnsafeAccess.unaligned();
+  private static final boolean UNSAFE_AVAIL = UnsafeAvailChecker.isAvailable();
+  private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
 
   // Underlying BB
   private final ByteBuffer buf;

http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/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 7f3d777..6ca97da 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
@@ -47,8 +47,8 @@ public final class ByteBufferUtils {
   public final static int VALUE_MASK = 0x7f;
   public final static int NEXT_BIT_SHIFT = 7;
   public final static int NEXT_BIT_MASK = 1 << 7;
-  private static final boolean UNSAFE_AVAIL = UnsafeAccess.isAvailable();
-  private static final boolean UNSAFE_UNALIGNED = UnsafeAccess.unaligned();
+  private static final boolean UNSAFE_AVAIL = UnsafeAvailChecker.isAvailable();
+  private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
 
   private ByteBufferUtils() {
   }
@@ -150,7 +150,7 @@ public final class ByteBufferUtils {
    }
 
   public static byte toByte(ByteBuffer buffer, int offset) {
-    if (UnsafeAccess.isAvailable()) {
+    if (UNSAFE_AVAIL) {
       return UnsafeAccess.toByte(buffer, offset);
     } else {
       return buffer.get(offset);
@@ -202,7 +202,7 @@ public final class ByteBufferUtils {
   }
 
   public static int putByte(ByteBuffer buffer, int offset, byte b) {
-    if (UnsafeAccess.isAvailable()) {
+    if (UNSAFE_AVAIL) {
       return UnsafeAccess.putByte(buffer, offset, b);
     } else {
       buffer.put(offset, b);
@@ -369,7 +369,7 @@ public final class ByteBufferUtils {
    * @param out destination buffer
    */
   public static void copyFromBufferToBuffer(ByteBuffer in, ByteBuffer out) {
-    if (UnsafeAccess.isAvailable()) {
+    if (UNSAFE_AVAIL) {
       int length = in.remaining();
       UnsafeAccess.copy(in, in.position(), out, out.position(), length);
       out.position(out.position() + length);

http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/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 987f1e2..aae6c4c 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
@@ -132,6 +132,7 @@ public class Bytes implements Comparable<Bytes> {
   // SizeOf which uses java.lang.instrument says 24 bytes. (3 longs?)
   public static final int ESTIMATED_HEAP_TAX = 16;
 
+  private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
 
   /**
    * Returns length of the byte array, returning 0 if the array is null.
@@ -789,7 +790,7 @@ public class Bytes implements Comparable<Bytes> {
     if (length != SIZEOF_LONG || offset + length > bytes.length) {
       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
     }
-    if (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.toLong(bytes, offset);
     } else {
       long l = 0;
@@ -830,7 +831,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 (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.putLong(bytes, offset, val);
     } else {
       for(int i = offset + 7; i > offset; i--) {
@@ -981,7 +982,7 @@ public class Bytes implements Comparable<Bytes> {
     if (length != SIZEOF_INT || offset + length > bytes.length) {
       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
     }
-    if (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.toInt(bytes, offset);
     } else {
       int n = 0;
@@ -1065,7 +1066,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 (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.putInt(bytes, offset, val);
     } else {
       for(int i= offset + 3; i > offset; i--) {
@@ -1135,7 +1136,7 @@ public class Bytes implements Comparable<Bytes> {
     if (length != SIZEOF_SHORT || offset + length > bytes.length) {
       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
     }
-    if (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.toShort(bytes, offset);
     } else {
       short n = 0;
@@ -1173,7 +1174,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 (UnsafeAccess.unaligned()) {
+    if (UNSAFE_UNALIGNED) {
       return UnsafeAccess.putShort(bytes, offset, val);
     } else {
       bytes[offset+1] = (byte) val;
@@ -1477,7 +1478,7 @@ public class Bytes implements Comparable<Bytes> {
 
       static final Unsafe theUnsafe;
       static {
-        if (UnsafeAccess.unaligned()) {
+        if (UNSAFE_UNALIGNED) {
           theUnsafe = UnsafeAccess.theUnsafe;
         } else {
           // It doesn't matter what we throw;

http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/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 af2632b..9078def 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,7 +18,6 @@
 package org.apache.hadoop.hbase.util;
 
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.security.AccessController;
@@ -34,14 +33,11 @@ import sun.nio.ch.DirectBuffer;
 
 @InterfaceAudience.Private
 @InterfaceStability.Evolving
-@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="REC_CATCH_EXCEPTION",
-  justification="If exception, presume unaligned")
 public final class UnsafeAccess {
 
   private static final Log LOG = LogFactory.getLog(UnsafeAccess.class);
 
   static final Unsafe theUnsafe;
-  private static boolean unaligned;
 
   /** The offset to the first element in a byte array. */
   public static final long BYTE_ARRAY_BASE_OFFSET;
@@ -70,38 +66,13 @@ public final class UnsafeAccess {
 
     if (theUnsafe != null) {
       BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
-      try {
-        // Using java.nio.Bits#unaligned() to check for unaligned-access capability
-        Class<?> clazz = Class.forName("java.nio.Bits");
-        Method m = clazz.getDeclaredMethod("unaligned");
-        m.setAccessible(true);
-        unaligned = (boolean) m.invoke(null);
-      } catch (Exception e) {
-        unaligned = false; // FindBugs: Causes REC_CATCH_EXCEPTION. Suppressed.
-      }
     } else{
       BYTE_ARRAY_BASE_OFFSET = -1;
-      unaligned = false;
     }
   }
 
   private UnsafeAccess(){}
 
-  /**
-   * @return true when running JVM is having sun's Unsafe package available in it.
-   */
-  public static boolean isAvailable() {
-    return theUnsafe != null;
-  }
-
-  /**
-   * @return true when running JVM is having sun's Unsafe package available in it and underlying
-   *         system having unaligned-access capability.
-   */
-  public static boolean unaligned() {
-    return unaligned;
-  }
-
   // APIs to read primitive data from a byte[] using Unsafe way
   /**
    * Converts a byte array to a short value considering it was written in big-endian format.

http://git-wip-us.apache.org/repos/asf/hbase/blob/6628d2df/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java
new file mode 100644
index 0000000..2e140c4
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/UnsafeAvailChecker.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+
+@InterfaceAudience.Private
+public class UnsafeAvailChecker {
+
+  private static final String CLASS_NAME = "sun.misc.Unsafe";
+  private static final Log LOG = LogFactory.getLog(UnsafeAvailChecker.class);
+  private static boolean avail = false;
+  private static boolean unaligned = false;
+
+  static {
+    avail = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+      @Override
+      public Boolean run() {
+        try {
+          Class<?> clazz = Class.forName(CLASS_NAME);
+          Field f = clazz.getDeclaredField("theUnsafe");
+          f.setAccessible(true);
+          return f.get(null) != null;
+        } catch (Throwable e) {
+          LOG.warn("sun.misc.Unsafe is not available/accessible", e);
+        }
+        return false;
+      }
+    });
+    // When Unsafe itself is not available/accessible consider unaligned as false.
+    if (avail) {
+      try {
+        // Using java.nio.Bits#unaligned() to check for unaligned-access capability
+        Class<?> clazz = Class.forName("java.nio.Bits");
+        Method m = clazz.getDeclaredMethod("unaligned");
+        m.setAccessible(true);
+        unaligned = (boolean) m.invoke(null);
+      } catch (Exception e) {
+        LOG.warn("java.nio.Bits#unaligned() check failed."
+            + "Unsafe based read/write of primitive types won't be used", e);
+      }
+    }
+  }
+
+  /**
+   * @return true when running JVM is having sun's Unsafe package available in it and it is
+   *         accessible.
+   */
+  public static boolean isAvailable() {
+    return avail;
+  }
+
+  /**
+   * @return true when running JVM is having sun's Unsafe package available in it and underlying
+   *         system having unaligned-access capability.
+   */
+  public static boolean unaligned() {
+    return unaligned;
+  }
+
+  private UnsafeAvailChecker() {
+    // private constructor to avoid instantiation
+  }
+}
\ No newline at end of file