if (cmd instanceof PutKeyValueCommand && ((PutKeyValueCommand) cmd).hasFlag(Flag.PUT_FOR_STATE_TRANSFER)) {
// signal we encounter a state transfer PUT
applyStateStartedLatch1.countDown();
// wait until it is ok to apply state
if (!applyStateProceedLatch.await(15, TimeUnit.SECONDS)) {
throw new TimeoutException();
}
}
return super.handleDefault(ctx, cmd);
}
}, 0);
final CountDownLatch applyStateStartedLatch2 = new CountDownLatch(1);
advancedCache(2).addInterceptor(new CommandInterceptor() {
@Override
protected Object handleDefault(InvocationContext ctx, VisitableCommand cmd) throws Throwable {
// if this 'put' command is caused by state transfer we delay it to ensure other cache operations
// are performed first and create opportunity for inconsistencies
if (cmd instanceof PutKeyValueCommand && ((PutKeyValueCommand) cmd).hasFlag(Flag.PUT_FOR_STATE_TRANSFER)) {
// signal we encounter a state transfer PUT
applyStateStartedLatch2.countDown();
// wait until it is ok to apply state
if (!applyStateProceedLatch.await(15, TimeUnit.SECONDS)) {
throw new TimeoutException();
}
}
return super.handleDefault(ctx, cmd);
}
}, 0);
log.info("Killing node 1 ..");
TestingUtil.killCacheManagers(manager(1));
log.info("Node 1 killed");
DataContainer dc0 = advancedCache(0).getDataContainer();
DataContainer dc2 = advancedCache(2).getDataContainer();
// wait for state transfer on nodes A and C to progress to the point where data segments are about to be applied
if (!applyStateStartedLatch1.await(15, TimeUnit.SECONDS)) {
throw new TimeoutException();
}
if (!applyStateStartedLatch2.await(15, TimeUnit.SECONDS)) {
throw new TimeoutException();
}
if (op == Operation.CLEAR) {
log.info("Clearing cache ..");
cache(0).clear();