Search in sources :

Example 1 with Mutation

use of org.infinispan.commands.functional.Mutation in project infinispan by infinispan.

the class CallInterceptor method visitReadOnlyKeyCommand.

@Override
public Object visitReadOnlyKeyCommand(InvocationContext ctx, ReadOnlyKeyCommand command) throws Throwable {
    if (command instanceof TxReadOnlyKeyCommand) {
        TxReadOnlyKeyCommand txReadOnlyKeyCommand = (TxReadOnlyKeyCommand) command;
        List<Mutation> mutations = txReadOnlyKeyCommand.getMutations();
        if (mutations != null && !mutations.isEmpty()) {
            return visitTxReadOnlyKeyCommand(ctx, txReadOnlyKeyCommand, mutations);
        }
    }
    Object key = command.getKey();
    CacheEntry entry = ctx.lookupEntry(key);
    if (entry == null) {
        throw new IllegalStateException();
    }
    DataConversion keyDataConversion = command.getKeyDataConversion();
    EntryView.ReadEntryView ro = entry.isNull() ? EntryViews.noValue(key, keyDataConversion) : EntryViews.readOnly(entry, keyDataConversion, command.getValueDataConversion());
    Object ret = snapshot(command.getFunction().apply(ro));
    // We'll consider the entry always read for stats purposes even if the function is a noop
    return Param.StatisticsMode.isSkip(command.getParams()) ? ret : StatsEnvelope.create(ret, entry.isNull());
}
Also used : DataConversion(org.infinispan.encoding.DataConversion) EntryView(org.infinispan.functional.EntryView) TxReadOnlyKeyCommand(org.infinispan.commands.functional.TxReadOnlyKeyCommand) Mutation(org.infinispan.commands.functional.Mutation) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) CacheEntry(org.infinispan.container.entries.CacheEntry)

Example 2 with Mutation

use of org.infinispan.commands.functional.Mutation in project infinispan by infinispan.

the class CallInterceptor method visitTxReadOnlyCommand.

private Object visitTxReadOnlyCommand(InvocationContext ctx, TxReadOnlyManyCommand command, List<List<Mutation>> mutations) {
    Collection<Object> keys = command.getKeys();
    ArrayList<Object> retvals = new ArrayList<>(keys.size());
    Iterator<List<Mutation>> mutIt = mutations.iterator();
    boolean skipStats = Param.StatisticsMode.isSkip(command.getParams());
    Function function = command.getFunction();
    DataConversion keyDataConversion = command.getKeyDataConversion();
    DataConversion valueDataConversion = command.getValueDataConversion();
    for (Object k : keys) {
        List<Mutation> innerMutations = mutIt.next();
        MVCCEntry entry = (MVCCEntry) ctx.lookupEntry(k);
        EntryView.ReadEntryView ro;
        Object ret = null;
        if (mutations.isEmpty()) {
            ro = entry.isNull() ? EntryViews.noValue(k, keyDataConversion) : EntryViews.readOnly(entry, keyDataConversion, valueDataConversion);
        } else {
            EntryView.ReadWriteEntryView rw = EntryViews.readWrite(entry, keyDataConversion, valueDataConversion);
            for (Mutation mutation : innerMutations) {
                entry.updatePreviousValue();
                ret = mutation.apply(rw);
            }
            ro = rw;
        }
        if (function != null) {
            ret = function.apply(ro);
        }
        ret = snapshot(ret);
        retvals.add(skipStats ? ret : StatsEnvelope.create(ret, entry.isNull()));
    }
    return retvals.stream();
}
Also used : ArrayList(java.util.ArrayList) DataConversion(org.infinispan.encoding.DataConversion) BiFunction(java.util.function.BiFunction) Function(java.util.function.Function) EntryView(org.infinispan.functional.EntryView) MVCCEntry(org.infinispan.container.entries.MVCCEntry) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) Mutation(org.infinispan.commands.functional.Mutation)

Example 3 with Mutation

use of org.infinispan.commands.functional.Mutation in project infinispan by infinispan.

the class TxDistributionInterceptor method handleTxFunctionalCommand.

public <C extends AbstractDataWriteCommand & FunctionalCommand> Object handleTxFunctionalCommand(InvocationContext ctx, C command) {
    Object key = command.getKey();
    if (ctx.isOriginLocal()) {
        CacheEntry entry = ctx.lookupEntry(key);
        if (entry == null) {
            if (command.hasAnyFlag(SKIP_REMOTE_FLAGS) || command.loadType() == VisitableCommand.LoadType.DONT_LOAD) {
                entryFactory.wrapExternalEntry(ctx, key, null, false, true);
                return invokeNext(ctx, command);
            }
            LocalizedCacheTopology cacheTopology = checkTopologyId(command);
            int segment = command.getSegment();
            DistributionInfo distributionInfo = cacheTopology.getSegmentDistribution(segment);
            // we could have stale value after state transfer.
            if (distributionInfo.isWriteOwner() || forceRemoteReadForFunctionalCommands && !command.hasAnyFlag(FlagBitSets.SKIP_XSITE_BACKUP)) {
                return asyncInvokeNext(ctx, command, remoteGetSingleKey(ctx, command, key, true));
            }
            List<Mutation<Object, Object, ?>> mutationsOnKey = getMutationsOnKey((TxInvocationContext) ctx, command, key);
            mutationsOnKey.add(command.toMutation(key));
            TxReadOnlyKeyCommand remoteRead = commandsFactory.buildTxReadOnlyKeyCommand(key, null, mutationsOnKey, segment, command.getParams(), command.getKeyDataConversion(), command.getValueDataConversion());
            remoteRead.setTopologyId(command.getTopologyId());
            CompletionStage<SuccessfulResponse> remoteGet = rpcManager.invokeCommandStaggered(distributionInfo.readOwners(), remoteRead, new RemoteGetSingleKeyCollector(), rpcManager.getSyncRpcOptions());
            return asyncValue(remoteGet).thenApply(ctx, command, (rCtx, rCommand, response) -> {
                Object responseValue = ((SuccessfulResponse) response).getResponseValue();
                return unwrapFunctionalResultOnOrigin(rCtx, rCommand.getKey(), responseValue);
            });
        }
        // It's possible that this is not an owner, but the entry was loaded from L1 - let the command run
        return invokeNext(ctx, command);
    } else {
        if (!checkTopologyId(command).isWriteOwner(key)) {
            return null;
        }
        CacheEntry entry = ctx.lookupEntry(key);
        if (entry == null) {
            if (command.hasAnyFlag(SKIP_REMOTE_FLAGS) || command.loadType() == VisitableCommand.LoadType.DONT_LOAD) {
                // in transactional mode, we always need the entry wrapped
                entryFactory.wrapExternalEntry(ctx, key, null, false, true);
            } else {
                return asyncInvokeNext(ctx, command, remoteGetSingleKey(ctx, command, command.getKey(), true));
            }
        }
        return invokeNextThenApply(ctx, command, (rCtx, rCommand, rv) -> wrapFunctionalResultOnNonOriginOnReturn(rv, entry));
    }
}
Also used : SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) TxReadOnlyKeyCommand(org.infinispan.commands.functional.TxReadOnlyKeyCommand) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) Mutation(org.infinispan.commands.functional.Mutation) CacheEntry(org.infinispan.container.entries.CacheEntry) DistributionInfo(org.infinispan.distribution.DistributionInfo)

Example 4 with Mutation

use of org.infinispan.commands.functional.Mutation in project infinispan by infinispan.

the class TxDistributionInterceptor method remoteGetSingleKey.

@Override
protected <C extends FlagAffectedCommand & TopologyAffectedCommand> CompletionStage<Void> remoteGetSingleKey(InvocationContext ctx, C command, Object key, boolean isWrite) {
    CompletionStage<Void> cf = super.remoteGetSingleKey(ctx, command, key, isWrite);
    // and we are just trying to execute all of them from EntryWrappingIntercepot$EntryWrappingVisitor
    if (!ctx.isOriginLocal() || !ctx.isInTxScope()) {
        return cf;
    }
    List<Mutation<Object, Object, ?>> mutationsOnKey = getMutationsOnKey((TxInvocationContext) ctx, command instanceof WriteCommand ? (WriteCommand) command : null, key);
    if (mutationsOnKey.isEmpty()) {
        return cf;
    }
    return cf.thenCompose(ignore -> {
        // TODO Dan: apply the modifications before wrapping the entry in the context
        CompletionStage<Void> stage = entryFactory.wrapEntryForWriting(ctx, key, SegmentSpecificCommand.extractSegment(command, key, keyPartitioner), false, true, CompletableFutures.completedNull());
        return stage.thenRun(() -> {
            MVCCEntry cacheEntry = (MVCCEntry) ctx.lookupEntry(key);
            for (Mutation mutation : mutationsOnKey) {
                EntryView.ReadWriteEntryView readWriteEntryView = EntryViews.readWrite(cacheEntry, mutation.keyDataConversion(), mutation.valueDataConversion());
                mutation.apply(readWriteEntryView);
                cacheEntry.updatePreviousValue();
            }
        });
    });
}
Also used : WriteCommand(org.infinispan.commands.write.WriteCommand) AbstractDataWriteCommand(org.infinispan.commands.write.AbstractDataWriteCommand) EntryView(org.infinispan.functional.EntryView) MVCCEntry(org.infinispan.container.entries.MVCCEntry) Mutation(org.infinispan.commands.functional.Mutation)

Example 5 with Mutation

use of org.infinispan.commands.functional.Mutation in project infinispan by infinispan.

the class TxDistributionInterceptor method handleRemotelyRetrievedKeys.

@Override
protected void handleRemotelyRetrievedKeys(InvocationContext ctx, WriteCommand appliedCommand, List<?> remoteKeys) {
    if (!ctx.isInTxScope()) {
        return;
    }
    List<List<Mutation<Object, Object, ?>>> mutations = getMutations(ctx, appliedCommand, remoteKeys);
    if (mutations == null || mutations.isEmpty()) {
        return;
    }
    Iterator<?> keysIterator = remoteKeys.iterator();
    Iterator<List<Mutation<Object, Object, ?>>> mutationsIterator = mutations.iterator();
    for (; keysIterator.hasNext() && mutationsIterator.hasNext(); ) {
        Object key = keysIterator.next();
        CompletionStage<Void> stage = entryFactory.wrapEntryForWriting(ctx, key, keyPartitioner.getSegment(key), false, true, CompletableFutures.completedNull());
        // We rely on the fact that when isOwner is false this never blocks
        assert CompletionStages.isCompletedSuccessfully(stage);
        MVCCEntry cacheEntry = (MVCCEntry) ctx.lookupEntry(key);
        EntryView.ReadWriteEntryView readWriteEntryView = EntryViews.readWrite(cacheEntry, DataConversion.IDENTITY_KEY, DataConversion.IDENTITY_VALUE);
        for (Mutation mutation : mutationsIterator.next()) {
            mutation.apply(readWriteEntryView);
            cacheEntry.updatePreviousValue();
        }
    }
    assert !keysIterator.hasNext();
    assert !mutationsIterator.hasNext();
}
Also used : EntryView(org.infinispan.functional.EntryView) MVCCEntry(org.infinispan.container.entries.MVCCEntry) List(java.util.List) ArrayList(java.util.ArrayList) Mutation(org.infinispan.commands.functional.Mutation)

Aggregations

Mutation (org.infinispan.commands.functional.Mutation)7 EntryView (org.infinispan.functional.EntryView)5 MVCCEntry (org.infinispan.container.entries.MVCCEntry)4 ArrayList (java.util.ArrayList)3 List (java.util.List)3 BiFunction (java.util.function.BiFunction)2 Function (java.util.function.Function)2 TxReadOnlyKeyCommand (org.infinispan.commands.functional.TxReadOnlyKeyCommand)2 AbstractDataWriteCommand (org.infinispan.commands.write.AbstractDataWriteCommand)2 WriteCommand (org.infinispan.commands.write.WriteCommand)2 CacheEntry (org.infinispan.container.entries.CacheEntry)2 DataConversion (org.infinispan.encoding.DataConversion)2 LinkedList (java.util.LinkedList)1 FunctionalCommand (org.infinispan.commands.functional.FunctionalCommand)1 InternalCacheEntry (org.infinispan.container.entries.InternalCacheEntry)1 LocalTxInvocationContext (org.infinispan.context.impl.LocalTxInvocationContext)1 TxInvocationContext (org.infinispan.context.impl.TxInvocationContext)1 DistributionInfo (org.infinispan.distribution.DistributionInfo)1 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)1 SuccessfulResponse (org.infinispan.remoting.responses.SuccessfulResponse)1