package org.infinispan.distribution.ch;
import java.util.ArrayList;
import java.util.List;
import org.infinispan.commons.hash.MurmurHash3;
import org.infinispan.distribution.ch.impl.DefaultConsistentHash;
import org.infinispan.distribution.ch.impl.TopologyAwareSyncConsistentHashFactory;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsTopologyAwareAddress;
import org.jgroups.util.ExtendedUUID;
import org.testng.annotations.Test;
/**
* Tests the uniformity of the SyncConsistentHashFactory algorithm, which is very similar to the 5.1
* default consistent hash algorithm virtual nodes.
*
* <p>This test assumes that key hashes are random and follow a uniform distribution so a key has the same chance
* to land on each one of the 2^31 positions on the hash wheel.
*
* <p>The output should stay pretty much the same between runs, so I added and example output here: vnodes_key_dist.txt.
*
* <p>Notes about the test output:
* <ul>
* <li>{@code P(p)} is the probability of proposition {@code p} being true
* <li>In the "Primary" rows {@code mean == total_keys / num_nodes} (each key has only one primary owner),
* but in the "Any owner" rows {@code mean == total_keys / num_nodes * num_owners} (each key is stored on
* {@code num_owner} nodes).
* </ul>
* @author Dan Berindei
* @since 5.2
*/
@Test(testName = "distribution.ch.TopologyAwareSyncConsistentHashFactoryKeyDistributionTest", groups = "profiling")
public class TopologyAwareSyncConsistentHashFactoryKeyDistributionTest extends SyncConsistentHashFactoryKeyDistributionTest {
@Override
protected DefaultConsistentHash createConsistentHash(int numSegments, int numOwners, List<Address> members) {
MurmurHash3 hash = MurmurHash3.getInstance();
ConsistentHashFactory<DefaultConsistentHash> chf = new TopologyAwareSyncConsistentHashFactory();
DefaultConsistentHash ch = chf.create(hash, numOwners, numSegments, members, null);
return ch;
}
@Override
protected List<Address> createAddresses(int numNodes) {
ArrayList<Address> addresses = new ArrayList<Address>(numNodes);
for (int i = 0; i < numNodes; i++) {
ExtendedUUID topologyAddress = JGroupsTopologyAwareAddress.randomUUID(null, "s" + (i % 2), null, "m" + i);
addresses.add(new IndexedTopologyAwareJGroupsAddress(topologyAddress, i));
}
return addresses;
}
}
/**
* We extend JGroupsAddress to make mapping an address to a node easier.
*/
class IndexedTopologyAwareJGroupsAddress extends JGroupsTopologyAwareAddress {
final int nodeIndex;
public IndexedTopologyAwareJGroupsAddress(ExtendedUUID address, int nodeIndex) {
super(address);
this.nodeIndex = nodeIndex;
}
}