>From Wail Alkowaileet <[email protected]>:

Wail Alkowaileet has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17421 )


Change subject: [WIP] Utilize unsafe
......................................................................

[WIP] Utilize unsafe

Details:
The micro benchmark shows ~4.5x improvment for
writing long values and ~2.4x for reading

Example for writing/reading 1M long value
Writing unsafe took: 585958
Unsafe avg time to read: 35972

Writing safe took: 2726958
Safe avg time to read: 86079

Change-Id: Icd8f8862ce03553ce2a3b6f8e1a8131bb2b78761
---
A 
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
M 
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
M 
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
M 
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
M 
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
A 
hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
A 
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
M 
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
15 files changed, 754 insertions(+), 61 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/21/17421/1

diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
index cba8e63..43e706d 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
@@ -18,68 +18,48 @@
  */
 package org.apache.asterix.runtime.aggregates.serializable.std;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 public class BufferSerDeUtil {

     public static double getDouble(byte[] bytes, int offset) {
-        return Double.longBitsToDouble(getLong(bytes, offset));
+        return ACCESSOR.getDouble(bytes, offset);
     }

     public static float getFloat(byte[] bytes, int offset) {
-        return Float.intBitsToFloat(getInt(bytes, offset));
+        return ACCESSOR.getFloat(bytes, offset);
     }

     public static boolean getBoolean(byte[] bytes, int offset) {
-        if (bytes[offset] == 0)
-            return false;
-        else
-            return true;
+        return bytes[offset] != 0;
     }

     public static int getInt(byte[] bytes, int offset) {
-        return ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) << 
16) + ((bytes[offset + 2] & 0xff) << 8)
-                + ((bytes[offset + 3] & 0xff) << 0);
+        return ACCESSOR.getInt(bytes, offset);
     }

     public static long getLong(byte[] bytes, int offset) {
-        return (((long) (bytes[offset] & 0xff)) << 56) + (((long) 
(bytes[offset + 1] & 0xff)) << 48)
-                + (((long) (bytes[offset + 2] & 0xff)) << 40) + (((long) 
(bytes[offset + 3] & 0xff)) << 32)
-                + (((long) (bytes[offset + 4] & 0xff)) << 24) + (((long) 
(bytes[offset + 5] & 0xff)) << 16)
-                + (((long) (bytes[offset + 6] & 0xff)) << 8) + (((long) 
(bytes[offset + 7] & 0xff)) << 0);
+        return ACCESSOR.getLong(bytes, offset);
     }

     public static void writeBoolean(boolean value, byte[] bytes, int offset) {
-        if (value)
-            bytes[offset] = (byte) 1;
-        else
-            bytes[offset] = (byte) 0;
+        bytes[offset] = (byte) (value ? 1 : 0);
     }

     public static void writeInt(int value, byte[] bytes, int offset) {
-        bytes[offset++] = (byte) (value >> 24);
-        bytes[offset++] = (byte) (value >> 16);
-        bytes[offset++] = (byte) (value >> 8);
-        bytes[offset++] = (byte) (value);
+        ACCESSOR.putInt(bytes, offset, value);
     }

     public static void writeLong(long value, byte[] bytes, int offset) {
-        bytes[offset++] = (byte) (value >> 56);
-        bytes[offset++] = (byte) (value >> 48);
-        bytes[offset++] = (byte) (value >> 40);
-        bytes[offset++] = (byte) (value >> 32);
-        bytes[offset++] = (byte) (value >> 24);
-        bytes[offset++] = (byte) (value >> 16);
-        bytes[offset++] = (byte) (value >> 8);
-        bytes[offset++] = (byte) (value);
+        ACCESSOR.putLong(bytes, offset, value);
     }

     public static void writeDouble(double value, byte[] bytes, int offset) {
-        long lValue = Double.doubleToLongBits(value);
-        writeLong(lValue, bytes, offset);
+        ACCESSOR.putDouble(bytes, offset, value);
     }

     public static void writeFloat(float value, byte[] bytes, int offset) {
-        int iValue = Float.floatToIntBits(value);
-        writeInt(iValue, bytes, offset);
+        ACCESSOR.putFloat(bytes, offset, value);
     }

 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
new file mode 100644
index 0000000..31fe95d
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hyracks.bytes;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class ByteAccessorProvider {
+    private static final Logger LOGGER = LogManager.getLogger();
+    public static final IByteValueAccessor ACCESSOR = getAccessor();
+
+    private static IByteValueAccessor getAccessor() {
+        if (UnsafeByteValueAccessor.isAccessible()) {
+            LOGGER.debug("Unsafe byte accessor is initialized");
+            return UnsafeByteValueAccessor.INSTANCE;
+        }
+        LOGGER.debug("Safe byte accessor is initialized");
+        return SafeByteValueAccessor.INSTANCE;
+    }
+
+    private ByteAccessorProvider() {
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
new file mode 100644
index 0000000..4fb7c59
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.hyracks.bytes;
+
+public interface IByteValueAccessor {
+    byte getByte(byte[] bytes, int offset);
+
+    short getShort(byte[] bytes, int offset);
+
+    int getInt(byte[] bytes, int offset);
+
+    long getLong(byte[] bytes, int offset);
+
+    float getFloat(byte[] bytes, int offset);
+
+    double getDouble(byte[] bytes, int offset);
+
+    void putByte(byte[] bytes, int offset, byte value);
+
+    void putShort(byte[] bytes, int offset, short value);
+
+    void putInt(byte[] bytes, int offset, int value);
+
+    void putLong(byte[] bytes, int offset, long value);
+
+    void putFloat(byte[] bytes, int offset, float value);
+
+    void putDouble(byte[] bytes, int offset, double value);
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
new file mode 100644
index 0000000..1799fe0
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
@@ -0,0 +1,105 @@
+/*
+ * 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.hyracks.bytes;
+
+final class SafeByteValueAccessor implements IByteValueAccessor {
+    static final IByteValueAccessor INSTANCE = new SafeByteValueAccessor();
+
+    private SafeByteValueAccessor() {
+    }
+
+    @Override
+    public byte getByte(byte[] bytes, int offset) {
+        return bytes[offset];
+    }
+
+    @Override
+    public short getShort(byte[] bytes, int offset) {
+        return (short) (((bytes[offset] & 0xff) << 8) + (bytes[offset + 1] & 
0xff));
+    }
+
+    @Override
+    public int getInt(byte[] bytes, int offset) {
+        return ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) << 
16) + ((bytes[offset + 2] & 0xff) << 8)
+                + ((bytes[offset + 3] & 0xff));
+    }
+
+    @Override
+    public long getLong(byte[] bytes, int offset) {
+        return (((long) (bytes[offset] & 0xff)) << 56) + (((long) 
(bytes[offset + 1] & 0xff)) << 48)
+                + (((long) (bytes[offset + 2] & 0xff)) << 40) + (((long) 
(bytes[offset + 3] & 0xff)) << 32)
+                + (((long) (bytes[offset + 4] & 0xff)) << 24) + (((long) 
(bytes[offset + 5] & 0xff)) << 16)
+                + (((long) (bytes[offset + 6] & 0xff)) << 8) + (((long) 
(bytes[offset + 7] & 0xff)));
+    }
+
+    @Override
+    public float getFloat(byte[] bytes, int offset) {
+        int bits = getInt(bytes, offset);
+        return Float.intBitsToFloat(bits);
+    }
+
+    @Override
+    public double getDouble(byte[] bytes, int offset) {
+        long bits = getLong(bytes, offset);
+        return Double.longBitsToDouble(bits);
+    }
+
+    @Override
+    public void putByte(byte[] bytes, int offset, byte value) {
+        bytes[offset] = value;
+    }
+
+    @Override
+    public void putShort(byte[] bytes, int offset, short value) {
+        bytes[offset] = (byte) ((value >>> 8) & 0xFF);
+        bytes[offset + 1] = (byte) ((value) & 0xFF);
+    }
+
+    @Override
+    public void putInt(byte[] bytes, int offset, int value) {
+        bytes[offset] = (byte) ((value >>> 24) & 0xFF);
+        bytes[offset + 1] = (byte) ((value >>> 16) & 0xFF);
+        bytes[offset + 2] = (byte) ((value >>> 8) & 0xFF);
+        bytes[offset + 3] = (byte) (value & 0xFF);
+    }
+
+    @Override
+    public void putLong(byte[] bytes, int offset, long value) {
+        bytes[offset] = (byte) ((value >>> 56) & 0xFF);
+        bytes[offset + 1] = (byte) ((value >>> 48) & 0xFF);
+        bytes[offset + 2] = (byte) ((value >>> 40) & 0xFF);
+        bytes[offset + 3] = (byte) ((value >>> 32) & 0xFF);
+        bytes[offset + 4] = (byte) ((value >>> 24) & 0xFF);
+        bytes[offset + 5] = (byte) ((value >>> 16) & 0xFF);
+        bytes[offset + 6] = (byte) ((value >>> 8) & 0xFF);
+        bytes[offset + 7] = (byte) (value & 0xFF);
+    }
+
+    @Override
+    public void putFloat(byte[] bytes, int offset, float value) {
+        int bits = Float.floatToIntBits(value);
+        putInt(bytes, offset, bits);
+    }
+
+    @Override
+    public void putDouble(byte[] bytes, int offset, double value) {
+        long bits = Double.doubleToLongBits(value);
+        putLong(bytes, offset, bits);
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
new file mode 100644
index 0000000..b0060f2
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
@@ -0,0 +1,121 @@
+/*
+ * 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.hyracks.bytes;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+final class UnsafeByteValueAccessor implements IByteValueAccessor {
+    static final IByteValueAccessor INSTANCE = new UnsafeByteValueAccessor();
+    private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+
+    private static final long BYTE_ARRAY_BASE_OFFSET = 
UNSAFE.arrayBaseOffset(byte[].class);
+
+    static sun.misc.Unsafe getUnsafe() {
+        sun.misc.Unsafe unsafe = null;
+        try {
+            unsafe = AccessController.doPrivileged(new 
PrivilegedExceptionAction<>() {
+                @Override
+                public sun.misc.Unsafe run() throws Exception {
+                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+                    for (Field f : k.getDeclaredFields()) {
+                        f.setAccessible(true);
+                        Object x = f.get(null);
+                        if (k.isInstance(x)) {
+                            return k.cast(x);
+                        }
+                    }
+                    return null;
+                }
+            });
+        } catch (Throwable e) {
+            // do nothing
+        }
+        return unsafe;
+    }
+
+    static boolean isAccessible() {
+        return UNSAFE != null;
+    }
+
+    private UnsafeByteValueAccessor() {
+    }
+
+    @Override
+    public byte getByte(byte[] bytes, int offset) {
+        return UNSAFE.getByte(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    @Override
+    public short getShort(byte[] bytes, int offset) {
+        return UNSAFE.getShort(bytes, offset);
+    }
+
+    @Override
+    public int getInt(byte[] bytes, int offset) {
+        return UNSAFE.getInt(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    @Override
+    public long getLong(byte[] bytes, int offset) {
+        return UNSAFE.getLong(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    @Override
+    public float getFloat(byte[] bytes, int offset) {
+        return UNSAFE.getFloat(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    @Override
+    public double getDouble(byte[] bytes, int offset) {
+        return UNSAFE.getDouble(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    @Override
+    public void putByte(byte[] bytes, int offset, byte value) {
+        UNSAFE.putByte(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+
+    @Override
+    public void putShort(byte[] bytes, int offset, short value) {
+        UNSAFE.putShort(bytes, offset, value);
+    }
+
+    @Override
+    public void putInt(byte[] bytes, int offset, int value) {
+        UNSAFE.putInt(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+
+    @Override
+    public void putLong(byte[] bytes, int offset, long value) {
+        UNSAFE.putLong(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+
+    @Override
+    public void putFloat(byte[] bytes, int offset, float value) {
+        UNSAFE.putFloat(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+
+    @Override
+    public void putDouble(byte[] bytes, int offset, double value) {
+        UNSAFE.putDouble(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
new file mode 100644
index 0000000..4321ed4
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.hyracks.bytes;
+
+import java.util.Random;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+abstract class AbstractPutGetTest {
+    private static final int TEST_LENGTH = 100;
+    private final IByteValueAccessor ACCESSOR;
+    private final Random random;
+
+    public AbstractPutGetTest() {
+        random = new Random(0);
+        ACCESSOR = getAccessor();
+    }
+
+    protected abstract IByteValueAccessor getAccessor();
+
+    @Test
+    public void testByte() {
+        int valueLength = Byte.BYTES;
+        byte[] values = new byte[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            byte value = (byte) random.nextInt();
+            values[i] = value;
+            ACCESSOR.putByte(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getByte(accessorBytes, i * 
valueLength));
+        }
+    }
+
+    @Test
+    public void testShort() {
+        int valueLength = Short.BYTES;
+        short[] values = new short[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            short value = (short) random.nextInt();
+            values[i] = value;
+            ACCESSOR.putShort(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getShort(accessorBytes, i 
* valueLength));
+        }
+    }
+
+    @Test
+    public void testInt() {
+        int valueLength = Integer.BYTES;
+        int[] values = new int[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            int value = random.nextInt();
+            values[i] = value;
+            ACCESSOR.putInt(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getInt(accessorBytes, i * 
valueLength));
+        }
+    }
+
+    @Test
+    public void testLong() {
+        int valueLength = Long.BYTES;
+        long[] values = new long[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            long value = random.nextLong();
+            values[i] = value;
+            ACCESSOR.putLong(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getLong(accessorBytes, i * 
valueLength));
+        }
+    }
+
+    @Test
+    public void testFloat() {
+        int valueLength = Float.BYTES;
+        float[] values = new float[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            float value = random.nextFloat();
+            values[i] = value;
+            ACCESSOR.putFloat(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getFloat(accessorBytes, i 
* valueLength), 0);
+        }
+    }
+
+    @Test
+    public void testDouble() {
+        int valueLength = Double.BYTES;
+        double[] values = new double[TEST_LENGTH];
+        byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            double value = random.nextDouble();
+            values[i] = value;
+            ACCESSOR.putDouble(accessorBytes, i * valueLength, value);
+        }
+
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            Assert.assertEquals(values[i], ACCESSOR.getDouble(accessorBytes, i 
* valueLength), 0);
+        }
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
new file mode 100644
index 0000000..3b69c8c
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.hyracks.bytes;
+
+import java.util.Random;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore
+public class MicroBenchmarkTest {
+    private static final int TEST_LENGTH = 1000000;
+    private static final int NUMBER_OF_ITERATIONS = 20;
+
+    @Test
+    public void run() {
+        Random random = new Random(0);
+        long[] values = new long[TEST_LENGTH];
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            values[i] = random.nextLong();
+        }
+        byte[] unsafeBytes = new byte[TEST_LENGTH * Long.BYTES];
+        byte[] safeBytes = new byte[TEST_LENGTH * Long.BYTES];
+
+        for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+            runUnsafe(unsafeBytes, values);
+            System.out.println();
+            runSafe(safeBytes, values);
+            System.out.println("========================");
+            System.out.println();
+        }
+
+    }
+
+    private void runSafe(byte[] bytes, long[] values) {
+        IByteValueAccessor accessor = SafeByteValueAccessor.INSTANCE;
+        System.out.println("Writing safe took: " + write(accessor, values, 
bytes));
+
+        long start = System.nanoTime();
+        for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+            read(accessor, bytes);
+        }
+        long avgTime = (System.nanoTime() - start) / NUMBER_OF_ITERATIONS;
+        System.out.println("Safe avg time to read: " + avgTime);
+    }
+
+    private void runUnsafe(byte[] bytes, long[] values) {
+        IByteValueAccessor accessor = UnsafeByteValueAccessor.INSTANCE;
+        System.out.println("Writing unsafe took: " + write(accessor, values, 
bytes));
+
+        long start = System.nanoTime();
+        for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+            read(accessor, bytes);
+        }
+        long avgTime = (System.nanoTime() - start) / NUMBER_OF_ITERATIONS;
+        System.out.println("Unsafe avg time to read: " + avgTime);
+    }
+
+    private void read(IByteValueAccessor accessor, byte[] bytes) {
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            accessor.getLong(bytes, i * Long.BYTES);
+        }
+    }
+
+    private long write(IByteValueAccessor accessor, long[] values, byte[] 
bytes) {
+
+        long start = System.nanoTime();
+        for (int i = 0; i < TEST_LENGTH; i++) {
+            accessor.putLong(bytes, i * Long.BYTES, values[i]);
+        }
+        return System.nanoTime() - start;
+    }
+
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
new file mode 100644
index 0000000..29e8eb2
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.hyracks.bytes;
+
+public class SafePutGetTest extends AbstractPutGetTest {
+
+    @Override
+    protected IByteValueAccessor getAccessor() {
+        return SafeByteValueAccessor.INSTANCE;
+    }
+
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
new file mode 100644
index 0000000..9d25bb1
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hyracks.bytes;
+
+public class UnsafePutGetTest extends AbstractPutGetTest {
+    @Override
+    protected IByteValueAccessor getAccessor() {
+        if (UnsafeByteValueAccessor.isAccessible()) {
+            return UnsafeByteValueAccessor.INSTANCE;
+        } else {
+            // Allow the test to proceed successfully
+            System.err.println("Cannot access unsafe object");
+            return SafeByteValueAccessor.INSTANCE;
+        }
+    }
+}
diff --git 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
index 4f5d0a1..1680f5a 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
@@ -18,6 +18,8 @@
  */
 package org.apache.hyracks.data.std.primitive;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IJsonSerializable;
@@ -84,13 +86,11 @@
     }

     public static double getDouble(byte[] bytes, int start) {
-        long bits = getLongBits(bytes, start);
-        return Double.longBitsToDouble(bits);
+        return ACCESSOR.getDouble(bytes, start);
     }

     public static void setDouble(byte[] bytes, int start, double value) {
-        long bits = Double.doubleToLongBits(value);
-        LongPointable.setLong(bytes, start, bits);
+        ACCESSOR.putDouble(bytes, start, value);
     }

     public double getDouble() {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
index 7c72d5c..aa08b47 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
@@ -18,6 +18,8 @@
  */
 package org.apache.hyracks.data.std.primitive;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IJsonSerializable;
@@ -67,13 +69,11 @@
     }

     public static float getFloat(byte[] bytes, int start) {
-        int bits = getIntBits(bytes, start);
-        return Float.intBitsToFloat(bits);
+        return ACCESSOR.getFloat(bytes, start);
     }

     public static void setFloat(byte[] bytes, int start, float value) {
-        int bits = Float.floatToIntBits(value);
-        IntegerPointable.setInteger(bytes, start, bits);
+        ACCESSOR.putFloat(bytes, start, value);
     }

     public float getFloat() {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
index ad80e23..effc791 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
@@ -18,6 +18,8 @@
  */
 package org.apache.hyracks.data.std.primitive;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IJsonSerializable;
@@ -71,15 +73,11 @@
     }

     public static int getInteger(byte[] bytes, int start) {
-        return ((bytes[start] & 0xff) << 24) + ((bytes[start + 1] & 0xff) << 
16) + ((bytes[start + 2] & 0xff) << 8)
-                + ((bytes[start + 3] & 0xff) << 0);
+        return ACCESSOR.getInt(bytes, start);
     }

     public static void setInteger(byte[] bytes, int start, int value) {
-        bytes[start] = (byte) ((value >>> 24) & 0xFF);
-        bytes[start + 1] = (byte) ((value >>> 16) & 0xFF);
-        bytes[start + 2] = (byte) ((value >>> 8) & 0xFF);
-        bytes[start + 3] = (byte) ((value >>> 0) & 0xFF);
+        ACCESSOR.putInt(bytes, start, value);
     }

     public int getInteger() {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
index 2de7b82..faabfcf 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
@@ -18,6 +18,8 @@
  */
 package org.apache.hyracks.data.std.primitive;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IJsonSerializable;
@@ -72,21 +74,11 @@
     }

     public static long getLong(byte[] bytes, int start) {
-        return (((long) (bytes[start] & 0xff)) << 56) + (((long) (bytes[start 
+ 1] & 0xff)) << 48)
-                + (((long) (bytes[start + 2] & 0xff)) << 40) + (((long) 
(bytes[start + 3] & 0xff)) << 32)
-                + (((long) (bytes[start + 4] & 0xff)) << 24) + (((long) 
(bytes[start + 5] & 0xff)) << 16)
-                + (((long) (bytes[start + 6] & 0xff)) << 8) + (((long) 
(bytes[start + 7] & 0xff)) << 0);
+        return ACCESSOR.getLong(bytes, start);
     }

     public static void setLong(byte[] bytes, int start, long value) {
-        bytes[start] = (byte) ((value >>> 56) & 0xFF);
-        bytes[start + 1] = (byte) ((value >>> 48) & 0xFF);
-        bytes[start + 2] = (byte) ((value >>> 40) & 0xFF);
-        bytes[start + 3] = (byte) ((value >>> 32) & 0xFF);
-        bytes[start + 4] = (byte) ((value >>> 24) & 0xFF);
-        bytes[start + 5] = (byte) ((value >>> 16) & 0xFF);
-        bytes[start + 6] = (byte) ((value >>> 8) & 0xFF);
-        bytes[start + 7] = (byte) ((value >>> 0) & 0xFF);
+        ACCESSOR.putLong(bytes, start, value);
     }

     public long getLong() {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
index 3806c0c..4bc5c90 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
@@ -18,6 +18,8 @@
  */
 package org.apache.hyracks.data.std.primitive;

+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IJsonSerializable;
@@ -63,12 +65,11 @@
     }

     public static short getShort(byte[] bytes, int start) {
-        return (short) (((bytes[start] & 0xff) << 8) + (bytes[start + 1] & 
0xff));
+        return ACCESSOR.getShort(bytes, start);
     }

     public static void setShort(byte[] bytes, int start, short value) {
-        bytes[start] = (byte) ((value >>> 8) & 0xFF);
-        bytes[start + 1] = (byte) ((value >>> 0) & 0xFF);
+        ACCESSOR.putShort(bytes, start, value);
     }

     public short getShort() {
diff --git 
a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
 
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
new file mode 100644
index 0000000..152b208
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
@@ -0,0 +1,109 @@
+/*
+ * 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.hyracks.storage.am.lsm.btree.column.utils;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * Unsafe accessor to serialize/deserialize bytes. This is intended for 
little-indian machines
+ */
+@SuppressWarnings("restriction")
+public class UnsafeUtil {
+    private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+
+    private static final long BYTE_ARRAY_BASE_OFFSET = 
UNSAFE.arrayBaseOffset(byte[].class);
+
+    private UnsafeUtil() {
+
+    }
+
+    static sun.misc.Unsafe getUnsafe() {
+        sun.misc.Unsafe unsafe = null;
+        try {
+            unsafe = AccessController.doPrivileged(new 
PrivilegedExceptionAction<>() {
+                @Override
+                public sun.misc.Unsafe run() throws Exception {
+                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+                    for (Field f : k.getDeclaredFields()) {
+                        f.setAccessible(true);
+                        Object x = f.get(null);
+                        if (k.isInstance(x)) {
+                            return k.cast(x);
+                        }
+                    }
+                    return null;
+                }
+            });
+        } catch (Throwable e) {
+
+        }
+        return unsafe;
+    }
+
+    public static byte getByte(byte[] target, int offset) {
+        return UNSAFE.getByte(target, BYTE_ARRAY_BASE_OFFSET + offset);
+    }
+
+    public static void putByte(Object target, int offset, byte value) {
+        UNSAFE.putByte(target, BYTE_ARRAY_BASE_OFFSET + offset, value);
+    }
+
+    public static short getShort(byte[] target, int offset) {
+        return Short.reverseBytes(UNSAFE.getShort(target, 
BYTE_ARRAY_BASE_OFFSET + offset));
+    }
+
+    public static void putShort(Object target, int offset, short value) {
+        UNSAFE.putShort(target, BYTE_ARRAY_BASE_OFFSET + offset, 
Short.reverseBytes(value));
+    }
+
+    public static int getInt(byte[] target, int offset) {
+        return Integer.reverseBytes(UNSAFE.getInt(target, 
BYTE_ARRAY_BASE_OFFSET + offset));
+    }
+
+    public static void putInt(byte[] target, int offset, int value) {
+        UNSAFE.putInt(target, BYTE_ARRAY_BASE_OFFSET + offset, 
Integer.reverseBytes(value));
+    }
+
+    public static long getLong(byte[] target, int offset) {
+        return Long.reverseBytes(UNSAFE.getLong(target, BYTE_ARRAY_BASE_OFFSET 
+ offset));
+    }
+
+    public static void putLong(byte[] target, int offset, long value) {
+        UNSAFE.putLong(target, BYTE_ARRAY_BASE_OFFSET + offset, 
Long.reverseBytes(value));
+    }
+
+    public static float getFloat(byte[] target, int offset) {
+        return Float.intBitsToFloat(Integer.reverseBytes(UNSAFE.getInt(target, 
BYTE_ARRAY_BASE_OFFSET + offset)));
+    }
+
+    public static void putFloat(byte[] target, int offset, float value) {
+        UNSAFE.putInt(target, BYTE_ARRAY_BASE_OFFSET + offset, 
Integer.reverseBytes(Float.floatToIntBits(value)));
+    }
+
+    public static double getDouble(byte[] target, int offset) {
+        return 
Double.longBitsToDouble(Long.reverseBytes(UNSAFE.getLong(target, 
BYTE_ARRAY_BASE_OFFSET + offset)));
+    }
+
+    public static void putDouble(byte[] target, int offset, double value) {
+        UNSAFE.putLong(target, BYTE_ARRAY_BASE_OFFSET + offset, 
Long.reverseBytes(Double.doubleToLongBits(value)));
+    }
+}

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17421
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings

Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Icd8f8862ce03553ce2a3b6f8e1a8131bb2b78761
Gerrit-Change-Number: 17421
Gerrit-PatchSet: 1
Gerrit-Owner: Wail Alkowaileet <[email protected]>
Gerrit-MessageType: newchange

Reply via email to