use of org.infinispan.persistence.util.EntryLoader in project infinispan by infinispan.
the class WriteSkewHelper method performWriteSkewCheckAndReturnNewVersions.
public static CompletionStage<Map<Object, IncrementableEntryVersion>> performWriteSkewCheckAndReturnNewVersions(VersionedPrepareCommand prepareCommand, EntryLoader<?, ?> entryLoader, VersionGenerator versionGenerator, TxInvocationContext<?> context, KeySpecificLogic ksl, KeyPartitioner keyPartitioner) {
if (prepareCommand.getVersionsSeen() == null) {
// Do not perform the write skew check if this prepare command is being replayed for state transfer
return CompletableFutures.completedEmptyMap();
}
Map<Object, IncrementableEntryVersion> uv = new HashMap<>();
AggregateCompletionStage<Map<Object, IncrementableEntryVersion>> aggregateCompletionStage = CompletionStages.aggregateCompletionStage(uv);
for (WriteCommand c : prepareCommand.getModifications()) {
for (Object k : c.getAffectedKeys()) {
int segment = SegmentSpecificCommand.extractSegment(c, k, keyPartitioner);
if (ksl.performCheckOnSegment(segment)) {
CacheEntry<?, ?> cacheEntry = context.lookupEntry(k);
if (!(cacheEntry instanceof VersionedRepeatableReadEntry)) {
continue;
}
VersionedRepeatableReadEntry entry = (VersionedRepeatableReadEntry) cacheEntry;
CompletionStage<Boolean> skewStage = entry.performWriteSkewCheck(entryLoader, segment, context, prepareCommand.getVersionsSeen().get(k), versionGenerator, c.hasAnyFlag(FlagBitSets.ROLLING_UPGRADE));
aggregateCompletionStage.dependsOn(skewStage.thenAccept(passSkew -> {
if (!passSkew) {
throw new WriteSkewException("Write skew detected on key " + entry.getKey() + " for transaction " + context.getCacheTransaction(), entry.getKey());
}
IncrementableEntryVersion newVersion = incrementVersion(entry, versionGenerator);
// Have to synchronize as we could have returns on different threads due to notifications/loaders etc
synchronized (uv) {
uv.put(entry.getKey(), newVersion);
}
}));
}
}
}
return aggregateCompletionStage.freeze();
}
Aggregations