use of org.infinispan.remoting.transport.jgroups.SuspectException in project infinispan by infinispan.
the class ScatteredStateConsumerImpl method handleSegments.
@Override
protected CompletionStage<Void> handleSegments(boolean isRebalance, IntSet addedSegments, IntSet removedSegments, IntSet transactionOnlySegments) {
if (!isRebalance) {
log.trace("This is not a rebalance, not doing anything...");
return CompletableFutures.completedNull();
}
if (addedSegments.isEmpty()) {
log.trace("No segments missing");
return CompletableFutures.completedNull();
}
synchronized (transferMapsLock) {
inboundSegments = IntSets.mutableFrom(addedSegments);
}
chunkCounter.set(0);
if (log.isTraceEnabled())
log.tracef("Revoking all segments, chunk counter reset to 0");
CacheRpcCommand command = commandsFactory.buildScatteredStateConfirmRevokeCommand(cacheTopology.getTopologyId(), addedSegments);
// we need to wait synchronously for the completion
return rpcManager.invokeCommandOnAll(command, MapResponseCollector.ignoreLeavers(), rpcManager.getSyncRpcOptions()).handle((responses, throwable) -> {
if (throwable == null) {
try {
svm.startKeyTransfer(addedSegments);
requestKeyTransfer(addedSegments);
} catch (SuspectException e) {
log.tracef("Key transfer source %s was suspected, another source will be selected", e.getSuspect());
} catch (Throwable t) {
log.failedToRequestSegments(cacheName, null, addedSegments, t);
}
} else {
if (cache.wired().getStatus() == ComponentStatus.RUNNING) {
log.failedConfirmingRevokedSegments(throwable);
} else {
// reduce verbosity for stopping cache
log.debug("Failed confirming revoked segments", throwable);
}
for (int segment : addedSegments) {
svm.notifyKeyTransferFinished(segment, false, false);
}
notifyEndOfStateTransferIfNeeded();
}
return null;
});
}
use of org.infinispan.remoting.transport.jgroups.SuspectException in project infinispan by infinispan.
the class SingleClusterExecutor method submit.
@Override
public CompletableFuture<Void> submit(Runnable runnable) {
Address target = findTarget();
if (target == null) {
return CompletableFutures.completedExceptionFuture(new SuspectException("No available nodes!"));
}
if (log.isTraceEnabled()) {
log.tracef("Submitting runnable to single remote node - JGroups Address %s", target);
}
CompletableFuture<Void> future = new CompletableFuture<>();
if (target == me) {
return super.submit(runnable);
} else {
ReplicableCommand command = new ReplicableRunnableCommand(runnable);
CompletionStage<Response> request = transport.invokeCommand(target, command, PassthroughSingleResponseCollector.INSTANCE, DeliverOrder.NONE, time, unit);
request.whenComplete((r, t) -> {
if (t != null) {
future.completeExceptionally(t);
} else {
consumeResponse(r, target, future::completeExceptionally);
future.complete(null);
}
});
}
return future;
}
use of org.infinispan.remoting.transport.jgroups.SuspectException 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);
}
}
use of org.infinispan.remoting.transport.jgroups.SuspectException in project infinispan by infinispan.
the class CacheNotifierImpl method registerClusterListeners.
private <C> CompletionStage<Void> registerClusterListeners(List<Address> members, UUID generatedId, Address ourAddress, CacheEventFilter<? super K, ? super V> filter, CacheEventConverter<? super K, ? super V, C> converter, Listener l, Object listener, DataConversion keyDataConversion, DataConversion valueDataConversion, boolean useStorageFormat) {
if (log.isTraceEnabled()) {
log.tracef("Replicating cluster listener to other nodes %s for cluster listener with id %s", members, generatedId);
}
ClusterListenerReplicateCallable<K, V> callable = new ClusterListenerReplicateCallable(cache.wired().getName(), generatedId, ourAddress, filter, converter, l.sync(), findListenerCallbacks(listener), keyDataConversion, valueDataConversion, useStorageFormat);
TriConsumer<Address, Void, Throwable> handleSuspect = (a, ignore, t) -> {
if (t != null && !(t instanceof SuspectException)) {
log.debugf(t, "Address: %s encountered an exception while adding cluster listener", a);
throw new CacheListenerException(t);
}
};
// Send to all nodes but ours
CompletionStage<Void> completionStage = clusterExecutor.filterTargets(a -> !ourAddress.equals(a)).submitConsumer(callable, handleSuspect);
// the listener - unfortunately if there are no nodes it throws a SuspectException, so we ignore that
return completionStage.thenCompose(v -> clusterExecutor.filterTargets(a -> !members.contains(a) && !a.equals(ourAddress)).submitConsumer(callable, handleSuspect).exceptionally(t -> {
// Ignore any suspect exception
if (!(t instanceof SuspectException)) {
throw new CacheListenerException(t);
}
return null;
}));
}
use of org.infinispan.remoting.transport.jgroups.SuspectException in project infinispan by infinispan.
the class AllClusterExecutor method executeRunnable.
private CompletableFuture<?> executeRunnable(Runnable runnable) {
CompletableFuture<?> localFuture = startLocalInvocation(runnable);
List<Address> targets = getRealTargets(false);
int size = targets.size();
CompletableFuture<?> remoteFuture;
if (size == 1) {
Address target = targets.get(0);
if (log.isTraceEnabled()) {
log.tracef("Submitting runnable to single remote node - JGroups Address %s", target);
}
remoteFuture = new CompletableFuture<>();
ReplicableCommand command = new ReplicableRunnableCommand(runnable);
CompletionStage<Response> request = transport.invokeCommand(target, command, PassthroughSingleResponseCollector.INSTANCE, DeliverOrder.NONE, time, unit);
request.handle((r, t) -> {
if (t != null) {
remoteFuture.completeExceptionally(t);
} else {
consumeResponse(r, target, remoteFuture::completeExceptionally);
// This won't override exception if there was one
remoteFuture.complete(null);
}
return null;
});
} else if (size > 1) {
remoteFuture = new CompletableFuture<>();
ReplicableCommand command = new ReplicableRunnableCommand(runnable);
ResponseCollector<Map<Address, Response>> collector = new PassthroughMapResponseCollector(targets.size());
CompletionStage<Map<Address, Response>> request = transport.invokeCommand(targets, command, collector, DeliverOrder.NONE, time, unit);
request.handle((r, t) -> {
if (t != null) {
remoteFuture.completeExceptionally(t);
} else {
r.forEach((key, value) -> consumeResponse(value, key, remoteFuture::completeExceptionally));
remoteFuture.complete(null);
}
return null;
});
} else if (localFuture != null) {
return localFuture;
} else {
return CompletableFutures.completedExceptionFuture(new SuspectException("No available nodes!"));
}
// remoteFuture is guaranteed to be non null at this point
if (localFuture != null) {
CompletableFuture<Void> future = new CompletableFuture<>();
CompletableFuture.allOf(localFuture, remoteFuture).whenComplete((v, t) -> {
if (t != null) {
if (t instanceof CompletionException) {
future.completeExceptionally(t.getCause());
} else {
future.completeExceptionally(t);
}
} else {
future.complete(null);
}
});
return future;
}
return remoteFuture;
}
Aggregations