use of org.infinispan.util.concurrent.AggregateCompletionStage 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();
}
use of org.infinispan.util.concurrent.AggregateCompletionStage in project infinispan by infinispan.
the class EntryWrappingInterceptor method getAllHandle.
private Object getAllHandle(InvocationContext rCtx, GetAllCommand command, Object rv, Throwable t) {
if (useRepeatableRead) {
for (Object key : command.getKeys()) {
CacheEntry cacheEntry = rCtx.lookupEntry(key);
if (cacheEntry == null) {
// Data was lost
if (log.isTraceEnabled())
log.tracef(t, "Missing entry for " + key);
} else {
cacheEntry.setSkipLookup(true);
}
}
}
AggregateCompletionStage<Void> stage = CompletionStages.aggregateCompletionStage();
// instanceof check excludes the case when the command returns UnsuccessfulResponse
if (t == null && rv instanceof Map) {
boolean notify = !command.hasAnyFlag(FlagBitSets.SKIP_LISTENER_NOTIFICATION) && notifier.hasListener(CacheEntryVisited.class);
log.tracef("Notifying getAll? %s; result %s", notify, rv);
if (notify) {
Map<Object, Object> map = (Map<Object, Object>) rv;
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value != null) {
Object finalValue = command.isReturnEntries() ? ((CacheEntry) value).getValue() : entry.getValue();
CompletionStage<Void> innerStage = notifier.notifyCacheEntryVisited(entry.getKey(), finalValue, true, rCtx, command);
stage.dependsOn(innerStage.thenCompose(ig -> notifier.notifyCacheEntryVisited(entry.getKey(), finalValue, false, rCtx, command)));
}
}
}
}
return delayedValue(stage.freeze(), rv, t);
}
use of org.infinispan.util.concurrent.AggregateCompletionStage in project infinispan by infinispan.
the class DefaultIracTombstoneManager method performCleanup.
private CompletionStage<Void> performCleanup() {
if (stopped) {
return CompletableFutures.completedNull();
}
scheduler.onTaskStarted(tombstoneMap.size());
try {
AggregateCompletionStage<Void> stage = CompletionStages.aggregateCompletionStage();
RpcOptions rpcOptions = rpcManager.getSyncRpcOptions();
Map<Address, BackPressure<IracTombstonePrimaryCheckCommand, Void>> staleTombstones = new HashMap<>(tombstoneMap.size());
for (IracTombstoneInfo tombstone : tombstoneMap.values()) {
DistributionInfo info = distributionManager.getCacheTopology().getSegmentDistribution(tombstone.getSegment());
if (!info.isWriteOwner()) {
// topology changed, no longer an owner
removeTombstone(tombstone);
continue;
}
// it means the primary owner hasn't sent the update to the remote site.
if (iracManager.running().containsKey(tombstone.getKey())) {
continue;
}
if (!info.isPrimary()) {
BackPressure<IracTombstonePrimaryCheckCommand, Void> backPressure = staleTombstones.get(info.primary());
if (backPressure == null) {
backPressure = new BackPressure<>(commandsFactory.buildIracTombstonePrimaryCheckCommand(batchSize), null);
staleTombstones.put(info.primary(), backPressure);
}
if (backPressure.element.addTombstone(tombstone) == batchSize) {
CompletionStage<Void> rsp;
if (backPressure.delay == null) {
rsp = rpcManager.invokeCommand(info.primary(), backPressure.element, ignoreLeavers(), rpcOptions);
} else {
ReplicableCommand rCmd = backPressure.element;
rsp = backPressure.delay.thenComposeAsync(unused -> rpcManager.invokeCommand(info.primary(), rCmd, ignoreLeavers(), rpcOptions), blockingExecutor);
}
staleTombstones.put(info.primary(), new BackPressure<>(commandsFactory.buildIracTombstonePrimaryCheckCommand(batchSize), rsp));
}
continue;
}
stage.dependsOn(new CleanupTask(tombstone).checkRemoteSites());
}
// sending any pending stale tombstones
for (Map.Entry<Address, BackPressure<IracTombstonePrimaryCheckCommand, Void>> entry : staleTombstones.entrySet()) {
BackPressure<IracTombstonePrimaryCheckCommand, Void> backPressure = entry.getValue();
if (backPressure.element.isEmpty()) {
continue;
}
if (backPressure.delay == null) {
rpcManager.sendTo(entry.getKey(), backPressure.element, DeliverOrder.NONE);
} else {
backPressure.delay.thenRunAsync(() -> rpcManager.sendTo(entry.getKey(), backPressure.element, DeliverOrder.NONE), blockingExecutor);
}
}
return stage.freeze().whenComplete(scheduler);
} catch (Throwable t) {
log.debug("Unexpected exception", t);
scheduler.scheduleWithCurrentDelay();
return CompletableFutures.completedNull();
}
}
use of org.infinispan.util.concurrent.AggregateCompletionStage in project infinispan by infinispan.
the class PersistenceManagerImpl method disableStore.
@Override
public CompletionStage<Void> disableStore(String storeType) {
boolean stillHasAStore = false;
AggregateCompletionStage<Void> aggregateCompletionStage = CompletionStages.aggregateCompletionStage();
long stamp = lock.writeLock();
try {
if (!checkStoreAvailability()) {
return CompletableFutures.completedNull();
}
boolean allAvailable = true;
Iterator<StoreStatus> statusIterator = stores.iterator();
while (statusIterator.hasNext()) {
StoreStatus status = statusIterator.next();
NonBlockingStore<?, ?> nonBlockingStore = unwrapStore(status.store());
if (nonBlockingStore.getClass().getName().equals(storeType) || containedInAdapter(nonBlockingStore, storeType)) {
statusIterator.remove();
aggregateCompletionStage.dependsOn(nonBlockingStore.stop().whenComplete((v, t) -> {
if (t != null) {
log.warn("There was an error stopping the store", t);
}
}));
} else {
stillHasAStore = true;
allAvailable = allAvailable && status.availability;
}
}
if (!stillHasAStore) {
unavailableExceptionMessage = null;
enabled = false;
stopAvailabilityTask();
} else if (allAvailable) {
unavailableExceptionMessage = null;
}
allSegmentedOrShared = allStoresSegmentedOrShared();
listeners.forEach(l -> l.storeChanged(createStatus()));
if (!stillHasAStore) {
AsyncInterceptorChain chain = cache.wired().getAsyncInterceptorChain();
AsyncInterceptor loaderInterceptor = chain.findInterceptorExtending(CacheLoaderInterceptor.class);
if (loaderInterceptor == null) {
PERSISTENCE.persistenceWithoutCacheLoaderInterceptor();
} else {
chain.removeInterceptor(loaderInterceptor.getClass());
}
AsyncInterceptor writerInterceptor = chain.findInterceptorExtending(CacheWriterInterceptor.class);
if (writerInterceptor == null) {
writerInterceptor = chain.findInterceptorWithClass(TransactionalStoreInterceptor.class);
if (writerInterceptor == null) {
PERSISTENCE.persistenceWithoutCacheWriteInterceptor();
} else {
chain.removeInterceptor(writerInterceptor.getClass());
}
} else {
chain.removeInterceptor(writerInterceptor.getClass());
}
}
return aggregateCompletionStage.freeze();
} finally {
lock.unlockWrite(stamp);
}
}
use of org.infinispan.util.concurrent.AggregateCompletionStage in project infinispan by infinispan.
the class CacheNotifierImpl method doNotifyPassivated.
private CompletionStage<Void> doNotifyPassivated(K key, V value, boolean pre, FlagAffectedCommand command) {
EventImpl<K, V> e = EventImpl.createEvent(cache.wired(), CACHE_ENTRY_PASSIVATED);
boolean isLocalNodePrimaryOwner = isLocalNodePrimaryOwner(key);
AggregateCompletionStage aggregateCompletionStage = null;
for (CacheEntryListenerInvocation<K, V> listener : cacheEntryPassivatedListeners) {
// Need a wrapper per invocation since converter could modify the entry in it
key = convertKey(listener, key);
value = convertValue(listener, value);
e.setPre(pre);
e.setKey(key);
e.setValue(value);
aggregateCompletionStage = composeStageIfNeeded(aggregateCompletionStage, listener.invoke(new EventWrapper<>(key, e, command), isLocalNodePrimaryOwner));
}
return aggregateCompletionStage != null ? aggregateCompletionStage.freeze() : CompletableFutures.completedNull();
}
Aggregations