return super.handleDefault(ctx, cmd);
}
});
// do not allow coordinator to send topology updates to node B
final ClusterTopologyManager ctm0 = TestingUtil.extractGlobalComponent(manager(0), ClusterTopologyManager.class);
ctm0.setRebalancingEnabled(false);
log.info("Adding a new node ..");
addClusterEnabledCacheManager(cacheConfigBuilder);
log.info("Added a new node");
// node B is not a member yet and rebalance has not started yet
CacheTopology cacheTopology = advancedCache(1).getComponentRegistry().getStateTransferManager().getCacheTopology();
assertNull(cacheTopology.getPendingCH());
assertTrue(cacheTopology.getMembers().contains(address(0)));
assertFalse(cacheTopology.getMembers().contains(address(1)));
assertFalse(cacheTopology.getCurrentCH().getMembers().contains(address(1)));
// no keys should be present on node B yet because state transfer is blocked
assertTrue(cache(1).keySet().isEmpty());
// initiate a REPLACE
Future<Object> getFuture = fork(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
return cache(1).replace("myKey", "newValue");
} catch (Exception e) {
log.errorf(e, "REPLACE failed: %s", e.getMessage());
throw e;
}
}
});
// wait for REPLACE command on node B to reach beyond *EntryWrappingInterceptor, where it will block.
// the value seen so far is null
if (!replaceStartedLatch.await(15, TimeUnit.SECONDS)) {
throw new TimeoutException();
}
// paranoia, yes the value is still missing from data container
assertTrue(cache(1).keySet().isEmpty());
// allow rebalance to start
ctm0.setRebalancingEnabled(true);
// wait for state transfer to end
TestingUtil.waitForRehashToComplete(cache(0), cache(1));
// the state should be already transferred now