use of org.infinispan.distribution.MagicKey in project infinispan by infinispan.
the class DenyReadWriteRemoveAllTest method beforeSplit.
@Override
protected void beforeSplit() {
// Put values locally before the split as an AvaililibityException will be thrown during the split
conflictKey = new MagicKey(cache(p0.node(0)), cache(p1.node(0)));
cache(p0.node(0)).put(conflictKey, "V1");
cache(p1.node(0)).getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).put(conflictKey, "V2");
}
use of org.infinispan.distribution.MagicKey in project infinispan by infinispan.
the class PessimisticReplTxTest method createCacheManagers.
@Override
protected void createCacheManagers() throws Throwable {
final ConfigurationBuilder conf = buildConfiguration();
createCluster(TestDataSCI.INSTANCE, conf, 2);
waitForClusterToForm();
k = new MagicKey(cache(0));
}
use of org.infinispan.distribution.MagicKey in project infinispan by infinispan.
the class NonTxPrimaryOwnerLeavingTest method doTest.
private void doTest(TestWriteOperation operation, boolean blockTopologyOnOriginator) throws Exception {
final AdvancedCache<Object, Object> cache0 = advancedCache(0);
AdvancedCache<Object, Object> cache1 = advancedCache(1);
AdvancedCache<Object, Object> cache2 = advancedCache(2);
TopologyUpdateListener listener0 = new TopologyUpdateListener();
cache0.addListener(listener0);
TopologyUpdateListener listener2 = new TopologyUpdateListener();
cache2.addListener(listener2);
// Block remote put commands invoked from cache0
ControlledRpcManager crm = ControlledRpcManager.replaceRpcManager(cache0);
crm.excludeCommands(StateTransferStartCommand.class, StateResponseCommand.class);
// Try to put a key/value from cache0 with cache1 the primary owner
final MagicKey key = new MagicKey(cache1);
Future<Object> future = fork(() -> operation.perform(cache0, key));
// After the write command was sent, kill cache1
ControlledRpcManager.BlockedRequest blockedWrite = crm.expectCommand(operation.getCommandClass());
cache1.stop();
if (!blockTopologyOnOriginator) {
listener0.unblockOnce();
listener0.waitForTopologyToFinish();
}
// Now that cache1 is stopped, unblock the write command and wait for the responses
blockedWrite.send().expectResponse(address(1), CacheNotFoundResponse.INSTANCE).receive();
if (blockTopologyOnOriginator) {
// The retry should be blocked on the originator until we unblock the topology update
crm.expectNoCommand(100, TimeUnit.MILLISECONDS);
listener0.unblockOnce();
listener0.waitForTopologyToFinish();
}
// Install the new topology without cache1 on cache2 as well
listener2.unblockOnce();
listener2.waitForTopologyToFinish();
// Retry the write command with a single owner (rebalance topology is blocked).
if (!cache0.getDistributionManager().getCacheTopology().getDistribution(key).isPrimary()) {
crm.expectCommand(operation.getCommandClass()).send().receiveAll();
}
// Check that the put command didn't fail
Object result = future.get(10, TimeUnit.SECONDS);
assertNull(result);
log.tracef("Write operation is done");
cache0.removeListener(listener0);
cache2.removeListener(listener2);
listener0.unblockOnce();
listener0.unblockOnce();
crm.stopBlocking();
// Check the value on the remaining node
assertEquals(operation.getValue(), cache0.get(key));
assertEquals(operation.getValue(), cache2.get(key));
}
use of org.infinispan.distribution.MagicKey in project infinispan by infinispan.
the class BaseTxStateTransferOverwriteTest method doStateTransferInBetweenPrepareCommit.
protected void doStateTransferInBetweenPrepareCommit(final TestWriteOperation op, final boolean additionalValueOnNonOwner) throws Exception {
// Test scenario:
// cache0,1,2 are in the cluster, an owner leaves
// Key k is in the cache, and is transferred to the non owner
// A user operation also modifies key k causing an invalidation
// on the non owner which is getting the state transfer
final AdvancedCache<Object, Object> primaryOwnerCache = advancedCache(0, cacheName);
final AdvancedCache<Object, Object> backupOwnerCache = advancedCache(1, cacheName);
final AdvancedCache<Object, Object> nonOwnerCache = advancedCache(2, cacheName);
final MagicKey key = new MagicKey(op + "-key", cache(0, cacheName), cache(1, cacheName));
// Prepare for replace/remove: put a previous value in cache0
final Object previousValue = op.getPreviousValue();
if (previousValue != null) {
primaryOwnerCache.put(key, previousValue);
assertEquals(previousValue, primaryOwnerCache.get(key));
log.tracef("Previous value inserted: %s = %s", key, previousValue);
assertEquals(previousValue, nonOwnerCache.get(key));
if (l1Enabled()) {
assertIsInL1(nonOwnerCache, key);
}
}
// Need to block after Prepare command was sent after it clears the StateTransferInterceptor
final CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
try {
TransactionManager tm = primaryOwnerCache.getTransactionManager();
Future<?> future = fork(runWithTx(tm, () -> {
if (additionalValueOnNonOwner) {
MagicKey mk = new MagicKey("placeholder", nonOwnerCache);
String value = "somevalue";
primaryOwnerCache.put(mk, value);
log.tracef("Adding additional value on nonOwner value inserted: %s = %s", mk, value);
}
extractInterceptorChain(primaryOwnerCache).addInterceptorBefore(new BlockingInterceptor<>(cyclicBarrier, getVisitableCommand(op), true, false), StateTransferInterceptor.class);
return op.perform(primaryOwnerCache, key);
}));
cyclicBarrier.await(10, SECONDS);
// After the barrier has been hit remove the interceptor, since we can just wake it up through the barrier,
// this way the state transfer won't be blocked if the normal put occurs before it.
removeAllBlockingInterceptorsFromCache(primaryOwnerCache);
// Block the rebalance confirmation on nonOwnerCache
CheckPoint checkPoint = new CheckPoint();
log.trace("Adding proxy to state transfer");
waitUntilStateBeingTransferred(nonOwnerCache, checkPoint);
backupOwnerCache.getCacheManager().stop();
// Wait for non owner to just about get state
checkPoint.awaitStrict("pre_state_apply_invoked_for_" + nonOwnerCache, 10, SECONDS);
// let prepare complete and thus commit command invalidating on nonOwner
cyclicBarrier.await(10, SECONDS);
assertEquals(op.getReturnValue(), future.get(10, SECONDS));
// let state transfer go
checkPoint.trigger("pre_state_apply_release_for_" + nonOwnerCache);
TestingUtil.waitForNoRebalance(primaryOwnerCache, nonOwnerCache);
switch(op) {
case REMOVE:
case REMOVE_EXACT:
break;
default:
assertIsInContainerImmortal(primaryOwnerCache, key);
assertIsInContainerImmortal(nonOwnerCache, key);
break;
}
// Check the value to make sure data container contains correct value
assertEquals(op.getValue(), primaryOwnerCache.get(key));
assertEquals(op.getValue(), nonOwnerCache.get(key));
} finally {
removeAllBlockingInterceptorsFromCache(primaryOwnerCache);
}
}
use of org.infinispan.distribution.MagicKey in project infinispan by infinispan.
the class BaseTxStateTransferOverwriteTest method doTestWhereCommitOccursAfterStateTransferBeginsBeforeCompletion.
/**
* When L1 is enabled this test should not be ran when a previous value is present as it will cause timeouts. Due
* to how locking works with L1 this cannot occur when the previous value exists.
*/
protected void doTestWhereCommitOccursAfterStateTransferBeginsBeforeCompletion(final TestWriteOperation op) throws Exception {
if (l1Enabled() && op.getPreviousValue() != null) {
fail("This test cannot be ran with L1 when a previous value is set");
}
// Test scenario:
// cache0,1,2 are in the cluster, an owner leaves
// Key k is in the cache, and is transferred to the non owner
// A user operation also modifies key k causing an invalidation
// on the non owner which is getting the state transfer
final AdvancedCache<Object, Object> primaryOwnerCache = cache(0, cacheName).getAdvancedCache();
final AdvancedCache<Object, Object> backupOwnerCache = cache(1, cacheName).getAdvancedCache();
final AdvancedCache<Object, Object> nonOwnerCache = cache(2, cacheName).getAdvancedCache();
final MagicKey key = new MagicKey(primaryOwnerCache, backupOwnerCache);
// Prepare for replace/remove: put a previous value in cache0
final Object previousValue = op.getPreviousValue();
if (previousValue != null) {
primaryOwnerCache.put(key, previousValue);
assertEquals(previousValue, primaryOwnerCache.get(key));
log.tracef("Previous value inserted: %s = %s", key, previousValue);
assertEquals(previousValue, nonOwnerCache.get(key));
if (l1Enabled()) {
assertIsInL1(nonOwnerCache, key);
}
}
int preJoinTopologyId = primaryOwnerCache.getDistributionManager().getCacheTopology().getTopologyId();
// Block any state response commands on cache0
CheckPoint checkPoint = new CheckPoint();
ControlledRpcManager blockingRpcManager0 = ControlledRpcManager.replaceRpcManager(primaryOwnerCache);
ControlledRpcManager blockingRpcManager2 = ControlledRpcManager.replaceRpcManager(nonOwnerCache);
// The execution of the write/prepare/commit commands is controlled with the BlockingInterceptor
blockingRpcManager0.excludeCommands(BackupWriteCommand.class, PrepareCommand.class, CommitCommand.class, TxCompletionNotificationCommand.class);
blockingRpcManager2.excludeCommands(BackupAckCommand.class);
// Block the rebalance confirmation on cache0
int rebalanceTopologyId = preJoinTopologyId + 2;
blockRebalanceConfirmation(primaryOwnerCache.getCacheManager(), checkPoint, rebalanceTopologyId);
assertEquals(primaryOwnerCache.getCacheManager().getCoordinator(), primaryOwnerCache.getCacheManager().getAddress());
// Remove the leaver
log.trace("Stopping the cache");
backupOwnerCache.getCacheManager().stop();
// Wait for the write CH to contain the joiner everywhere
eventuallyEquals(2, () -> primaryOwnerCache.getRpcManager().getMembers().size());
eventuallyEquals(2, () -> nonOwnerCache.getRpcManager().getMembers().size());
assertEquals(primaryOwnerCache.getCacheManager().getCoordinator(), primaryOwnerCache.getCacheManager().getAddress());
// Wait for both nodes to start state transfer
if (transactional) {
blockingRpcManager0.expectCommand(StateTransferGetTransactionsCommand.class).send().receiveAll();
blockingRpcManager2.expectCommand(StateTransferGetTransactionsCommand.class).send().receiveAll();
}
ControlledRpcManager.BlockedRequest<StateTransferStartCommand> blockedStateRequest0 = blockingRpcManager0.expectCommand(StateTransferStartCommand.class);
ControlledRpcManager.BlockedRequest<StateTransferStartCommand> blockedStateRequest2 = blockingRpcManager2.expectCommand(StateTransferStartCommand.class);
// Unblock the state request from node 2
// Don't wait for response, because node 2 might be sending the first state response on the request thread
blockedStateRequest2.send().receiveAllAsync();
// Wait for cache0 to collect the state to send to node 2 (including our previous value).
ControlledRpcManager.BlockedRequest<StateResponseCommand> blockedStateResponse0 = blockingRpcManager0.expectCommand(StateResponseCommand.class);
// Every PutKeyValueCommand will be blocked before committing the entry on cache1
CyclicBarrier beforeCommitCache1Barrier = new CyclicBarrier(2);
BlockingInterceptor<?> blockingInterceptor1 = new BlockingInterceptor<>(beforeCommitCache1Barrier, op.getCommandClass(), true, false);
extractInterceptorChain(nonOwnerCache).addInterceptorAfter(blockingInterceptor1, EntryWrappingInterceptor.class);
// Put/Replace/Remove from cache0 with cache0 as primary owner, cache1 will become a backup owner for the retry
// The put command will be blocked on cache1 just before committing the entry.
Future<Object> future = fork(() -> op.perform(primaryOwnerCache, key));
// Wait for the entry to be wrapped on node 2
// The replicated command could be either a non-tx BackupWriteCommand or a PrepareCommand
beforeCommitCache1Barrier.await(10, TimeUnit.SECONDS);
// Remove the interceptor so we don't mess up any other state transfer puts
removeAllBlockingInterceptorsFromCache(nonOwnerCache);
// Allow the state to be applied on cache1 (writing the old value for our entry)
blockedStateResponse0.send().receiveAll();
// Wait for second in line to finish applying the state, but don't allow the rebalance confirmation to be processed.
// (It would change the topology and it would trigger a retry for the command.)
// Don't wait for response, because node 2 might be sending the first state response on the request thread
blockedStateRequest0.send().receiveAllAsync();
blockingRpcManager2.expectCommand(StateResponseCommand.class).send().receiveAll();
checkPoint.awaitStrict("pre_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + primaryOwnerCache.getCacheManager().getAddress(), 10, SECONDS);
// Now allow the command to commit on cache1
beforeCommitCache1Barrier.await(10, TimeUnit.SECONDS);
// Wait for the command to finish and check that it didn't fail
Object result = future.get(10, TimeUnit.SECONDS);
assertEquals(op.getReturnValue(), result);
log.tracef("%s operation is done", op);
// Allow the rebalance confirmation to proceed and wait for the topology to change everywhere
checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + primaryOwnerCache.getCacheManager().getAddress());
checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + nonOwnerCache.getCacheManager().getAddress());
TestingUtil.waitForNoRebalance(primaryOwnerCache, nonOwnerCache);
switch(op) {
case REMOVE:
case REMOVE_EXACT:
break;
default:
assertIsInContainerImmortal(primaryOwnerCache, key);
assertIsInContainerImmortal(nonOwnerCache, key);
break;
}
// Check the value to make sure data container contains correct value
assertEquals(op.getValue(), primaryOwnerCache.get(key));
assertEquals(op.getValue(), nonOwnerCache.get(key));
}
Aggregations