import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 初始化化一致环
 * **/
public class UniformLoop {
	//自动排序好的key，value的数组
	private  TreeMap<Long,Object> nodes = null;
	int i,j;
    public int VIRTUAL_NUM = 1;
	
	public void loopInit(SeverList serverlist)
	{
	  
      nodes = new TreeMap<Long,Object>();
      i=0;
      
       while(serverlist.getNext() !=null )
       {
    	   serverlist = serverlist.getNext();
           Object serverlist_name = serverlist.get_host_name();
           
           //根据内存比例和当前内存比率生成权值
           VIRTUAL_NUM = (serverlist.get_all_Memory()/512)*1+(100 - serverlist.rate_memory)/10;
           
          //node产生的节点数为服务器*虚拟节点数，key=shard-i-node-j和j共同产生的hash值，value=实质那台服务器
           for(int j=0; j<VIRTUAL_NUM; j++)
           {
           nodes.put(hash(computeMd5("Host-" + i + "-NODE-" + j),1), serverlist);                 
           }
           i++;       
       }
       
    	   System.out.println(nodes);
	}
	/**
	 * 获取一致环
	 * **/
	public TreeMap<Long,Object> getHashnodes()
	{
		return this.nodes;
	}
	
	
	 /**
     * 根据2^32把节点分布到圆环上面。
     * @param digest
     * @param nTime
     * @return
     */
     //   // 哈希算法
      public long hash(byte[] digest, int nTime) {
		long rv = ((long) (digest[3+nTime*4] & 0xFF) << 24)
				| ((long) (digest[2+nTime*4] & 0xFF) << 16)
				| ((long) (digest[1+nTime*4] & 0xFF) << 8)
				| (digest[0+nTime*4] & 0xFF);

		return rv & 0xffffffffL; /* Truncate to 32-bits */
	  }

	
	/**
	 * Get the md5 of the given key.
     * 计算MD5值
	 */
	 public byte[] computeMd5(String k) {
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("MD5 not supported", e);
		}
		md5.reset();
		byte[] keyBytes = null;
		try {
			keyBytes = k.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Unknown string :" + k, e);
		}

		md5.update(keyBytes);
		return md5.digest();
	 }


}
