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);
}
}
Aggregations