32, // partitions
n, // nodes
2, // replicas
"MasterSlave", true);
final MockController controller = new MockController(zkAddr, clusterName, "controller_0");
controller.syncStart();
MockParticipant[] participants = new MockParticipant[n];
for (int i = 0; i < n; i++) {
String instanceName = "localhost_" + (12918 + i);
participants[i] = new MockParticipant(zkAddr, clusterName, instanceName);
participants[i].syncStart();
// register a controller listener on participant_0
if (i == 0) {
// ZkHelixTestManager manager = participants[0].getManager();
MockParticipant manager = participants[0];
manager.addCurrentStateChangeListener(new CurrentStateChangeListener() {
@Override
public void onStateChange(String instanceName, List<CurrentState> statesInfo,
NotificationContext changeContext) {
// To change body of implemented methods use File | Settings | File Templates.
// System.out.println(instanceName + " on current-state change, type: " +
// changeContext.getType());
}
}, manager.getInstanceName(), manager.getSessionId());
}
}
Boolean result =
ClusterStateVerifier
.verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(zkAddr,
clusterName));
Assert.assertTrue(result);
MockParticipant participantToExpire = participants[0];
String oldSessionId = participantToExpire.getSessionId();
PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName);
// check manager#hanlders
Assert.assertEquals(participantToExpire.getHandlers().size(), 2,
"Should have 2 handlers: CURRENTSTATE/{sessionId}, and MESSAGES");
// check zkclient#listeners
Map<String, Set<IZkDataListener>> dataListeners =
ZkTestHelper.getZkDataListener(participantToExpire.getZkClient());
Map<String, Set<IZkChildListener>> childListeners =
ZkTestHelper.getZkChildListener(participantToExpire.getZkClient());
// printZkListeners(participantToExpire.getZkClient());
Assert.assertEquals(dataListeners.size(), 1,
"Should have 1 path (CURRENTSTATE/{sessionId}/TestDB0) which has 1 data-listeners");
String path =
keyBuilder.currentState(participantToExpire.getInstanceName(), oldSessionId, "TestDB0")
.getPath();
Assert.assertEquals(dataListeners.get(path).size(), 1, "Should have 1 data-listeners on path: "
+ path);
Assert
.assertEquals(childListeners.size(), 2,
"Should have 2 paths (CURRENTSTATE/{sessionId}, and MESSAGES) each of which has 1 child-listener");
path = keyBuilder.currentStates(participantToExpire.getInstanceName(), oldSessionId).getPath();
Assert.assertEquals(childListeners.get(path).size(), 1,
"Should have 1 child-listener on path: " + path);
path = keyBuilder.messages(participantToExpire.getInstanceName()).getPath();
Assert.assertEquals(childListeners.get(path).size(), 1,
"Should have 1 child-listener on path: " + path);
path = keyBuilder.controller().getPath();
Assert.assertNull(childListeners.get(path), "Should have no child-listener on path: " + path);
// check zookeeper#watches on client side
Map<String, List<String>> watchPaths =
ZkTestHelper.getZkWatch(participantToExpire.getZkClient());
// System.out.println("localhost_12918 zk-client side watchPaths: " + watchPaths + "\n");
Assert
.assertEquals(watchPaths.get("dataWatches").size(), 3,
"Should have 3 data-watches: CURRENTSTATE/{sessionId}, CURRENTSTATE/{sessionId}/TestDB, MESSAGES");
Assert.assertEquals(watchPaths.get("childWatches").size(), 2,
"Should have 2 child-watches: MESSAGES, and CURRENTSTATE/{sessionId}");
// expire localhost_12918
System.out.println("Expire participant: " + participantToExpire.getInstanceName()
+ ", session: " + participantToExpire.getSessionId());
ZkTestHelper.expireSession(participantToExpire.getZkClient());
String newSessionId = participantToExpire.getSessionId();
System.out.println(participantToExpire.getInstanceName() + " oldSessionId: " + oldSessionId
+ ", newSessionId: " + newSessionId);
result =
ClusterStateVerifier
.verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(zkAddr,
clusterName));
Assert.assertTrue(result);
// check manager#hanlders
Assert
.assertEquals(
participantToExpire.getHandlers().size(),
1,
"Should have 1 handlers: MESSAGES. CURRENTSTATE/{sessionId} handler should be removed by CallbackHandler#handleChildChange()");
// check zkclient#listeners
dataListeners = ZkTestHelper.getZkDataListener(participantToExpire.getZkClient());
childListeners = ZkTestHelper.getZkChildListener(participantToExpire.getZkClient());
// printZkListeners(participantToExpire.getZkClient());
Assert.assertTrue(dataListeners.isEmpty(), "Should have no data-listeners");
Assert
.assertEquals(
childListeners.size(),
2,
"Should have 2 paths (CURRENTSTATE/{oldSessionId}, and MESSAGES). "
+ "CONTROLLER and MESSAGE has 1 child-listener each. CURRENTSTATE/{oldSessionId} doesn't have listener (ZkClient doesn't remove empty childListener set. probably a ZkClient bug. see ZkClient#unsubscribeChildChange())");
path = keyBuilder.currentStates(participantToExpire.getInstanceName(), oldSessionId).getPath();
Assert.assertEquals(childListeners.get(path).size(), 0,
"Should have no child-listener on path: " + path);
path = keyBuilder.messages(participantToExpire.getInstanceName()).getPath();
Assert.assertEquals(childListeners.get(path).size(), 1,
"Should have 1 child-listener on path: " + path);
path = keyBuilder.controller().getPath();
Assert.assertNull(childListeners.get(path), "Should have no child-listener on path: " + path);
// check zookeeper#watches on client side
watchPaths = ZkTestHelper.getZkWatch(participantToExpire.getZkClient());
// System.out.println("localhost_12918 zk-client side watchPaths: " + watchPaths + "\n");
Assert.assertEquals(watchPaths.get("dataWatches").size(), 1,
"Should have 1 data-watches: MESSAGES");
Assert.assertEquals(watchPaths.get("childWatches").size(), 1,
"Should have 1 child-watches: MESSAGES");
Assert
.assertEquals(watchPaths.get("existWatches").size(), 2,
"Should have 2 exist-watches: CURRENTSTATE/{oldSessionId} and CURRENTSTATE/{oldSessionId}/TestDB0");
// another session expiry on localhost_12918 should clear the two exist-watches on
// CURRENTSTATE/{oldSessionId}
System.out.println("Expire participant: " + participantToExpire.getInstanceName()
+ ", session: " + participantToExpire.getSessionId());
ZkTestHelper.expireSession(participantToExpire.getZkClient());
result =
ClusterStateVerifier
.verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(zkAddr,
clusterName));
Assert.assertTrue(result);
// check zookeeper#watches on client side
watchPaths = ZkTestHelper.getZkWatch(participantToExpire.getZkClient());
// System.out.println("localhost_12918 zk-client side watchPaths: " + watchPaths + "\n");
Assert.assertEquals(watchPaths.get("dataWatches").size(), 1,
"Should have 1 data-watches: MESSAGES");
Assert.assertEquals(watchPaths.get("childWatches").size(), 1,
"Should have 1 child-watches: MESSAGES");
Assert
.assertEquals(
watchPaths.get("existWatches").size(),
0,
"Should have no exist-watches. exist-watches on CURRENTSTATE/{oldSessionId} and CURRENTSTATE/{oldSessionId}/TestDB0 should be cleared during handleNewSession");
// Thread.sleep(1000);
// clean up
controller.syncStop();
for (int i = 0; i < n; i++) {
participants[i].syncStop();
}
System.out.println("END " + clusterName + " at " + new Date(System.currentTimeMillis()));