Use consistent hashing for map keys

Change-Id: I9a3e7947c0ffa7b39569b8b6164bd84051c3e543
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TransactionManager.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TransactionManager.java
index 0e99212..198c1ae 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TransactionManager.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TransactionManager.java
@@ -23,14 +23,12 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 
-import com.google.common.base.Charsets;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.hash.Hashing;
 import com.google.common.util.concurrent.Futures;
-import org.onlab.util.HexString;
 import org.onosproject.cluster.PartitionId;
 import org.onosproject.store.primitives.MapUpdate;
 import org.onosproject.store.primitives.PartitionService;
@@ -51,15 +49,21 @@
     private final List<PartitionId> sortedPartitions;
     private final AsyncConsistentMap<TransactionId, Transaction.State> transactions;
     private final int cacheSize;
+    private final int buckets;
     private final Map<PartitionId, Cache<String, CachedMap>> partitionCache = Maps.newConcurrentMap();
 
-    public TransactionManager(StorageService storageService, PartitionService partitionService) {
-        this(storageService, partitionService, DEFAULT_CACHE_SIZE);
+    public TransactionManager(StorageService storageService, PartitionService partitionService, int buckets) {
+        this(storageService, partitionService, DEFAULT_CACHE_SIZE, buckets);
     }
 
-    public TransactionManager(StorageService storageService, PartitionService partitionService, int cacheSize) {
+    public TransactionManager(
+            StorageService storageService,
+            PartitionService partitionService,
+            int cacheSize,
+            int buckets) {
         this.partitionService = partitionService;
         this.cacheSize = cacheSize;
+        this.buckets = buckets;
         this.transactions = storageService.<TransactionId, Transaction.State>consistentMapBuilder()
                 .withName("onos-transactions")
                 .withSerializer(Serializer.using(KryoNamespaces.API,
@@ -103,9 +107,9 @@
         }
 
         Hasher<K> hasher = key -> {
-            int hashCode = Hashing.sha256()
-                    .hashString(HexString.toHexString(serializer.encode(key)), Charsets.UTF_8).asInt();
-            return sortedPartitions.get(Math.abs(hashCode) % sortedPartitions.size());
+            int bucket = Math.abs(Hashing.murmur3_32().hashBytes(serializer.encode(key)).asInt()) % buckets;
+            int partition = Hashing.consistentHash(bucket, sortedPartitions.size());
+            return sortedPartitions.get(partition);
         };
         return new PartitionedTransactionalMap<>(partitions, hasher);
     }