use of org.infinispan.commands.MetadataAwareCommand in project infinispan by infinispan.
the class ScatteredDistributionInterceptor method handleWriteCommand.
private Object handleWriteCommand(InvocationContext ctx, DataWriteCommand command) throws Throwable {
RepeatableReadEntry cacheEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
EntryVersion seenVersion = getVersionOrNull(cacheEntry);
LocalizedCacheTopology cacheTopology = checkTopology(command);
DistributionInfo info = cacheTopology.getSegmentDistribution(command.getSegment());
if (info.primary() == null) {
throw OutdatedTopologyException.RETRY_NEXT_TOPOLOGY;
}
if (isLocalModeForced(command)) {
RepeatableReadEntry contextEntry = cacheEntry;
if (cacheEntry == null) {
entryFactory.wrapExternalEntry(ctx, command.getKey(), null, false, true);
contextEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
}
EntryVersion nextVersion = null;
if (command.hasAnyFlag(FlagBitSets.PUT_FOR_STATE_TRANSFER)) {
// we don't increment versions with state transfer
} else if (info.isPrimary()) {
if (!cacheTopology.isConnected() && command instanceof MetadataAwareCommand) {
// Preload does not use functional commands which are not metadata-aware
Metadata metadata = ((MetadataAwareCommand) command).getMetadata();
svm.updatePreloadedEntryVersion(metadata.version());
} else {
// let's allow local-mode writes on primary owner, preserving versions
nextVersion = svm.incrementVersion(info.segmentId());
}
}
return commitSingleEntryOnReturn(ctx, command, contextEntry, nextVersion);
}
if (ctx.isOriginLocal()) {
if (info.isPrimary()) {
Object seenValue = cacheEntry.getValue();
return invokeNextThenApply(ctx, command, (rCtx, rCommand, rv) -> handleWriteOnOriginPrimary(rCtx, rCommand, rv, cacheEntry, seenValue, seenVersion, cacheTopology, info));
} else {
// not primary owner
CompletionStage<ValidResponse> rpcFuture = singleWriteOnRemotePrimary(info.primary(), command);
return asyncValue(rpcFuture).thenApply(ctx, command, handleWritePrimaryResponse);
}
} else {
// remote origin
if (info.isPrimary()) {
// TODO [ISPN-3918]: the previous value is unreliable as this could be second invocation
return invokeNextThenApply(ctx, command, (rCtx, cmd, rv) -> {
if (!cmd.isSuccessful()) {
if (log.isTraceEnabled())
log.tracef("Skipping the replication of the command as it did not succeed on primary owner (%s).", cmd);
return singleWriteResponse(rCtx, cmd, rv);
}
EntryVersion nextVersion = svm.incrementVersion(info.segmentId());
Metadata metadata = addVersion(cacheEntry.getMetadata(), nextVersion);
cacheEntry.setMetadata(metadata);
CompletionStage<Void> stage;
if (cmd.loadType() != DONT_LOAD) {
stage = commitSingleEntryIfNoChange(cacheEntry, rCtx, cmd);
} else {
stage = commitSingleEntryIfNewer(cacheEntry, rCtx, cmd);
}
Object returnValue = cmd.acceptVisitor(ctx, new PrimaryResponseGenerator(cacheEntry, rv));
return asyncValue(stage).thenApply(rCtx, cmd, (rCtx2, rCommand2, rv2) -> singleWriteResponse(rCtx, rCommand2, returnValue));
});
} else {
// The origin is primary and we're merely backup saving the data
assert cacheEntry == null || command.hasAnyFlag(FlagBitSets.SKIP_OWNERSHIP_CHECK);
RepeatableReadEntry contextEntry;
if (cacheEntry == null) {
entryFactory.wrapExternalEntry(ctx, command.getKey(), null, false, true);
contextEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
} else {
contextEntry = cacheEntry;
}
return invokeNextThenApply(ctx, command, (rCtx, rCommand, rv) -> delayedNull(commitSingleEntryIfNewer(contextEntry, rCtx, rCommand)));
}
}
}
Aggregations