use of org.infinispan.encoding.DataConversion 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.encoding.DataConversion in project infinispan by infinispan.
the class CallInterceptor method visitReadWriteKeyValueCommand.
@Override
public Object visitReadWriteKeyValueCommand(InvocationContext ctx, ReadWriteKeyValueCommand command) throws Throwable {
ValueMatcher valueMatcher = command.getValueMatcher();
// It's not worth looking up the entry if we're never going to apply the change.
if (valueMatcher == ValueMatcher.MATCH_NEVER) {
command.fail();
return null;
}
MVCCEntry e = (MVCCEntry) ctx.lookupEntry(command.getKey());
// Could be that the key is not local
if (e == null)
return null;
Object prevValue = command.getPrevValue();
Metadata prevMetadata = command.getPrevMetadata();
boolean hasCommandRetry = command.hasAnyFlag(FlagBitSets.COMMAND_RETRY);
// Command only has one previous value, do not override it
if (prevValue == null && !hasCommandRetry) {
prevValue = e.getValue();
prevMetadata = e.getMetadata();
command.setPrevValueAndMetadata(prevValue, prevMetadata);
}
// Protect against outdated old value using the value matcher.
// If the value has been update while on the retry, use the newer value.
// Also take into account that the value might have been removed.
// TODO: Configure equivalence function
// TODO: this won't work properly until we store if the command was executed or not...
Object oldPrevValue = e.getValue();
// Note: other commands don't clone the entry as they don't carry the previous value for comparison
// using value matcher - if other commands are retried these can apply the function multiple times.
// Here we don't want to modify the value in context when trying what would be the outcome of the operation.
MVCCEntry copy = e.clone();
DataConversion valueDataConversion = command.getValueDataConversion();
Object decodedArgument = valueDataConversion.fromStorage(command.getArgument());
EntryViews.AccessLoggingReadWriteView view = EntryViews.readWrite(copy, prevValue, prevMetadata, command.getKeyDataConversion(), valueDataConversion);
Object ret = snapshot(command.getBiFunction().apply(decodedArgument, view));
if (valueMatcher.matches(oldPrevValue, prevValue, copy.getValue())) {
log.tracef("Execute read-write function on previous value %s and previous metadata %s", prevValue, prevMetadata);
e.setValue(copy.getValue());
e.setMetadata(copy.getMetadata());
// These are the only flags that should be changed with EntryViews.readWrite
e.setChanged(copy.isChanged());
e.setRemoved(copy.isRemoved());
}
// The effective result of retried command is not safe; we'll go to backup anyway
if (!e.isChanged() && !hasCommandRetry) {
command.fail();
}
updateStoreFlags(command, e);
return Param.StatisticsMode.isSkip(command.getParams()) ? ret : StatsEnvelope.create(ret, e, prevValue != null, view.isRead());
}
use of org.infinispan.encoding.DataConversion in project infinispan by infinispan.
the class CallInterceptor method visitReadOnlyManyCommand.
@Override
public Object visitReadOnlyManyCommand(InvocationContext ctx, ReadOnlyManyCommand command) throws Throwable {
if (command instanceof TxReadOnlyManyCommand) {
TxReadOnlyManyCommand txReadOnlyManyCommand = (TxReadOnlyManyCommand) command;
List<List<Mutation>> mutations = txReadOnlyManyCommand.getMutations();
if (mutations != null && !mutations.isEmpty()) {
return visitTxReadOnlyCommand(ctx, (TxReadOnlyManyCommand) command, mutations);
}
}
Collection<?> keys = command.getKeys();
// lazy execution triggers exceptions on unexpected places
ArrayList<Object> retvals = new ArrayList<>(keys.size());
boolean skipStats = Param.StatisticsMode.isSkip(command.getParams());
DataConversion keyDataConversion = command.getKeyDataConversion();
DataConversion valueDataConversion = command.getValueDataConversion();
Function function = command.getFunction();
for (Object k : keys) {
CacheEntry me = ctx.lookupEntry(k);
EntryView.ReadEntryView view = me.isNull() ? EntryViews.noValue(k, keyDataConversion) : EntryViews.readOnly(me, keyDataConversion, valueDataConversion);
Object ret = snapshot(function.apply(view));
retvals.add(skipStats ? ret : StatsEnvelope.create(ret, me.isNull()));
}
return retvals.stream();
}
use of org.infinispan.encoding.DataConversion in project infinispan by infinispan.
the class CallInterceptor method visitReadWriteManyCommand.
@Override
public Object visitReadWriteManyCommand(InvocationContext ctx, ReadWriteManyCommand command) throws Throwable {
// Can't return a lazy stream here because the current code in
// EntryWrappingInterceptor expects any changes to be done eagerly,
// otherwise they're not applied. So, apply the function eagerly and
// return a lazy stream of the void returns.
Collection<Object> keys = command.getAffectedKeys();
List<Object> returns = new ArrayList<>(keys.size());
boolean skipStats = Param.StatisticsMode.isSkip(command.getParams());
DataConversion keyDataConversion = command.getKeyDataConversion();
DataConversion valueDataConversion = command.getValueDataConversion();
Function function = command.getFunction();
keys.forEach(k -> {
MVCCEntry entry = (MVCCEntry) ctx.lookupEntry(k);
boolean exists = entry.getValue() != null;
EntryViews.AccessLoggingReadWriteView view = EntryViews.readWrite(entry, keyDataConversion, valueDataConversion);
Object r = snapshot(function.apply(view));
returns.add(skipStats ? r : StatsEnvelope.create(r, entry, exists, view.isRead()));
updateStoreFlags(command, entry);
});
return returns;
}
use of org.infinispan.encoding.DataConversion 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();
}
Aggregations