HBASE-15322 Operations using Unsafe path broken for platforms not having sun.misc.Unsafe.
This commit is contained in:
parent
bb5bfe82f2
commit
6628d2df11
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue