* This implementation is concurrency safe; additions and removals are serialized, but look up
- * can be performed concurrently even when modifications is in progress.
+ * can be performed concurrently even when modifications are in progress.
*
*
* Since typical hash functions we use in {@link Object#hashCode()} isn't random enough to
* evenly populate the 2^32 ring space, we only ask the user to give us
* an injective function to a string,
- * and then we use MD5 to create random enough distribution.
+ * and then we use SHA-256 to create random enough distribution.
*
*
* This consistent hash implementation is consistent both to the addition/removal of Ts, as well
@@ -56,7 +55,7 @@ import hudson.util.Iterators.DuplicateFilterIterator;
*
*
* See http://en.wikipedia.org/wiki/Consistent_hashing for references, and
- * http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html is probably a reasonable depiction.
+ * http://tom-e-white.com/2007/11/consistent-hashing.html is probably a reasonable depiction.
* If we trust his experiments, creating 100 replicas will reduce the stddev to 10% of the mean for 10 nodes.
*
* @author Kohsuke Kawaguchi
@@ -66,14 +65,14 @@ public class ConsistentHash {
/**
* All the items in the hash, to their replication factors.
*/
- private final Map items = new HashMap<>();
+ private final Map items = new HashMap<>();
private int numPoints;
private final int defaultReplication;
private final Hash hash;
/**
- * Used for remembering the computed MD5 hash, since it's bit expensive to do it all over again.
+ * Used for remembering the computed SHA-256 hash, since it's bit expensive to do it all over again.
*/
private static final class Point implements Comparable {
final int hash;
@@ -99,37 +98,41 @@ public class ConsistentHash {
*/
private final class Table {
private final int[] hash;
- private final Object[] owner; // really T[]
+ // really T[]
+ private final Object[] owner;
private Table() {
- int r=0;
- for (Point[] v : items.values())
- r+=v.length;
+ int r = 0;
+ for (Point[] v : items.values()) {
+ r += v.length;
+ }
numPoints = r;
// merge all points from all nodes and sort them into a single array
Point[] allPoints = new Point[numPoints];
- int p=0;
+ int p = 0;
for (Point[] v : items.values()) {
- System.arraycopy(v,0,allPoints,p,v.length);
- p+=v.length;
+ System.arraycopy(v, 0, allPoints, p, v.length);
+ p += v.length;
}
Arrays.sort(allPoints);
hash = new int[allPoints.length];
owner = new Object[allPoints.length];
- for (int i=0; i {
}
public T next() {
- if (!hasNext()) throw new NoSuchElementException();
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
return (T) owner[(start + (pos++)) % owner.length];
}
@@ -161,10 +166,14 @@ public class ConsistentHash {
private int index(int queryPoint) {
int idx = Arrays.binarySearch(hash, queryPoint);
- if(idx<0) {
- idx = -idx-1; // idx is now 'insertion point'
- if(hash.length==0) return -1;
- idx %= hash.length; // make it a circle
+ if (idx < 0) {
+ // idx is now 'insertion point'
+ idx = - idx - 1;
+ if (hash.length == 0) {
+ return -1;
+ }
+ // make it a circle
+ idx %= hash.length;
}
return idx;
}
@@ -180,7 +189,7 @@ public class ConsistentHash {
*
*
* This hash function need not produce a very uniform distribution, as the
- * output is rehashed with MD5. But it does need to make sure it doesn't
+ * output is rehashed with SHA-256. But it does need to make sure it doesn't
* produce the same value for two different 'T's (and that's why this returns
* String, not the usual int.)
*/
@@ -194,11 +203,7 @@ public class ConsistentHash {
String hash(T t);
}
- static final Hash> DEFAULT_HASH = new Hash