All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yestech.lib.util.ConsistentHash Maven / Gradle / Ivy

Go to download

A collection of classes that can be used across yestech artifacts/components, but must not be dependant on any yestech component. Most of the code is utility type code. When more than a few classes are found to be in a package or the package start to handle more that a few reposibilities then a new independant component is created and the existing code in yeslib is ported to the new component.

The newest version!
/*
 * Copyright LGPL3
 * YES Technology Association
 * http://yestech.org
 *
 * http://www.opensource.org/licenses/lgpl-3.0.html
 */
package org.yestech.lib.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * A simple Consistent Hash Algorithmn derived from:
 * http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html
 *
 * @param  Type of the Node on the circle
 */
public class ConsistentHash implements IConsistentHash {

    private final HashAlgorithm hashFunction;
    private final int numberOfReplicas;
    private final SortedMap circle = new TreeMap();

    /**
     * Creates a Ring and adds an initial collection of node to the Ring.
     * 
     * @param hashFunction The Hashing Functions to use.
     * @param numberOfReplicas Number of times to replicate a node on the Ring
     */
    public ConsistentHash(HashAlgorithm hashFunction, int numberOfReplicas) {
        this(hashFunction, numberOfReplicas, new ArrayList());
    }

    /**
     * Creates a Ring and adds an initial collection of node to the Ring.
     *
     * @param hashFunction The Hashing Functions to use.
     * @param numberOfReplicas Number of times to replicate a node on the Ring
     * @param nodes Nodes to add
     */
    public ConsistentHash(HashAlgorithm hashFunction, int numberOfReplicas,
                          Collection nodes) {
        this.hashFunction = hashFunction;
        this.numberOfReplicas = numberOfReplicas;

        for (T node : nodes) {
            add(node);
        }
    }

    /**
     * Add a node to the Ring and replicate it.
     *
     * @param node Node to add
     */
    public void add(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.put(hashFunction.hash(node.toString() + i), node);
        }
    }

    /**
     * Remove a node from the Ring.
     *
     * @param node Node to remove
     */
    public void remove(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.remove(hashFunction.hash(node.toString() + i));
        }
    }

    /**
     * Return the number of nodes on the Ring.
     *
     * @return the total node count.
     */
    public int getTotalNodes() {
        return circle.size();
    }
    
    /**
     * Return the nearest node associated with a resource.
     *
     * @param resource The check to has to find the nearest node
     * @return The nearest Node
     */
    public T get(Object resource) {
        if (circle.isEmpty()) {
            return null;
        }
        long hash = hashFunction.hash(resource.toString());
        if (!circle.containsKey(hash)) {
            SortedMap tailMap = circle.tailMap(hash);
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        return circle.get(hash);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy