package org.infinispan.partitionhandling;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.infinispan.distribution.MagicKey;
import org.infinispan.remoting.transport.Address;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.testng.annotations.Test;
@Test(groups = "functional", testName = "partitionhandling.ThreeWaySplitAndMergeTest")
public class ThreeWaySplitAndMergeTest extends BasePartitionHandlingTest {
private static Log log = LogFactory.getLog(ThreeWaySplitAndMergeTest.class);
public void testSplitAndMerge1() throws Exception {
testSplitAndMerge(new PartitionDescriptor(0, 1), new PartitionDescriptor(2), new PartitionDescriptor(3));
}
public void testSplitAndMerge2() throws Exception {
testSplitAndMerge(new PartitionDescriptor(1, 2), new PartitionDescriptor(0), new PartitionDescriptor(3));
}
public void testSplitAndMerge3() throws Exception {
testSplitAndMerge(new PartitionDescriptor(2, 3), new PartitionDescriptor(0), new PartitionDescriptor(1));
}
public void testSplitAndMerge4() throws Exception {
testSplitAndMerge(new PartitionDescriptor(2, 3), new PartitionDescriptor(1), new PartitionDescriptor(0));
}
private void testSplitAndMerge(PartitionDescriptor p0, PartitionDescriptor p1, PartitionDescriptor p2) throws Exception {
Object k0 = new MagicKey("k0", cache(p0.node(0)), cache(p0.node(1)));
cache(0).put(k0, 0);
Object k1 = new MagicKey("k1", cache(p0.node(1)), cache(p1.node(0)));
cache(1).put(k1, 1);
Object k2 = new MagicKey("k2", cache(p1.node(0)), cache(p2.node(0)));
cache(2).put(k2, 2);
Object k3 = new MagicKey(cache(p2.node(0)), cache(p0.node(0)));
cache(3).put(k3, 3);
log.trace("Before split.");
splitCluster(p0.getNodes(), p1.getNodes(), p2.getNodes());
partition(0).assertDegradedMode();
partition(1).assertDegradedMode();
partition(2).assertDegradedMode();
//1. check key visibility in partition 0
partition(0).assertKeyAvailableForRead(k0, 0);
partition(0).assertKeysNotAvailableForRead(k1, k2, k3);
//2. check key visibility in partition 1
partition(1).assertKeysNotAvailableForRead(k0, k1, k2, k3);
//3. check key visibility in partition 2
partition(2).assertKeysNotAvailableForRead(k0, k1, k2, k3);
//4. check key ownership
assertTrue(dataContainer(p0.node(0)).containsKey(k0));
assertFalse(dataContainer(p0.node(0)).containsKey(k1));
assertFalse(dataContainer(p0.node(0)).containsKey(k2));
assertTrue(dataContainer(p0.node(0)).containsKey(k3));
assertTrue(dataContainer(p0.node(1)).containsKey(k0));
assertTrue(dataContainer(p0.node(1)).containsKey(k1));
assertFalse(dataContainer(p0.node(1)).containsKey(k2));
assertFalse(dataContainer(p0.node(1)).containsKey(k3));
assertFalse(dataContainer(p1.node(0)).containsKey(k0));
assertTrue(dataContainer(p1.node(0)).containsKey(k1));
assertTrue(dataContainer(p1.node(0)).containsKey(k2));
assertFalse(dataContainer(p1.node(0)).containsKey(k3));
assertFalse(dataContainer(p2.node(0)).containsKey(k0));
assertFalse(dataContainer(p2.node(0)).containsKey(k1));
assertTrue(dataContainer(p2.node(0)).containsKey(k2));
assertTrue(dataContainer(p2.node(0)).containsKey(k3));
//5. check writes on partition 0
partition(0).assertKeyAvailableForWrite(k0, -1);
//5. check writes on partition 1
partition(1).assertKeysNotAvailableForWrite(k0, k1, k2);
//6. check writes on partition 2
partition(2).assertKeysNotAvailableForWrite(k0, k1, k2);
log.tracef("Before the 1st merge P0 = %s, P1 = %s, P2 = %s", partition(0), partition(1), partition(2));
assertEquals(partitions.length, 3);
partition(0).merge(partition(1));
assertEquals(partitions.length, 2);
log.tracef("After the 1st merge P0 = %s, P1 = %s", partition(0), partition(1));
partition(0).assertAvailabilityMode(AvailabilityMode.AVAILABLE);
partition(1).assertAvailabilityMode(AvailabilityMode.DEGRADED_MODE);
partition(0).assertKeyAvailableForRead(k0, -1);
partition(0).assertKeyAvailableForRead(k1, 1);
partition(0).assertKeyAvailableForRead(k2, 2);
partition(0).assertKeyAvailableForRead(k3, 3);
partition(0).assertKeyAvailableForWrite(k0, 10);
partition(0).assertKeyAvailableForWrite(k1, 11);
partition(0).assertKeyAvailableForWrite(k2, 12);
partition(0).assertKeyAvailableForWrite(k3, 13);
Set<Address> members = new HashSet<>(Arrays.asList(new Address[]{address(p0.node(0)), address(p0.node(1)), address(p1.node(0))}));
assertEquals(new HashSet<>(advancedCache(p0.node(0)).getDistributionManager().getWriteConsistentHash().getMembers()), members);
assertEquals(new HashSet<>(advancedCache(p0.node(1)).getDistributionManager().getWriteConsistentHash().getMembers()), members);
assertEquals(new HashSet<>(advancedCache(p1.node(0)).getDistributionManager().getWriteConsistentHash().getMembers()), members);
partition(1).assertKeysNotAvailableForRead(k0, k1, k2, k3);
members = new HashSet<>(Arrays.asList(new Address[]{address(0), address(1), address(2), address(3)}));
assertEquals(new HashSet<>(advancedCache(p2.node(0)).getDistributionManager().getWriteConsistentHash().getMembers()), members);
for (int i = 0; i < 100; i++) {
dataContainer(p2.node(0)).put(i, i, null);
}
log.tracef("Before the 2nd merge P0 = %s, P1 = %s", partition(0), partition(1));
partition(0).merge(partition(1));
log.tracef("After 2nd merge P0=%s", partition(0));
assertEquals(partitions.length, 1);
partition(0).assertAvailabilityMode(AvailabilityMode.AVAILABLE);
partition(0).assertKeyAvailableForRead(k0, 10);
partition(0).assertKeyAvailableForRead(k1, 11);
partition(0).assertKeyAvailableForRead(k2, 12);
partition(0).assertKeyAvailableForRead(k3, 13);
for (int i = 0; i < 100; i++) {
partition(0).assertKeyAvailableForRead(i, null);
}
cache(0).put(k0, 10);
cache(1).put(k1, 100);
cache(2).put(k2, 1000);
cache(3).put(k3, 10000);
assertExpectedValue(10, k0);
assertExpectedValue(100, k1);
assertExpectedValue(1000, k2);
assertExpectedValue(10000, k3);
}
}