Search in sources :

Example 1 with AllOwnersLostException

use of org.infinispan.statetransfer.AllOwnersLostException 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)

Aggregations

FlagAffectedCommand (org.infinispan.commands.FlagAffectedCommand)1 TopologyAffectedCommand (org.infinispan.commands.TopologyAffectedCommand)1 RemoteException (org.infinispan.remoting.RemoteException)1 SuspectException (org.infinispan.remoting.transport.jgroups.SuspectException)1 AllOwnersLostException (org.infinispan.statetransfer.AllOwnersLostException)1 OutdatedTopologyException (org.infinispan.statetransfer.OutdatedTopologyException)1 CacheTopology (org.infinispan.topology.CacheTopology)1