*
* @throws Exception
*/
public void testIsMasterReplica() throws Exception
{
GossipRouter router = null;
ClusterPartition partition1 = null;
ClusterPartition partition2 = null;
boolean partition1Started = false;
boolean partition2Started = false;
log.debug("+++ testIsMasterReplica()");
try
{
String partitionName = "DRMTestCasePartition";
String muxFile = "cluster/drm/drm-test-stacks.xml";
String stackName = "tunnel1";
log.info("DRMTestCase.testIsMasterReplica() - starting GossipRouter");
// router characteristics here must match the definition in the stack configuration
router = new GossipRouter(12001, "localhost");
router.start();
Thread.sleep(10000);
log.info("router routing table = " + router.dumpRoutingTable());
assertTrue("router is started", router.isStarted());
assertTrue("router is running", router.isRunning());
JChannelFactory factory1 = new JChannelFactory();
factory1.setMultiplexerConfig(muxFile);
factory1.setNamingServicePort(1099);
factory1.setNodeName("node1");
factory1.setExposeChannels(false);
factory1.setExposeProtocols(false);
factory1.setAddMissingSingletonName(false);
factory1.create();
factory1.start();
partition1 = new InjectedChannelClusterPartition(factory1.createChannel(stackName));
partition1.setPartitionName(partitionName);
partition1.setStateTransferTimeout(30000);
partition1.setMethodCallTimeout(60000);
partition1.setBindIntoJndi(false);
partition1.create();
partition1.start();
DistributedReplicantManager drm1 = partition1.getDistributedReplicantManager();
Thread.sleep(10000);
// Use a different stack name with the same config to avoid singleton conflicts
stackName = "tunnel2";
JChannelFactory factory2 = new JChannelFactory();
factory2.setMultiplexerConfig(muxFile);
factory2.setNamingServicePort(1099);
factory2.setNodeName("node2");
factory2.setExposeChannels(false);
factory2.setExposeProtocols(false);
factory2.setAddMissingSingletonName(false);
factory2.create();
factory2.start();
partition2 = new InjectedChannelClusterPartition(factory2.createChannel(stackName));
partition2.setPartitionName(partitionName);
partition2.setStateTransferTimeout(30000);
partition2.setMethodCallTimeout(60000);
partition2.setBindIntoJndi(false);
partition2.create();
partition2.start();
DistributedReplicantManager drm2 = partition2.getDistributedReplicantManager();
Thread.sleep(10000);
// confirm that each partition contains two nodes
assertEquals("Partition1 should contain two nodes; ", 2, partition1.getCurrentView().size());
assertEquals("Partition2 should contain two nodes; ", 2, partition2.getCurrentView().size());
drm1.add(SERVICEA, "valueA1");
drm2.add(SERVICEA, "valueA2");
drm2.add(SERVICEB, "valueB2");
// test that only one node is the master replica for serviceA
assertTrue("ServiceA must have a master replica",
drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
assertTrue("ServiceA must have a single master replica",
drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
// ServiceB should only be a master replica on partition2
assertFalse("ServiceB should not be a master replica on partition1",
drm1.isMasterReplica(SERVICEB));
assertTrue("ServiceB must have a master replica on partition2",
drm2.isMasterReplica(SERVICEB));
// confirm that each partition contains correct DRM replicants for services A and B
assertEquals("Partition1 should contain two DRM replicants for serviceA; ",
2, drm1.lookupReplicants(SERVICEA).size());
assertEquals("Partition2 should contain two DRM replicants for serviceA; ",
2, drm2.lookupReplicants(SERVICEA).size());
assertEquals("Partition1 should contain one DRM replicant for serviceB; ",
1, drm1.lookupReplicants(SERVICEB).size());
assertEquals("Partition2 should contain one DRM replicant for serviceB; ",
1, drm2.lookupReplicants(SERVICEB).size());
// simulate a split of the partition
log.info("DRMTestCase.testIsMasterReplica() - stopping GossipRouter");
router.clear(); // temporary workaround for JGRP-1232
router.stop();
sleepThread(15000);
log.info("router stopped, routing table = " + router.dumpRoutingTable() + ", partition1 view=" + partition1.getCurrentView().toString());
assertTrue("router is stopped", !router.isStarted());
assertTrue("router is NOT running", !router.isRunning());
// confirm that each partition contains one node
assertEquals("Partition1 should contain one node after split; ",
1, partition1.getCurrentView().size());
assertEquals("Partition2 should contain one node after split; ",
1, partition2.getCurrentView().size());
// confirm that each node is a master replica for serviceA after the split
assertTrue("ServiceA should be a master replica on partition1 after split",
drm1.isMasterReplica(SERVICEA));
assertTrue("ServiceA should be a master replica on partition2 after split",
drm2.isMasterReplica(SERVICEA));
// ServiceB should still only be a master replica on partition2 after split
assertFalse("ServiceB should not be a master replica on partition1 after split",
drm1.isMasterReplica(SERVICEB));
assertTrue("ServiceB must have a master replica on partition2 after split",
drm2.isMasterReplica(SERVICEB));
// Remove ServiceA replicant from partition1
drm1.remove(SERVICEA);
// test that this node is not the master replica
assertFalse("partition1 is not master replica after dropping ServiceA replicant",
drm1.isMasterReplica(SERVICEA));
//Restore the local replicant
drm1.add(SERVICEA, "valueA1a");
// simulate a merge
log.info("DRMTestCase.testIsMasterReplica() - restarting GossipRouter");
router.start();
// it seems to take more than 15 seconds for the merge to take effect
sleepThread(30000);
assertTrue(router.isStarted());
// confirm that each partition contains two nodes again
assertEquals("Partition1 should contain two nodes after merge; ",
2, partition1.getCurrentView().size());
assertEquals("Partition2 should contain two nodes after merge; ",
2, partition2.getCurrentView().size());
// test that only one node is the master replica for serviceA after merge
assertTrue("ServiceA must have a master replica after merge",
drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
assertTrue("ServiceA must have a single master replica after merge",
drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
// ServiceB should only be a master replica on partition2 after merge
assertFalse("ServiceB should not be a master replica on partition1 after merge",
drm1.isMasterReplica(SERVICEB));
assertTrue("ServiceB must have a master replica on partition2 after merge",
drm2.isMasterReplica(SERVICEB));
// confirm that each partition contains correct DRM replicants for services A and B after merge
assertEquals("Partition1 should contain two DRM replicants for serviceA after merge; ",
2, drm1.lookupReplicants(SERVICEA).size());
assertEquals("Partition2 should contain two DRM replicants for serviceA after merge; ",
2, drm2.lookupReplicants(SERVICEA).size());
assertEquals("Partition1 should contain one DRM replicant for serviceB after merge; ",
1, drm1.lookupReplicants(SERVICEB).size());
assertEquals("Partition2 should contain one DRM replicant for serviceB after merge; ",
1, drm2.lookupReplicants(SERVICEB).size());
partition1.stop();
partition2.stop();
}
finally
{
log.info("DRMTestCase.testIsMasterReplica() - cleaning up resources");
if (partition1Started)
partition1.stop();
if (partition2Started)
partition2.stop();
if (router != null)
router.stop();
}
}