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

org.bdware.doip.cluster.engine.DigestUtil Maven / Gradle / Ivy

The newest version!
package org.bdware.doip.cluster.engine;


import java.security.SecureRandom;
import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;

public class DigestUtil {
    SecureRandom random = new SecureRandom();

    public int nextInt(int n) {
        return random.nextInt(n);
    }

    public String md5Hex(String arg) {
        return org.apache.commons.codec.digest.DigestUtils.md5Hex(arg);
    }

    public int md5Int(String string) {
        byte[] bytes = org.apache.commons.codec.digest.DigestUtils.md5(string);
        return Math.abs(((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF));
    }

    public double md5Double(String string) {
        int intValue = md5Int(string);
        int N = 0x10000;
        return (intValue % N) / (double) N;
    }

    public int[] locateByStraw(String address, int clusterMemberSize, int number, double[] weights) {
        assert weights.length == clusterMemberSize;
        int[] result = new int[number];
        PriorityQueue priorityQueue = new PriorityQueue<>(clusterMemberSize,
                Comparator.comparingDouble(o -> o.dValue));
        for (int i = 0; i < clusterMemberSize; ++i) {
            double hash = md5Int(address + i) * weights[i];
            priorityQueue.offer(new DoubleInt(hash, i));
        }
        for (int i = 0; i < number; ++i)
            result[i] = priorityQueue.poll().iValue;
        return result;
    }

    public int[] locateByUniform(String address, int clusterMemberSize, int number, double[] weights) {
        assert weights.length == clusterMemberSize && number <= clusterMemberSize;
        Set integerSet = new HashSet<>();
        int[] result = new int[number];
        int index = 0;
        for (int i = 0; i < number; ++i) {
            int retries = 0;
            do {
                if (++retries > 10) {
                    for (int j = 0; j < clusterMemberSize; ++j) {
                        if (!integerSet.contains(j)) {
                            index = j;
                            break;
                        }
                    }
                    break;
                }
                else {
                    index = locateByUniform(address + (i * 10 + retries), clusterMemberSize, weights);
                }
            } while (integerSet.contains(index));
            integerSet.add(index);
            result[i] = index;
        }
        return result;
    }

    private int locateByUniform(String address, int clusterMemberSize, double[] weights) {
        double totalWeight = 0.0;
        for (int i = 0; i < clusterMemberSize; ++i)
            totalWeight += weights[i];
        double hash = md5Double(address) * totalWeight;
        int index = weights.length;
        while (hash <= totalWeight)
            totalWeight -= weights[--index];
        return index;
    }

    public int locateByTree(String address, int clusterMemberSize, double[] weights) {
        assert weights.length == clusterMemberSize;
        TreeNode treeNode = createTree(weights);
        int index = 0;
        while (treeNode.level != 0) {
            double hash = md5Double(address + treeNode.label);
            if (hash < treeNode.leftChild.weight / treeNode.weight) {
                treeNode = treeNode.leftChild;
            } else {
                treeNode = treeNode.rightChild;
                index += treeNode.leftChild.leafCount;
            }
        }
        return index;
    }

    private TreeNode createTree(double[] weights) {
        int length = weights.length;
        return createTree("", log2(length), weights, 0, length - 1);
    }

    private TreeNode createTree(String labelPrefix, int level, double[] weights, int left, int right) {
        int size = right - left + 1;
        if (size < 1 || level < 0)
            return null;
        if (level == 0)
            return new TreeNode(labelPrefix + '1', weights[left], level, 1);

        int x = pow2(level);
        int leftSize = Math.min(x / 2, size);
        TreeNode leftTree = createTree("", level - 1, weights, left, left + leftSize - 1);
        TreeNode rightTree = createTree("1", level - 1, weights, left + leftSize - 1, right);
        StringBuilder label = new StringBuilder(labelPrefix);
        label.append('1');
        for (int i = 0; i < level; ++i)
            label.append('0');
        assert leftTree != null && rightTree != null;
        TreeNode thisNode = new TreeNode(label.toString(), leftTree.weight + rightTree.weight, level,
                leftTree.leafCount + rightTree.leafCount);
        thisNode.leftChild = leftTree;
        thisNode.rightChild = rightTree;
        return thisNode;
    }

    public int log2(int n) {
        if (n < 1)
            return -1;
        int x = 1, i = 0;
        for (; x < n; ++i)
            x *= 2;
        return i;
    }

    // O(n), can be optimized to O(log(n))
    public int pow2(int n) {
        if (n < 0)
            return -1;
        int x = 1;
        while (--n >= 0)
            x *= 2;
        return x;
    }

    private static class TreeNode {
        TreeNode leftChild;
        TreeNode rightChild;
        String label;
        double weight;
        int level;
        int leafCount;

        TreeNode(String label, double weight, int level, int leafCount) {
            this.label = label;
            this.weight = weight;
            this.level = level;
            this.leafCount = leafCount;
        }
    }

    private static class DoubleInt {
        double dValue;
        int iValue;

        DoubleInt(double dValue, int iValue) {
            this.dValue = dValue;
            this.iValue = iValue;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy