Search in sources :

Example 1 with ControlledRpcManager

use of org.infinispan.util.ControlledRpcManager in project infinispan by infinispan.

the class NonTxInvalidationLockingTest method testConcurrentWritesFromDifferentNodes.

public void testConcurrentWritesFromDifferentNodes() throws Exception {
    Cache<Object, Object> cache1 = cache(0, CACHE);
    ControlledRpcManager rpc1 = ControlledRpcManager.replaceRpcManager(cache1);
    Cache<Object, Object> cache2 = cache(1, CACHE);
    ControlledRpcManager rpc2 = ControlledRpcManager.replaceRpcManager(cache2);
    CompletableFuture<ControlledRpcManager.BlockedRequest<InvalidateCommand>> invalidate1 = rpc1.expectCommandAsync(InvalidateCommand.class);
    CompletableFuture<Object> put1 = cache1.putAsync(KEY, VALUE1);
    CompletableFuture<ControlledRpcManager.BlockedRequest<InvalidateCommand>> invalidate2 = rpc2.expectCommandAsync(InvalidateCommand.class);
    CompletableFuture<Object> put2 = cache2.putAsync(KEY, VALUE2);
    ControlledRpcManager.SentRequest sentInvalidate1 = invalidate1.join().send();
    ControlledRpcManager.SentRequest sentInvalidate2 = invalidate2.join().send();
    sentInvalidate1.expectAllResponses().receive();
    sentInvalidate2.expectAllResponses().receive();
    put1.get(10, TimeUnit.SECONDS);
    put2.get(10, TimeUnit.SECONDS);
    assertEquals(VALUE1, cache1.get(KEY));
    assertEquals(VALUE2, cache2.get(KEY));
}
Also used : ControlledRpcManager(org.infinispan.util.ControlledRpcManager)

Example 2 with ControlledRpcManager

use of org.infinispan.util.ControlledRpcManager in project infinispan by infinispan.

the class ReplicationTxExceptionTest method testReplicationFailure.

public void testReplicationFailure() throws Exception {
    Cache<?, ?> cache = cache(0);
    ControlledRpcManager controlledRpcManager = ControlledRpcManager.replaceRpcManager(cache);
    try {
        Future<Void> future = fork(() -> {
            controlledRpcManager.expectCommand(VersionedPrepareCommand.class).fail();
            controlledRpcManager.expectCommand(RollbackCommand.class).send().receiveAll();
        });
        TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
        tm.begin();
        cache(0).put("k0", "v");
        Exceptions.expectException(RollbackException.class, tm::commit);
        future.get(30, TimeUnit.SECONDS);
    } finally {
        controlledRpcManager.revertRpcManager();
    }
}
Also used : VersionedPrepareCommand(org.infinispan.commands.tx.VersionedPrepareCommand) TransactionManager(javax.transaction.TransactionManager) ControlledRpcManager(org.infinispan.util.ControlledRpcManager)

Example 3 with ControlledRpcManager

use of org.infinispan.util.ControlledRpcManager 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));
}
Also used : ControlledRpcManager(org.infinispan.util.ControlledRpcManager) MagicKey(org.infinispan.distribution.MagicKey)

Example 4 with ControlledRpcManager

use of org.infinispan.util.ControlledRpcManager in project infinispan by infinispan.

the class NonTxStateTransferOverwritingValue2Test method doTest.

private void doTest(final TestWriteOperation op) throws Exception {
    // Test scenario:
    // cache0 is the only member in the cluster, cache1 joins
    // Key k is in the cache, and is transferred to cache1
    // A user operation/tx also modifies key k
    // Even if both state transfer and the user tx try to commit the entry for k concurrently,
    // the value of k at the end should be the one set by the user tx.
    final AdvancedCache<Object, Object> cache0 = advancedCache(0);
    final String key = "key";
    // Prepare for replace/remove: put a previous value in cache0
    final Object previousValue = op.getPreviousValue();
    if (previousValue != null) {
        cache0.put(key, previousValue);
        assertEquals(previousValue, cache0.get(key));
        log.tracef("Previous value inserted: %s = %s", key, previousValue);
    }
    int preJoinTopologyId = cache0.getDistributionManager().getCacheTopology().getTopologyId();
    // Block any state response commands on cache0
    // So that we can install the spy ClusteringDependentLogic on cache1 before state transfer is applied
    final CheckPoint checkPoint = new CheckPoint();
    ControlledRpcManager blockingRpcManager0 = ControlledRpcManager.replaceRpcManager(cache0);
    blockingRpcManager0.excludeCommands(BackupWriteCommand.class, BackupAckCommand.class);
    // Block the rebalance confirmation on coordinator (to avoid the retrying of commands)
    blockRebalanceConfirmation(manager(0), checkPoint, preJoinTopologyId + 1);
    // Start the joiner
    log.tracef("Starting the cache on the joiner");
    ConfigurationBuilder c = getConfigurationBuilder();
    c.clustering().stateTransfer().awaitInitialTransfer(false);
    addClusterEnabledCacheManager(c);
    final AdvancedCache<Object, Object> cache1 = advancedCache(1);
    // Wait for the write CH to contain the joiner everywhere
    eventually(() -> cache0.getRpcManager().getMembers().size() == 2 && cache1.getRpcManager().getMembers().size() == 2);
    // Every PutKeyValueCommand will be blocked before committing the entry on cache1
    blockEntryCommit(checkPoint, cache1);
    // Wait for cache0 to collect the state to send to cache1 (including our previous value).
    ControlledRpcManager.BlockedRequest blockedStateResponse = blockingRpcManager0.expectCommand(StateResponseCommand.class);
    // Allow the state to be applied on cache1 (writing the old value for our entry)
    ControlledRpcManager.SentRequest sentStateResponse = blockedStateResponse.send();
    // Wait for state transfer tx/operation to call commitEntry on cache1 and block
    checkPoint.awaitStrict("pre_commit_entry_" + key + "_from_" + null, 5, SECONDS);
    // Put/Replace/Remove from cache0 with cache0 as primary owner, cache1 as backup owner
    // The put command will be blocked on cache1 just before committing the entry.
    Future<Object> future = fork(() -> op.perform(cache0, key));
    // Check that the user write is blocked by the state transfer write
    boolean blocked = checkPoint.peek(1, SECONDS, "pre_commit_entry_" + key + "_from_" + address(0)) == null;
    assertTrue(blocked);
    // Allow state transfer to commit
    checkPoint.trigger("resume_commit_entry_" + key + "_from_" + null);
    // Check that the user operation can now commit the entry
    checkPoint.awaitStrict("pre_commit_entry_" + key + "_from_" + address(0), 5, SECONDS);
    // Allow the user put to commit
    checkPoint.trigger("resume_commit_entry_" + key + "_from_" + address(0));
    // Wait for both state transfer and the command to commit
    checkPoint.awaitStrict("post_commit_entry_" + key + "_from_" + null, 10, SECONDS);
    checkPoint.awaitStrict("post_commit_entry_" + key + "_from_" + address(0), 10, 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);
    // Receive the response for the state response command (only after all commits have finished)
    sentStateResponse.receiveAll();
    // Allow the rebalance confirmation to proceed and wait for the topology to change everywhere
    int rebalanceTopologyId = preJoinTopologyId + 1;
    checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + address(0));
    checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + address(1));
    TestingUtil.waitForNoRebalance(cache0, cache1);
    // Check the value on all the nodes
    assertEquals(op.getValue(), cache0.get(key));
    assertEquals(op.getValue(), cache1.get(key));
    blockingRpcManager0.stopBlocking();
}
Also used : ConfigurationBuilder(org.infinispan.configuration.cache.ConfigurationBuilder) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ControlledRpcManager(org.infinispan.util.ControlledRpcManager) CheckPoint(org.infinispan.test.fwk.CheckPoint) CheckPoint(org.infinispan.test.fwk.CheckPoint)

Example 5 with ControlledRpcManager

use of org.infinispan.util.ControlledRpcManager 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));
}
Also used : BlockingInterceptor(org.infinispan.distribution.BlockingInterceptor) CheckPoint(org.infinispan.test.fwk.CheckPoint) CyclicBarrier(java.util.concurrent.CyclicBarrier) StateTransferStartCommand(org.infinispan.commands.statetransfer.StateTransferStartCommand) StateResponseCommand(org.infinispan.commands.statetransfer.StateResponseCommand) MagicKey(org.infinispan.distribution.MagicKey) ControlledRpcManager(org.infinispan.util.ControlledRpcManager) CheckPoint(org.infinispan.test.fwk.CheckPoint)

Aggregations

ControlledRpcManager (org.infinispan.util.ControlledRpcManager)37 BlockingLocalTopologyManager (org.infinispan.util.BlockingLocalTopologyManager)9 MagicKey (org.infinispan.distribution.MagicKey)7 CyclicBarrier (java.util.concurrent.CyclicBarrier)6 TxCompletionNotificationCommand (org.infinispan.commands.remote.recovery.TxCompletionNotificationCommand)6 EmbeddedCacheManager (org.infinispan.manager.EmbeddedCacheManager)5 ConfigurationBuilder (org.infinispan.configuration.cache.ConfigurationBuilder)4 BlockingInterceptor (org.infinispan.distribution.BlockingInterceptor)4 Map (java.util.Map)3 RpcManager (org.infinispan.remoting.rpc.RpcManager)3 CheckPoint (org.infinispan.test.fwk.CheckPoint)3 Test (org.testng.annotations.Test)3 Future (java.util.concurrent.Future)2 Transaction (javax.transaction.Transaction)2 Cache (org.infinispan.Cache)2 ClusteredGetCommand (org.infinispan.commands.remote.ClusteredGetCommand)2 StateResponseCommand (org.infinispan.commands.statetransfer.StateResponseCommand)2 CacheStatisticCollector (org.infinispan.extendedstats.CacheStatisticCollector)2 Address (org.infinispan.remoting.transport.Address)2 MultipleCacheManagersTest (org.infinispan.test.MultipleCacheManagersTest)2