Search in sources :

Example 1 with FlagAffectedCommand

use of org.infinispan.commands.FlagAffectedCommand in project infinispan by infinispan.

the class BaseStateTransferInterceptor method handleExceptionOnReadCommandReturn.

private Object handleExceptionOnReadCommandReturn(InvocationContext rCtx, VisitableCommand rCommand, Throwable t) throws Throwable {
    Throwable ce = t;
    while (ce instanceof RemoteException) {
        ce = ce.getCause();
    }
    TopologyAffectedCommand cmd = (TopologyAffectedCommand) rCommand;
    final CacheTopology cacheTopology = distributionManager.getCacheTopology();
    int currentTopologyId = cacheTopology.getTopologyId();
    int requestedTopologyId;
    if (ce instanceof SuspectException) {
        // Read commands must ignore CacheNotFoundResponses
        throw new IllegalStateException("Read commands must ignore leavers");
    } else if (ce instanceof OutdatedTopologyException) {
        logRetry(currentTopologyId, cmd);
        // We can get OTE for dist reads even if current topology information is sufficient:
        // 1. A has topology in phase READ_ALL_WRITE_ALL, sends message to both old owner B and new C
        // 2. C has old topology with READ_OLD_WRITE_ALL, so it responds with UnsureResponse
        // 3. C updates topology to READ_ALL_WRITE_ALL, B updates to READ_NEW_WRITE_ALL
        // 4. B receives the read, but it already can't read: responds with UnsureResponse
        // 5. A receives two unsure responses and throws OTE
        // However, now we are sure that we can immediately retry the request, because C must have updated its topology
        OutdatedTopologyException ote = (OutdatedTopologyException) ce;
        requestedTopologyId = cmd.getTopologyId() + ote.topologyIdDelta;
    } else if (ce instanceof AllOwnersLostException) {
        if (getLog().isTraceEnabled())
            getLog().tracef("All owners for command %s have been lost.", cmd);
        // In scattered cache it might be common to lose the single owner, we need to retry. We will find out that
        // we can return null only after the next topology is installed. If partition handling is enabled we decide
        // only based on the availability status.
        // In other cache modes, during partition the exception is already handled in PartitionHandlingInterceptor,
        // and if the handling is not enabled, we can't but return null.
        requestedTopologyId = cmd.getTopologyId() + 1;
    } else {
        throw t;
    }
    // Only retry once if currentTopologyId > cmdTopologyId + 1
    int retryTopologyId = Math.max(currentTopologyId, requestedTopologyId);
    cmd.setTopologyId(retryTopologyId);
    ((FlagAffectedCommand) cmd).addFlags(FlagBitSets.COMMAND_RETRY);
    if (retryTopologyId == currentTopologyId) {
        return invokeNextAndHandle(rCtx, rCommand, handleReadCommandReturn);
    } else {
        return makeStage(asyncInvokeNext(rCtx, rCommand, stateTransferLock.transactionDataFuture(retryTopologyId))).andHandle(rCtx, rCommand, handleReadCommandReturn);
    }
}
Also used : FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) AllOwnersLostException(org.infinispan.statetransfer.AllOwnersLostException) CacheTopology(org.infinispan.topology.CacheTopology) TopologyAffectedCommand(org.infinispan.commands.TopologyAffectedCommand) OutdatedTopologyException(org.infinispan.statetransfer.OutdatedTopologyException) RemoteException(org.infinispan.remoting.RemoteException) SuspectException(org.infinispan.remoting.transport.jgroups.SuspectException)

Example 2 with FlagAffectedCommand

use of org.infinispan.commands.FlagAffectedCommand in project infinispan by infinispan.

the class NonTxBackupOwnerBecomingPrimaryOwnerTest method doTest.

protected void doTest(final TestOperation op) throws Exception {
    final String key = "testkey";
    final String cacheName = getDefaultCacheName();
    op.insertPreviousValue(advancedCache(0, cacheName), key);
    CheckPoint checkPoint = new CheckPoint();
    LocalTopologyManager ltm0 = extractGlobalComponent(manager(0), LocalTopologyManager.class);
    int preJoinTopologyId = ltm0.getCacheTopology(cacheName).getTopologyId();
    int joinTopologyId = preJoinTopologyId + 1;
    int stateReceivedTopologyId = joinTopologyId + 1;
    final AdvancedCache<Object, Object> cache0 = advancedCache(0);
    addBlockingLocalTopologyManager(manager(0), checkPoint, joinTopologyId, stateReceivedTopologyId);
    final AdvancedCache<Object, Object> cache1 = advancedCache(1);
    addBlockingLocalTopologyManager(manager(1), checkPoint, joinTopologyId, stateReceivedTopologyId);
    // Add a new member and block the rebalance before the final topology is installed
    ConfigurationBuilder c = getConfigurationBuilder();
    c.clustering().stateTransfer().awaitInitialTransfer(false);
    CountDownLatch stateTransferLatch = new CountDownLatch(1);
    if (op.getPreviousValue() != null) {
        c.customInterceptors().addInterceptor().before(EntryWrappingInterceptor.class).interceptor(new StateTransferLatchInterceptor(stateTransferLatch));
    } else {
        stateTransferLatch.countDown();
    }
    // Add a new cache manager, but don't start it yet
    GlobalConfigurationBuilder globalBuilder = GlobalConfigurationBuilder.defaultClusteredBuilder();
    globalBuilder.serialization().addContextInitializer(DistributionRehashSCI.INSTANCE);
    EmbeddedCacheManager cm = createClusteredCacheManager(false, globalBuilder, c, new TransportFlags());
    registerCacheManager(cm);
    addBlockingLocalTopologyManager(manager(2), checkPoint, joinTopologyId, stateReceivedTopologyId);
    log.tracef("Starting the cache on the joiner");
    final AdvancedCache<Object, Object> cache2 = advancedCache(2);
    checkPoint.trigger("allow_topology_" + joinTopologyId + "_on_" + address(0));
    checkPoint.trigger("allow_topology_" + joinTopologyId + "_on_" + address(1));
    checkPoint.trigger("allow_topology_" + joinTopologyId + "_on_" + address(2));
    // Wait for the write CH to contain the joiner everywhere
    eventually(() -> cache0.getRpcManager().getMembers().size() == 3 && cache1.getRpcManager().getMembers().size() == 3 && cache2.getRpcManager().getMembers().size() == 3);
    CacheTopology duringJoinTopology = ltm0.getCacheTopology(cacheName);
    assertEquals(joinTopologyId, duringJoinTopology.getTopologyId());
    assertNotNull(duringJoinTopology.getPendingCH());
    int keySegment = TestingUtil.getSegmentForKey(key, cache0);
    log.tracef("Rebalance started. Found key %s with current owners %s and pending owners %s", key, duringJoinTopology.getCurrentCH().locateOwnersForSegment(keySegment), duringJoinTopology.getPendingCH().locateOwnersForSegment(keySegment));
    // We need to wait for the state transfer to insert the entry before inserting the blocking interceptor;
    // otherwise we could block the PUT_FOR_STATE_TRANSFER instead
    stateTransferLatch.await(10, TimeUnit.SECONDS);
    // Every operation command will be blocked before reaching the distribution interceptor on cache1
    CyclicBarrier beforeCache1Barrier = new CyclicBarrier(2);
    BlockingInterceptor<?> blockingInterceptor1 = new BlockingInterceptor<>(beforeCache1Barrier, op.getCommandClass(), false, false);
    extractInterceptorChain(cache1).addInterceptorBefore(blockingInterceptor1, TriangleDistributionInterceptor.class);
    // Every operation command will be blocked after returning to the distribution interceptor on cache2
    CyclicBarrier afterCache2Barrier = new CyclicBarrier(2);
    BlockingInterceptor<?> blockingInterceptor2 = new BlockingInterceptor<>(afterCache2Barrier, op.getCommandClass(), true, false, cmd -> !(cmd instanceof FlagAffectedCommand) || !((FlagAffectedCommand) cmd).hasAnyFlag(FlagBitSets.PUT_FOR_STATE_TRANSFER));
    extractInterceptorChain(cache2).addInterceptorBefore(blockingInterceptor2, StateTransferInterceptor.class);
    // Put from cache0 with cache0 as primary owner, cache2 will become the primary owner for the retry
    Future<Object> future = fork(() -> op.perform(cache0, key));
    // Wait for the command to be executed on cache2 and unblock it
    afterCache2Barrier.await(10, TimeUnit.SECONDS);
    afterCache2Barrier.await(10, TimeUnit.SECONDS);
    // Allow the READ_ALL_WRITE_ALL PHASE topology update to proceed on all the caches
    checkPoint.trigger("allow_topology_" + stateReceivedTopologyId + "_on_" + address(0));
    checkPoint.trigger("allow_topology_" + stateReceivedTopologyId + "_on_" + address(1));
    checkPoint.trigger("allow_topology_" + stateReceivedTopologyId + "_on_" + address(2));
    // Wait for the topology to change everywhere
    waitForNoRebalance(cache0, cache1, cache2);
    // Allow the put command to throw an OutdatedTopologyException on cache1
    log.tracef("Unblocking the put command on node " + address(1));
    beforeCache1Barrier.await(10, TimeUnit.SECONDS);
    beforeCache1Barrier.await(10, TimeUnit.SECONDS);
    // Allow the retry to proceed on cache1
    CacheTopology postReceiveStateTopology = ltm0.getCacheTopology(cacheName);
    if (postReceiveStateTopology.getCurrentCH().locateOwnersForSegment(keySegment).contains(address(1))) {
        beforeCache1Barrier.await(10, TimeUnit.SECONDS);
        beforeCache1Barrier.await(10, TimeUnit.SECONDS);
    }
    // And allow the retry to finish successfully on cache2
    afterCache2Barrier.await(10, TimeUnit.SECONDS);
    afterCache2Barrier.await(10, TimeUnit.SECONDS);
    // Check that the write command didn't fail
    Object result = future.get(10, TimeUnit.SECONDS);
    assertEquals(op.getReturnValueWithRetry(), result);
    log.tracef("Write operation is done");
    // Check the value on all the nodes
    assertEquals(op.getValue(), cache0.get(key));
    assertEquals(op.getValue(), cache1.get(key));
    assertEquals(op.getValue(), cache2.get(key));
    // Check that there are no leaked locks
    assertFalse(cache0.getAdvancedCache().getLockManager().isLocked(key));
    assertFalse(cache1.getAdvancedCache().getLockManager().isLocked(key));
    assertFalse(cache2.getAdvancedCache().getLockManager().isLocked(key));
}
Also used : GlobalConfigurationBuilder(org.infinispan.configuration.global.GlobalConfigurationBuilder) ConfigurationBuilder(org.infinispan.configuration.cache.ConfigurationBuilder) GlobalConfigurationBuilder(org.infinispan.configuration.global.GlobalConfigurationBuilder) BlockingInterceptor(org.infinispan.distribution.BlockingInterceptor) EntryWrappingInterceptor(org.infinispan.interceptors.impl.EntryWrappingInterceptor) CountDownLatch(java.util.concurrent.CountDownLatch) EmbeddedCacheManager(org.infinispan.manager.EmbeddedCacheManager) CheckPoint(org.infinispan.test.fwk.CheckPoint) CyclicBarrier(java.util.concurrent.CyclicBarrier) FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) CacheTopology(org.infinispan.topology.CacheTopology) TransportFlags(org.infinispan.test.fwk.TransportFlags) CheckPoint(org.infinispan.test.fwk.CheckPoint) LocalTopologyManager(org.infinispan.topology.LocalTopologyManager)

Example 3 with FlagAffectedCommand

use of org.infinispan.commands.FlagAffectedCommand in project infinispan by infinispan.

the class BaseDistributionInterceptor method handleFunctionalReadManyCommand.

protected <C extends TopologyAffectedCommand & FlagAffectedCommand> Object handleFunctionalReadManyCommand(InvocationContext ctx, C command, ReadManyCommandHelper<C> helper) {
    // TODO: repeatable-reads are not implemented - see visitReadOnlyKeyCommand
    if (command.hasAnyFlag(FlagBitSets.CACHE_MODE_LOCAL | FlagBitSets.SKIP_REMOTE_LOOKUP)) {
        return handleLocalOnlyReadManyCommand(ctx, command, helper.keys(command));
    }
    LocalizedCacheTopology cacheTopology = checkTopologyId(command);
    Collection<?> keys = helper.keys(command);
    if (!ctx.isOriginLocal()) {
        return handleRemoteReadManyCommand(ctx, command, keys, helper);
    }
    if (keys.isEmpty()) {
        return Stream.empty();
    }
    ConsistentHash ch = cacheTopology.getReadConsistentHash();
    int estimateForOneNode = 2 * keys.size() / ch.getMembers().size();
    List<Object> availableKeys = new ArrayList<>(estimateForOneNode);
    Map<Address, List<Object>> requestedKeys = getKeysByOwner(ctx, keys, cacheTopology, availableKeys, null);
    CompletionStage<Void> requiredKeysFuture = helper.fetchRequiredKeys(cacheTopology, requestedKeys, availableKeys, ctx, command);
    if (requiredKeysFuture == null) {
        return asyncValue(fetchAndApplyValues(ctx, command, helper, keys, availableKeys, requestedKeys));
    } else {
        // b) fetchAndApplyValues invokes the command on availableKeys and stores the result
        return asyncValue(requiredKeysFuture.thenCompose(nil -> fetchAndApplyValues(ctx, command, helper, keys, availableKeys, requestedKeys)));
    }
}
Also used : WriteCommand(org.infinispan.commands.write.WriteCommand) Arrays(java.util.Arrays) GetCacheEntryCommand(org.infinispan.commands.read.GetCacheEntryCommand) CacheNotFoundResponse(org.infinispan.remoting.responses.CacheNotFoundResponse) LogFactory(org.infinispan.util.logging.LogFactory) UnsureResponse(org.infinispan.remoting.responses.UnsureResponse) GetKeysInGroupCommand(org.infinispan.commands.remote.GetKeysInGroupCommand) InvocationContext(org.infinispan.context.InvocationContext) CompletableFutures(org.infinispan.util.concurrent.CompletableFutures) TxInvocationContext(org.infinispan.context.impl.TxInvocationContext) OutdatedTopologyException(org.infinispan.statetransfer.OutdatedTopologyException) Map(java.util.Map) RpcOptions(org.infinispan.remoting.rpc.RpcOptions) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Collection(java.util.Collection) InvocationSuccessFunction(org.infinispan.interceptors.InvocationSuccessFunction) ResponseCollector(org.infinispan.remoting.transport.ResponseCollector) List(java.util.List) SingletonMapResponseCollector(org.infinispan.remoting.transport.impl.SingletonMapResponseCollector) CompletionStage(java.util.concurrent.CompletionStage) Stream(java.util.stream.Stream) SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue) FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) TopologyAffectedCommand(org.infinispan.commands.TopologyAffectedCommand) ArrayCollector(org.infinispan.commons.util.ArrayCollector) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) HashMap(java.util.HashMap) GetAllCommand(org.infinispan.commands.read.GetAllCommand) RemoteValueRetrievedListener(org.infinispan.distribution.RemoteValueRetrievedListener) Function(java.util.function.Function) ReadOnlyKeyCommand(org.infinispan.commands.functional.ReadOnlyKeyCommand) InternalExpirationManager(org.infinispan.expiration.impl.InternalExpirationManager) ArrayList(java.util.ArrayList) Start(org.infinispan.factories.annotations.Start) MapResponseCollector(org.infinispan.remoting.transport.impl.MapResponseCollector) FlagBitSets(org.infinispan.context.impl.FlagBitSets) AbstractDataWriteCommand(org.infinispan.commands.write.AbstractDataWriteCommand) KeyPartitioner(org.infinispan.distribution.ch.KeyPartitioner) SingleResponseCollector(org.infinispan.remoting.transport.impl.SingleResponseCollector) ClusteredGetCommand(org.infinispan.commands.remote.ClusteredGetCommand) Log(org.infinispan.util.logging.Log) BiConsumer(java.util.function.BiConsumer) VoidResponseCollector(org.infinispan.remoting.transport.impl.VoidResponseCollector) AbstractDataCommand(org.infinispan.commands.read.AbstractDataCommand) SegmentSpecificCommand(org.infinispan.commands.SegmentSpecificCommand) DataWriteCommand(org.infinispan.commands.write.DataWriteCommand) ValueMatcher(org.infinispan.commands.write.ValueMatcher) ClearCommand(org.infinispan.commands.write.ClearCommand) Address(org.infinispan.remoting.transport.Address) ExceptionResponse(org.infinispan.remoting.responses.ExceptionResponse) Response(org.infinispan.remoting.responses.Response) ClusteringInterceptor(org.infinispan.interceptors.impl.ClusteringInterceptor) ReplicableCommand(org.infinispan.commands.ReplicableCommand) GetKeyValueCommand(org.infinispan.commands.read.GetKeyValueCommand) CacheEntry(org.infinispan.container.entries.CacheEntry) ValidResponse(org.infinispan.remoting.responses.ValidResponse) Inject(org.infinispan.factories.annotations.Inject) ReadOnlyManyCommand(org.infinispan.commands.functional.ReadOnlyManyCommand) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) GlobalTransaction(org.infinispan.transaction.xa.GlobalTransaction) DistributionInfo(org.infinispan.distribution.DistributionInfo) VisitableCommand(org.infinispan.commands.VisitableCommand) DeliverOrder(org.infinispan.remoting.inboundhandler.DeliverOrder) Collections(java.util.Collections) BaseClusteredReadCommand(org.infinispan.commands.remote.BaseClusteredReadCommand) TimeService(org.infinispan.commons.time.TimeService) NullCacheEntry(org.infinispan.container.entries.NullCacheEntry) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Address(org.infinispan.remoting.transport.Address) ArrayList(java.util.ArrayList) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) List(java.util.List) ArrayList(java.util.ArrayList)

Example 4 with FlagAffectedCommand

use of org.infinispan.commands.FlagAffectedCommand in project infinispan by infinispan.

the class NonTxStateTransferOverwritingValue2Test method blockEntryCommit.

private void blockEntryCommit(final CheckPoint checkPoint, AdvancedCache<Object, Object> cache) {
    ClusteringDependentLogic cdl1 = TestingUtil.extractComponent(cache, ClusteringDependentLogic.class);
    ClusteringDependentLogic replaceCdl = new ClusteringDependentLogicDelegator(cdl1) {

        @Override
        public CompletionStage<Void> commitEntry(CacheEntry entry, FlagAffectedCommand command, InvocationContext ctx, Flag trackFlag, boolean l1Invalidation) {
            // skip for clear command!
            if (entry instanceof ClearCacheEntry) {
                return super.commitEntry(entry, command, ctx, trackFlag, l1Invalidation);
            }
            final Address source = ctx.getOrigin();
            CacheEntry newEntry = new CacheEntryDelegator(entry) {

                @Override
                public void commit(DataContainer container) {
                    checkPoint.trigger("pre_commit_entry_" + getKey() + "_from_" + source);
                    try {
                        checkPoint.awaitStrict("resume_commit_entry_" + getKey() + "_from_" + source, 10, SECONDS);
                    } catch (InterruptedException | TimeoutException e) {
                        throw new RuntimeException(e);
                    }
                    super.commit(container);
                    checkPoint.trigger("post_commit_entry_" + getKey() + "_from_" + source);
                }
            };
            return super.commitEntry(newEntry, command, ctx, trackFlag, l1Invalidation);
        }
    };
    TestingUtil.replaceComponent(cache, ClusteringDependentLogic.class, replaceCdl, true);
}
Also used : Address(org.infinispan.remoting.transport.Address) ClusteringDependentLogic(org.infinispan.interceptors.locking.ClusteringDependentLogic) CacheEntryDelegator(org.infinispan.test.fwk.CacheEntryDelegator) ClearCacheEntry(org.infinispan.container.entries.ClearCacheEntry) CacheEntry(org.infinispan.container.entries.CacheEntry) Flag(org.infinispan.context.Flag) ClearCacheEntry(org.infinispan.container.entries.ClearCacheEntry) FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) DataContainer(org.infinispan.container.DataContainer) InvocationContext(org.infinispan.context.InvocationContext) ClusteringDependentLogicDelegator(org.infinispan.test.fwk.ClusteringDependentLogicDelegator) TimeoutException(java.util.concurrent.TimeoutException)

Example 5 with FlagAffectedCommand

use of org.infinispan.commands.FlagAffectedCommand in project infinispan by infinispan.

the class ClusteringInterceptor method checkTopologyId.

protected LocalizedCacheTopology checkTopologyId(TopologyAffectedCommand command) {
    LocalizedCacheTopology cacheTopology = distributionManager.getCacheTopology();
    int currentTopologyId = cacheTopology.getTopologyId();
    int cmdTopology = command.getTopologyId();
    if (command instanceof FlagAffectedCommand && ((((FlagAffectedCommand) command).hasAnyFlag(FlagBitSets.SKIP_OWNERSHIP_CHECK | FlagBitSets.CACHE_MODE_LOCAL)))) {
        getLog().tracef("Skipping topology check for command %s", command);
        return cacheTopology;
    }
    if (getLog().isTraceEnabled()) {
        getLog().tracef("Current topology %d, command topology %d", currentTopologyId, cmdTopology);
    }
    if (cmdTopology >= 0 && currentTopologyId != cmdTopology) {
        throw OutdatedTopologyException.RETRY_NEXT_TOPOLOGY;
    }
    return cacheTopology;
}
Also used : FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology)

Aggregations

FlagAffectedCommand (org.infinispan.commands.FlagAffectedCommand)8 CacheException (org.infinispan.commons.CacheException)3 OutdatedTopologyException (org.infinispan.statetransfer.OutdatedTopologyException)3 TopologyAffectedCommand (org.infinispan.commands.TopologyAffectedCommand)2 CacheEntry (org.infinispan.container.entries.CacheEntry)2 InvocationContext (org.infinispan.context.InvocationContext)2 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)2 Address (org.infinispan.remoting.transport.Address)2 CacheTopology (org.infinispan.topology.CacheTopology)2 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 CompletionStage (java.util.concurrent.CompletionStage)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 CyclicBarrier (java.util.concurrent.CyclicBarrier)1 TimeoutException (java.util.concurrent.TimeoutException)1