for (int i = 0; i < 1000; ++i)
{
int ii = i % 100;
RewriteClient client =
(RewriteClient) loadBalancer.getClient(new URIRequest("d2://foo/id=" + ii), new RequestContext());
String clientUri = client.getUri().toString();
HashFunction<String[]> hashFunction = null;
String[] str = new String[1];
// test KeyMapper target host hint: request is always to target host regardless of what's in d2 URI and whether it's hash-based or range-based partitions
RequestContext requestContextWithHint = new RequestContext();
KeyMapper.TargetHostHints.setRequestContextTargetHost(requestContextWithHint, uri1);
RewriteClient hintedClient1 = (RewriteClient)loadBalancer.getClient(new URIRequest("d2://foo/id=" + ii), requestContextWithHint);
String hintedUri1 = hintedClient1.getUri().toString();
Assert.assertEquals(hintedUri1, uri1.toString() + "/foo");
RewriteClient hintedClient2 = (RewriteClient)loadBalancer.getClient(new URIRequest("d2://foo/action=purge-all"), requestContextWithHint);
String hintedUri2 = hintedClient2.getUri().toString();
Assert.assertEquals(hintedUri2, uri1.toString() + "/foo");
// end test KeyMapper target host hint
if (partitionMethod == 2)
{
hashFunction = new MD5Hash();
}
for (URI uri : expectedUris)
{
if (clientUri.contains(uri.toString()))
{
// check if only key belonging to partition 0 gets uri2
if (uri.equals(uri2))
{
if (partitionMethod == 0)
{
assertTrue(ii < 50);
}
else if (partitionMethod == 1)
{
assertTrue(ii % 2 == 0);
}
else
{
str[0] = ii + "";
assertTrue(hashFunction.hash(str) % 2 == 0);
}
}
// check if only key belonging to partition 1 gets uri3
if (uri.equals(uri3))
{
if (partitionMethod == 0)
{
assertTrue(ii >= 50);
}
else if (partitionMethod == 1)
{
assertTrue(ii % 2 == 1);
}
else
{
str[0] = ii + "";
assertTrue(hashFunction.hash(str) % 2 == 1);
}
}
}
}
}
// two rings for two partitions
Map<Integer, Ring<URI>> ringMap = loadBalancer.getRings(URI.create("d2://foo"));
assertEquals(ringMap.size(), 2);
if (partitionMethod != 2)
{
Set<String> keys = new HashSet<String>();
for (int j = 0; j < 50; j++)
{
if (partitionMethod == 0)
{
keys.add(j + "");
}
else
{
keys.add(j * 2 + "");
}
}
// if it is range based partition, all keys from 0 ~ 49 belong to partition 0 according to the range definition
// if it is modulo based partition, all even keys belong to partition 0 because the partition count is 2
// only from partition 0
MapKeyResult<Ring<URI>, String> mapKeyResult = loadBalancer.getRings(URI.create("d2://foo"), keys);
Map<Ring<URI>, Collection<String>> keyToPartition = mapKeyResult.getMapResult();
assertEquals(keyToPartition.size(), 1);
for (Ring<URI> ring : keyToPartition.keySet())
{
assertEquals(ring, ringMap.get(0));
}
// now also from partition 1
keys.add("51");
mapKeyResult = loadBalancer.getRings(URI.create("d2://foo"), keys);
assertEquals(mapKeyResult.getMapResult().size(), 2);
assertEquals(mapKeyResult.getUnmappedKeys().size(), 0);
// now only from partition 1
keys.clear();
keys.add("99");
mapKeyResult = loadBalancer.getRings(URI.create("d2://foo"), keys);
keyToPartition = mapKeyResult.getMapResult();
assertEquals(keyToPartition.size(), 1);
assertEquals(mapKeyResult.getUnmappedKeys().size(), 0);
for (Ring<URI> ring : keyToPartition.keySet())
{
assertEquals(ring, ringMap.get(1));
}
keys.add("100");
mapKeyResult = loadBalancer.getRings(URI.create("d2://foo"), keys);
if (partitionMethod == 0)
{
// key out of range
Collection<MapKeyResult.UnmappedKey<String>> unmappedKeys = mapKeyResult.getUnmappedKeys();
assertEquals(unmappedKeys.size(), 1);
}
try
{
loadBalancer.getClient(new URIRequest("d2://foo/id=100"), new RequestContext());
if (partitionMethod == 0)
{
// key out of range
fail("Should throw ServiceUnavailableException caused by PartitionAccessException");
}