Slicing out minor utils/modification created for shared logs

Change-Id: I1c5dd4bfcf147e29b7bec9662cef9a9e23b02651
diff --git a/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZTable.java b/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZTable.java
index da2c102..4d26cf3 100644
--- a/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZTable.java
+++ b/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZTable.java
@@ -13,6 +13,7 @@
 import net.onrc.onos.core.datastore.ObjectDoesntExistException;
 import net.onrc.onos.core.datastore.ObjectExistsException;
 import net.onrc.onos.core.datastore.WrongVersionException;
+import net.onrc.onos.core.datastore.utils.ByteArrayUtil;
 
 import org.apache.commons.collections.BufferOverflowException;
 import org.apache.commons.lang.ArrayUtils;
@@ -193,6 +194,12 @@
         void setVersion(final long version) {
             this.version = version;
         }
+
+        @Override
+        public String toString() {
+            return "[Entry key=" + ByteArrayUtil.toHexStringBuilder(key, ":") + ", value="
+                    + ByteArrayUtil.toHexStringBuilder(value, ":") + ", version=" + version + "]";
+        }
     }
 
 
diff --git a/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCClient.java b/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCClient.java
index a2d23a5..9096f8a 100644
--- a/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCClient.java
+++ b/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCClient.java
@@ -510,7 +510,8 @@
         for (int i = 0; i < results.length; ++i) {
             IModifiableMultiEntryOperation op = ops.get(i);
             if (results[i] == null) {
-                log.error("MultiRead error, skipping {}, {}", op.getTableId(), op);
+                // Logging as error gets too noisy when doing speculative read.
+                log.trace("MultiRead error {}, {}", op.getTableId(), op);
                 failExists = true;
                 op.setStatus(STATUS.FAILED);
                 continue;
diff --git a/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCTable.java b/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCTable.java
index 4a92b4f..a6d5080 100644
--- a/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCTable.java
+++ b/src/main/java/net/onrc/onos/core/datastore/ramcloud/RCTable.java
@@ -5,6 +5,7 @@
 import net.onrc.onos.core.datastore.ObjectDoesntExistException;
 import net.onrc.onos.core.datastore.ObjectExistsException;
 import net.onrc.onos.core.datastore.WrongVersionException;
+import net.onrc.onos.core.datastore.utils.ByteArrayUtil;
 
 import org.apache.commons.lang.ArrayUtils;
 import org.slf4j.Logger;
@@ -54,6 +55,12 @@
         void setVersion(long version) {
             this.version = version;
         }
+
+        @Override
+        public String toString() {
+            return "[Entry key=" + ByteArrayUtil.toHexStringBuilder(key, ":") + ", value="
+                    + ByteArrayUtil.toHexStringBuilder(value, ":") + ", version=" + version + "]";
+        }
     }
 
     private final RCTableID rcTableId;
diff --git a/src/main/java/net/onrc/onos/core/datastore/utils/ByteArrayUtil.java b/src/main/java/net/onrc/onos/core/datastore/utils/ByteArrayUtil.java
index 5c63df8..6dd6493 100644
--- a/src/main/java/net/onrc/onos/core/datastore/utils/ByteArrayUtil.java
+++ b/src/main/java/net/onrc/onos/core/datastore/utils/ByteArrayUtil.java
@@ -1,6 +1,7 @@
 package net.onrc.onos.core.datastore.utils;
 
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 public final class ByteArrayUtil {
 
@@ -51,4 +52,26 @@
 
         return buf;
     }
+
+    /**
+     * Convert {@code value} to Little Endian byte array.
+     *
+     * @param value
+     * @return {@code value} as Little Endian byte array
+     */
+    public static byte[] toLEBytes(final long value) {
+        return ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN)
+                .putLong(value).array();
+    }
+
+    /**
+     * Convert Little Endian byte array to long.
+     *
+     * @param value 8 byte Little Endian byte array
+     * @return {@code value} converted to long
+     */
+    public static long fromLEBytes(final byte[] value) {
+        ByteBuffer counter = ByteBuffer.wrap(value).order(ByteOrder.LITTLE_ENDIAN);
+        return counter.getLong();
+    }
 }
diff --git a/src/main/java/net/onrc/onos/core/datastore/utils/KryoSerializer.java b/src/main/java/net/onrc/onos/core/datastore/utils/KryoSerializer.java
new file mode 100644
index 0000000..bcc2736
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datastore/utils/KryoSerializer.java
@@ -0,0 +1,35 @@
+package net.onrc.onos.core.datastore.utils;
+
+import net.onrc.onos.core.datastore.DataStoreClient;
+
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+/**
+ * {@link Serializer} implementation using Kryo.
+ */
+public final class KryoSerializer
+            implements Serializer {
+
+    private final ThreadLocalKryo kryo;
+
+    public KryoSerializer(Class<?>... expectedTypes) {
+        kryo = new ThreadLocalKryo(expectedTypes);
+    }
+
+    @Override
+    public byte[] serialize(Object obj) {
+        // 1MB RAMCloud limit
+        Output out = new Output(DataStoreClient.MAX_VALUE_BYTES);
+        kryo.get().writeClassAndObject(out, obj);
+        return out.toBytes();
+    }
+
+    @Override
+    public <T> T deserialize(byte[] bytes) {
+        Input in = new Input(bytes);
+        @SuppressWarnings("unchecked")
+        T obj = (T) kryo.get().readClassAndObject(in);
+        return obj;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/datastore/utils/Serializer.java b/src/main/java/net/onrc/onos/core/datastore/utils/Serializer.java
new file mode 100644
index 0000000..69581e1
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datastore/utils/Serializer.java
@@ -0,0 +1,25 @@
+package net.onrc.onos.core.datastore.utils;
+
+/**
+ * Interface to serialize object into byte[].
+ *
+ * Serializer instance is expected to be functional even if the
+ * instance was shared among multiple threads.
+ */
+public interface Serializer {
+    /**
+     * Serializes a given object.
+     *
+     * @param obj the object to serialize
+     * @return binary representation of the serialized object
+     */
+    public byte[] serialize(final Object obj);
+
+    /**
+     * Deserializes a given byte array.
+     *
+     * @param bytes binary representation of an Object
+     * @return deserialized object
+     */
+    public <T> T deserialize(final byte[] bytes);
+}
diff --git a/src/main/java/net/onrc/onos/core/datastore/utils/ThreadLocalKryo.java b/src/main/java/net/onrc/onos/core/datastore/utils/ThreadLocalKryo.java
new file mode 100644
index 0000000..e13bf7e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datastore/utils/ThreadLocalKryo.java
@@ -0,0 +1,31 @@
+package net.onrc.onos.core.datastore.utils;
+
+import com.esotericsoftware.kryo.Kryo;
+
+/**
+ * Helper class to create thread local instance of Kryo.
+ */
+public final class ThreadLocalKryo extends ThreadLocal<Kryo> {
+    private final Class<?>[] expectedTypes;
+
+    /**
+     * Constructor specifying expected classes to be serialized using this
+     * Kryo instance.
+     * <p/>
+     * @param expectedTypes list of .class to register to Kryo
+     */
+    public ThreadLocalKryo(Class<?>... expectedTypes) {
+        this.expectedTypes = expectedTypes;
+    }
+
+    @Override
+    protected Kryo initialValue() {
+        Kryo kryo = new Kryo();
+        //            kryo.setRegistrationRequired(true);
+        //            kryo.setReferences(false);
+        for (Class<?> type : expectedTypes) {
+            kryo.register(type);
+        }
+        return kryo;
+    }
+}