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