package org.hivedb;
import java.util.Collection;
import org.hivedb.meta.Assigner;
import org.hivedb.meta.Node;
import org.hivedb.util.Lists;
/***
* A node assigner that uses a hash function to allocate partition keys
* to a large number of virtual buckets. One node may contain many buckets,
* allowing you to easily subdivide a node at a later time. This is very
* similar to the concept of virtual shards in Hibernate Shards.
* Here it is being used as a simple solution for directory partitioning.
* @author bcrawford
*
*/
public class BucketAssigner implements Assigner {
private int bucketCount = 1024;
public BucketAssigner() {}
public BucketAssigner(int bucketCount) {
this.bucketCount = bucketCount;
}
public Node chooseNode(Collection<Node> nodes, Object value) {
return getNode(nodes, getBucket(value));
}
public Collection<Node> chooseNodes(Collection<Node> nodes, Object value) {
return Lists.newList(new Node[]{chooseNode(nodes, value)});
}
private Node getNode(Collection<Node> nodes, int bucket) {
return Lists.newList(nodes).get(bucket % nodes.size());
}
private int getBucket(Object value) {
return castAsNumber(value).intValue() % getBucketCount();
}
private Number castAsNumber(Object value) {
if(value.getClass() == Integer.class || value.getClass() == int.class)
return (Integer)value;
else if(value.getClass() == Long.class || value.getClass() == long.class)
return (Long)value;
else
throw new UnsupportedOperationException(String.format("Cannot convert object of type %s, the object must be a number.", value.getClass()));
}
public int getBucketCount() {
return bucketCount;
}
public void setBucketCount(int bucketCount) {
this.bucketCount = bucketCount;
}
}