return invocation.callRealMethod();
}
}).when(spyLocalTopologyManager).handleRebalance(eq(CACHE_NAME), any(CacheTopology.class), anyInt());
final EmbeddedCacheManager cm4 = addClusterEnabledCacheManager(defaultConfig,
new TransportFlags().withFD(true).withMerge(true));
Future<Cache<Object,Object>> cacheFuture = fork(new Callable<Cache<Object, Object>>() {
@Override
public Cache<Object, Object> call() throws Exception {
return cm4.getCache(CACHE_NAME);
}
});
log.debugf("Waiting for the REBALANCE_START command to reach the merge coordinator");
checkpoint.awaitStrict("rebalance_" + (viewIdAfterSplit + 1), 10, TimeUnit.SECONDS);
// merge the partitions
log.debugf("Merging the cluster partitions");
d1.setDiscardAll(false);
d2.setDiscardAll(false);
d3.setDiscardAll(false);
// wait for the JGroups merge
long startTime = System.currentTimeMillis();
TestingUtil.blockUntilViewsReceived(30000, cacheManagers);
// unblock the REBALANCE_START command
log.debugf("Unblocking the REBALANCE_START command on the coordinator");
checkpoint.triggerForever("merge");
// wait for the 4th cache to finish joining
Cache<Object, Object> c4 = cacheFuture.get(30, TimeUnit.SECONDS);
TestingUtil.waitForRehashToComplete(c1, c2, c3, c4);
long endTime = System.currentTimeMillis();
log.debugf("Merge took %s", Util.prettyPrintTime(endTime - startTime));
assert endTime - startTime < 30000 : "Merge took too long: " + Util.prettyPrintTime(endTime - startTime);
// Check that another node can join
ConfigurationBuilder defaultConfig = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, true);
EmbeddedCacheManager cm5 = addClusterEnabledCacheManager(defaultConfig,
new TransportFlags().withFD(true).withMerge(true));
Cache<Object, Object> c5 = cm5.getCache(CACHE_NAME);
TestingUtil.blockUntilViewsReceived(30000, true, c1, c2, c3, c4, c5);
TestingUtil.waitForRehashToComplete(c1, c2, c3, c4, c5);
}