Search in sources :

Example 1 with MetadataAwareCommand

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)));
        }
    }
}
Also used : MetadataAwareCommand(org.infinispan.commands.MetadataAwareCommand) EntryVersion(org.infinispan.container.versioning.EntryVersion) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) ValidResponse(org.infinispan.remoting.responses.ValidResponse) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) EmbeddedMetadata(org.infinispan.metadata.EmbeddedMetadata) Metadata(org.infinispan.metadata.Metadata) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) DistributionInfo(org.infinispan.distribution.DistributionInfo)

Aggregations

MetadataAwareCommand (org.infinispan.commands.MetadataAwareCommand)1 RemoteMetadata (org.infinispan.container.entries.RemoteMetadata)1 RepeatableReadEntry (org.infinispan.container.entries.RepeatableReadEntry)1 EntryVersion (org.infinispan.container.versioning.EntryVersion)1 DistributionInfo (org.infinispan.distribution.DistributionInfo)1 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)1 EmbeddedMetadata (org.infinispan.metadata.EmbeddedMetadata)1 Metadata (org.infinispan.metadata.Metadata)1 ValidResponse (org.infinispan.remoting.responses.ValidResponse)1