n, // number of nodes
3, // replicas
"MasterSlave", true); // do rebalance
// start controller
MockController controller =
new MockController(_zkaddr, clusterName, "controller_0");
controller.syncStart();
// start participants
Map<String, Set<String>> errTransitions = new HashMap<String, Set<String>>();
errTransitions.put("SLAVE-MASTER", TestHelper.setOf("TestDB0_4"));
errTransitions.put("ERROR-DROPPED", TestHelper.setOf("TestDB0_4"));
for (int i = 0; i < n; i++) {
String instanceName = "localhost_" + (12918 + i);
if (i == 0) {
participants[i] = new MockParticipant(_zkaddr, clusterName, instanceName);
participants[i].setTransition(new ErrTransition(errTransitions));
} else {
participants[i] = new MockParticipant(_zkaddr, clusterName, instanceName);
}
participants[i].syncStart();
}
Map<String, Map<String, String>> errStateMap = new HashMap<String, Map<String, String>>();
errStateMap.put("TestDB0", new HashMap<String, String>());
errStateMap.get("TestDB0").put("TestDB0_4", "localhost_12918");
boolean result =
ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
clusterName, errStateMap));
Assert.assertTrue(result);
// drop resource containing error partitions should invoke error->dropped transition
// if error happens during error->dropped transition, partition should be disabled
ClusterSetup.processCommandLineArgs(new String[] {
"--zkSvr", _zkaddr, "--dropResource", clusterName, "TestDB0"
});
// make sure TestDB0_4 stay in ERROR state and is disabled
result =
ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(_zkaddr,
clusterName, errStateMap));
Assert.assertTrue(result);
ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, _baseAccessor);
PropertyKey.Builder keyBuilder = accessor.keyBuilder();
InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig("localhost_12918"));
List<String> disabledPartitions = config.getDisabledPartitions();
// System.out.println("disabledPartitions: " + disabledPartitions);
Assert.assertEquals(disabledPartitions.size(), 1, "TestDB0_4 should be disabled");
Assert.assertEquals(disabledPartitions.get(0), "TestDB0_4");
// ExteranlView should have TestDB0_4->localhost_12918_>ERROR
ExternalView ev = accessor.getProperty(keyBuilder.externalView("TestDB0"));
Set<String> partitions = ev.getPartitionSet();
Assert.assertEquals(partitions.size(), 1, "Should have TestDB0_4->localhost_12918->ERROR");
String errPartition = partitions.iterator().next();
Assert.assertEquals(errPartition, "TestDB0_4");
Map<String, String> stateMap = ev.getStateMap(errPartition);
Assert.assertEquals(stateMap.size(), 1);
Assert.assertEquals(stateMap.keySet().iterator().next(), "localhost_12918");
Assert.assertEquals(stateMap.get("localhost_12918"), HelixDefinedState.ERROR.name());
// localhost_12918 should have TestDB0_4 in ERROR state
CurrentState cs =
accessor.getProperty(keyBuilder.currentState(participants[0].getInstanceName(),
participants[0].getSessionId(), "TestDB0"));
Map<String, String> partitionStateMap = cs.getPartitionStateMap();
Assert.assertEquals(partitionStateMap.size(), 1);
Assert.assertEquals(partitionStateMap.keySet().iterator().next(), "TestDB0_4");
Assert.assertEquals(partitionStateMap.get("TestDB0_4"), HelixDefinedState.ERROR.name());
// all other participants should have cleaned up empty current state
for (int i = 1; i < n; i++) {
String instanceName = participants[i].getInstanceName();
String sessionId = participants[i].getSessionId();
Assert.assertNull(accessor.getProperty(keyBuilder.currentState(instanceName, sessionId,
"TestDB0")));
}
// clean up
controller.syncStop();
for (int i = 0; i < n; i++) {
participants[i].syncStop();
}
System.out.println("END " + clusterName + " at " + new Date(System.currentTimeMillis()));