Search in sources :

Example 1 with RepeatableReadEntry

use of org.infinispan.container.entries.RepeatableReadEntry in project infinispan by infinispan.

the class ScatteredDistributionInterceptor method handleWriteManyOnOrigin.

private <C extends WriteCommand, Container, Item> Object handleWriteManyOnOrigin(InvocationContext ctx, C command, WriteManyCommandHelper<C, Container, Item> helper) {
    LocalizedCacheTopology cacheTopology = checkTopology(command);
    Map<Address, Container> remoteEntries = new HashMap<>();
    for (Item item : helper.getItems(command)) {
        Object key = helper.item2key(item);
        DistributionInfo info = cacheTopology.getDistribution(key);
        Address primary = info.primary();
        if (primary == null) {
            throw AllOwnersLostException.INSTANCE;
        } else {
            Container currentEntries = remoteEntries.computeIfAbsent(primary, k -> helper.newContainer());
            helper.accumulate(currentEntries, item);
        }
    }
    Object[] results = command.loadType() == DONT_LOAD ? null : new Object[command.getAffectedKeys().size()];
    MergingCompletableFuture<Object> allFuture = new SyncMergingCompletableFuture<>(remoteEntries.size(), results, helper::transformResult);
    int offset = 0;
    Container localEntries = remoteEntries.remove(rpcManager.getAddress());
    if (localEntries != null) {
        helper.containerSize(localEntries);
        C localCommand = helper.copyForLocal(command, localEntries);
        localCommand.setTopologyId(command.getTopologyId());
        LocalWriteManyHandler handler = new LocalWriteManyHandler(allFuture, localCommand.getAffectedKeys(), cacheTopology);
        invokeNextAndFinally(ctx, localCommand, handler);
    }
    // This will be null in a non-biased variant
    MultiTargetCollector multiTargetCollector = createMultiTargetCollector(command, remoteEntries.size());
    for (Map.Entry<Address, Container> ownerEntry : remoteEntries.entrySet()) {
        Address owner = ownerEntry.getKey();
        // TODO: copyForLocal just creates the command with given entries, not using the segment-aware map
        Container container = ownerEntry.getValue();
        C toPrimary = helper.copyForLocal(command, container);
        toPrimary.setTopologyId(command.getTopologyId());
        CompletionStage<ValidResponse> rpcFuture = manyWriteOnRemotePrimary(owner, toPrimary, multiTargetCollector);
        int myOffset = offset;
        offset += helper.containerSize(container);
        rpcFuture.whenComplete((response, t) -> {
            if (t != null) {
                allFuture.completeExceptionally(t);
                return;
            }
            Object responseValue = response.getResponseValue();
            // Note: we could use PrimaryResponseHandler, but we would have to add the reference to allFuture, offset...
            InternalCacheValue[] values;
            try {
                if (command.loadType() == DONT_LOAD) {
                    if (!(responseValue instanceof InternalCacheValue[])) {
                        allFuture.completeExceptionally(new CacheException("Response from " + owner + ": expected InternalCacheValue[] but it is " + responseValue));
                        return;
                    }
                    values = (InternalCacheValue[]) responseValue;
                } else {
                    if (!(responseValue instanceof Object[]) || (((Object[]) responseValue).length != 2)) {
                        allFuture.completeExceptionally(new CacheException("Response from " + owner + ": expected Object[2] but it is " + responseValue));
                        return;
                    }
                    // We use Object[] { InternalCacheValue[], Object[] } structure to get benefit of same-type array marshalling
                    // TODO optimize returning entry itself
                    // Note: some interceptors relying on the return value *could* have a problem interpreting this
                    values = (InternalCacheValue[]) ((Object[]) responseValue)[0];
                    MergingCompletableFuture.moveListItemsToFuture(((Object[]) responseValue)[1], allFuture, myOffset);
                }
                AggregateCompletionStage<Void> aggregateCompletionStage = CompletionStages.aggregateCompletionStage();
                synchronized (allFuture) {
                    if (allFuture.isDone()) {
                        return;
                    }
                    int i = 0;
                    for (Object key : helper.toKeys(container)) {
                        // we will serve as the backup
                        InternalCacheEntry ice = values[i++].toInternalCacheEntry(key);
                        entryFactory.wrapExternalEntry(ctx, key, ice, true, true);
                        RepeatableReadEntry entry = (RepeatableReadEntry) ctx.lookupEntry(key);
                        // we don't care about setCreated() since backup owner should not fire listeners
                        entry.setChanged(true);
                        aggregateCompletionStage.dependsOn(commitSingleEntryIfNewer(entry, ctx, command));
                        if (entry.isCommitted() && !command.hasAnyFlag(FlagBitSets.PUT_FOR_STATE_TRANSFER)) {
                            scheduleKeyInvalidation(entry.getKey(), entry.getMetadata().version(), entry.isRemoved());
                        }
                    }
                    assert i == values.length;
                }
                aggregateCompletionStage.freeze().thenRun(allFuture::countDown);
            } catch (Throwable t2) {
                allFuture.completeExceptionally(t2);
            }
        });
    }
    return asyncValue(allFuture);
}
Also used : Address(org.infinispan.remoting.transport.Address) HashMap(java.util.HashMap) CacheException(org.infinispan.commons.CacheException) ValidResponse(org.infinispan.remoting.responses.ValidResponse) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) MultiTargetCollector(org.infinispan.util.concurrent.CommandAckCollector.MultiTargetCollector) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) DistributionInfo(org.infinispan.distribution.DistributionInfo) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) Map(java.util.Map) HashMap(java.util.HashMap)

Example 2 with RepeatableReadEntry

use of org.infinispan.container.entries.RepeatableReadEntry in project infinispan by infinispan.

the class EntryFactoryImpl method createWrappedEntry.

protected MVCCEntry<?, ?> createWrappedEntry(Object key, CacheEntry<?, ?> cacheEntry) {
    Object value = null;
    Metadata metadata = null;
    PrivateMetadata internalMetadata = null;
    if (cacheEntry != null) {
        synchronized (cacheEntry) {
            value = cacheEntry.getValue();
            metadata = cacheEntry.getMetadata();
            internalMetadata = cacheEntry.getInternalMetadata();
        }
    }
    if (log.isTraceEnabled())
        log.tracef("Creating new entry for key %s", toStr(key));
    MVCCEntry<?, ?> mvccEntry;
    if (useRepeatableRead) {
        if (useVersioning) {
            if (internalMetadata == null) {
                internalMetadata = nonExistingPrivateMetadata;
            }
            mvccEntry = new VersionedRepeatableReadEntry(key, value, metadata);
        } else {
            mvccEntry = new RepeatableReadEntry(key, value, metadata);
        }
    } else {
        mvccEntry = new ReadCommittedEntry(key, value, metadata);
    }
    mvccEntry.setInternalMetadata(internalMetadata);
    if (cacheEntry != null) {
        mvccEntry.setCreated(cacheEntry.getCreated());
        mvccEntry.setLastUsed(cacheEntry.getLastUsed());
    }
    return mvccEntry;
}
Also used : ReadCommittedEntry(org.infinispan.container.entries.ReadCommittedEntry) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) VersionedRepeatableReadEntry(org.infinispan.container.entries.VersionedRepeatableReadEntry) Metadata(org.infinispan.metadata.Metadata) PrivateMetadata(org.infinispan.metadata.impl.PrivateMetadata) PrivateMetadata(org.infinispan.metadata.impl.PrivateMetadata) VersionedRepeatableReadEntry(org.infinispan.container.entries.VersionedRepeatableReadEntry)

Example 3 with RepeatableReadEntry

use of org.infinispan.container.entries.RepeatableReadEntry in project infinispan by infinispan.

the class ScatteredDistributionInterceptor method handleWriteManyOnPrimary.

private Object handleWriteManyOnPrimary(InvocationContext ctx, WriteCommand cmd, Object rv) {
    int numKeys = cmd.getAffectedKeys().size();
    InternalCacheValue[] values = new InternalCacheValue[numKeys];
    // keys are always iterated in order
    int i = 0;
    AggregateCompletionStage<Void> aggregateCompletionStage = CompletionStages.aggregateCompletionStage();
    for (Object key : cmd.getAffectedKeys()) {
        RepeatableReadEntry entry = (RepeatableReadEntry) ctx.lookupEntry(key);
        EntryVersion nextVersion = svm.incrementVersion(keyPartitioner.getSegment(key));
        entry.setMetadata(addVersion(entry.getMetadata(), nextVersion));
        if (cmd.loadType() == DONT_LOAD) {
            aggregateCompletionStage.dependsOn(commitSingleEntryIfNewer(entry, ctx, cmd));
        } else {
            aggregateCompletionStage.dependsOn(commitSingleEntryIfNoChange(entry, ctx, cmd));
        }
        values[i++] = new MetadataImmortalCacheValue(entry.getValue(), entry.getMetadata());
    }
    CompletionStage<Void> aggregatedStage = aggregateCompletionStage.freeze();
    Object returnValue;
    if (cmd.loadType() == DONT_LOAD) {
        // Disable ignoring return value in response
        cmd.setFlagsBitSet(cmd.getFlagsBitSet() & ~FlagBitSets.IGNORE_RETURN_VALUES);
        returnValue = values;
    } else {
        returnValue = new Object[] { values, ((List) rv).toArray() };
    }
    return asyncValue(aggregatedStage).thenApply(ctx, cmd, ((rCtx, rCommand, rv1) -> manyWriteResponse(rCtx, cmd, returnValue)));
}
Also used : MetadataImmortalCacheValue(org.infinispan.container.entries.metadata.MetadataImmortalCacheValue) WriteCommand(org.infinispan.commands.write.WriteCommand) Arrays(java.util.Arrays) GetCacheEntryCommand(org.infinispan.commands.read.GetCacheEntryCommand) CacheNotFoundResponse(org.infinispan.remoting.responses.CacheNotFoundResponse) LogFactory(org.infinispan.util.logging.LogFactory) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) ClusteredGetAllCommand(org.infinispan.commands.remote.ClusteredGetAllCommand) Map(java.util.Map) RemoveCommand(org.infinispan.commands.write.RemoveCommand) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) EmbeddedMetadata(org.infinispan.metadata.EmbeddedMetadata) ReadWriteManyEntriesCommand(org.infinispan.commands.functional.ReadWriteManyEntriesCommand) UnsuccessfulResponse(org.infinispan.remoting.responses.UnsuccessfulResponse) Set(java.util.Set) GroupManager(org.infinispan.distribution.group.impl.GroupManager) CacheTopology(org.infinispan.topology.CacheTopology) ResponseCollector(org.infinispan.remoting.transport.ResponseCollector) DONT_LOAD(org.infinispan.commands.VisitableCommand.LoadType.DONT_LOAD) CompletionStage(java.util.concurrent.CompletionStage) Stream(java.util.stream.Stream) SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue) AbstractVisitor(org.infinispan.commands.AbstractVisitor) ArrayCollector(org.infinispan.commons.util.ArrayCollector) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) CacheEntryRemoved(org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved) PersistenceManager(org.infinispan.persistence.manager.PersistenceManager) ComputeCommand(org.infinispan.commands.write.ComputeCommand) MetadataAwareCommand(org.infinispan.commands.MetadataAwareCommand) EvictionManager(org.infinispan.eviction.EvictionManager) ReadOnlyKeyCommand(org.infinispan.commands.functional.ReadOnlyKeyCommand) ArrayList(java.util.ArrayList) WriteOnlyManyEntriesCommand(org.infinispan.commands.functional.WriteOnlyManyEntriesCommand) Start(org.infinispan.factories.annotations.Start) MapResponseCollector(org.infinispan.remoting.transport.impl.MapResponseCollector) PassthroughSingleResponseCollector(org.infinispan.remoting.transport.impl.PassthroughSingleResponseCollector) SingleResponseCollector(org.infinispan.remoting.transport.impl.SingleResponseCollector) DataWriteCommand(org.infinispan.commands.write.DataWriteCommand) FunctionalNotifier(org.infinispan.functional.impl.FunctionalNotifier) ValueMatcher(org.infinispan.commands.write.ValueMatcher) ClearCommand(org.infinispan.commands.write.ClearCommand) Address(org.infinispan.remoting.transport.Address) ExceptionResponse(org.infinispan.remoting.responses.ExceptionResponse) CacheEntry(org.infinispan.container.entries.CacheEntry) NotifyHelper(org.infinispan.notifications.cachelistener.NotifyHelper) WriteOnlyKeyValueCommand(org.infinispan.commands.functional.WriteOnlyKeyValueCommand) ValidResponse(org.infinispan.remoting.responses.ValidResponse) CacheNotifier(org.infinispan.notifications.cachelistener.CacheNotifier) Inject(org.infinispan.factories.annotations.Inject) ReadWriteKeyCommand(org.infinispan.commands.functional.ReadWriteKeyCommand) ReadWriteManyCommand(org.infinispan.commands.functional.ReadWriteManyCommand) NullCacheEntry(org.infinispan.container.entries.NullCacheEntry) AggregateCompletionStage(org.infinispan.util.concurrent.AggregateCompletionStage) ReplaceCommand(org.infinispan.commands.write.ReplaceCommand) EntryVersion(org.infinispan.container.versioning.EntryVersion) UnsureResponse(org.infinispan.remoting.responses.UnsureResponse) MultiTargetCollector(org.infinispan.util.concurrent.CommandAckCollector.MultiTargetCollector) GetKeysInGroupCommand(org.infinispan.commands.remote.GetKeysInGroupCommand) ActivationManager(org.infinispan.eviction.impl.ActivationManager) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) InvocationContext(org.infinispan.context.InvocationContext) CompletableFutures(org.infinispan.util.concurrent.CompletableFutures) OutdatedTopologyException(org.infinispan.statetransfer.OutdatedTopologyException) RpcOptions(org.infinispan.remoting.rpc.RpcOptions) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ReadWriteKeyValueCommand(org.infinispan.commands.functional.ReadWriteKeyValueCommand) MetadataImmortalCacheEntry(org.infinispan.container.entries.metadata.MetadataImmortalCacheEntry) DataOperationOrderer(org.infinispan.util.concurrent.DataOperationOrderer) InequalVersionComparisonResult(org.infinispan.container.versioning.InequalVersionComparisonResult) InvocationSuccessFunction(org.infinispan.interceptors.InvocationSuccessFunction) List(java.util.List) SingletonMapResponseCollector(org.infinispan.remoting.transport.impl.SingletonMapResponseCollector) InvocationFinallyAction(org.infinispan.interceptors.InvocationFinallyAction) PutKeyValueCommand(org.infinispan.commands.write.PutKeyValueCommand) FlagAffectedCommand(org.infinispan.commands.FlagAffectedCommand) TopologyAffectedCommand(org.infinispan.commands.TopologyAffectedCommand) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Metadata(org.infinispan.metadata.Metadata) CompletionStages(org.infinispan.util.concurrent.CompletionStages) GetAllCommand(org.infinispan.commands.read.GetAllCommand) Function(java.util.function.Function) AllOwnersLostException(org.infinispan.statetransfer.AllOwnersLostException) FlagBitSets(org.infinispan.context.impl.FlagBitSets) KeyPartitioner(org.infinispan.distribution.ch.KeyPartitioner) ClusteredGetCommand(org.infinispan.commands.remote.ClusteredGetCommand) IracPutKeyValueCommand(org.infinispan.commands.write.IracPutKeyValueCommand) Log(org.infinispan.util.logging.Log) AbstractDataCommand(org.infinispan.commands.read.AbstractDataCommand) SegmentSpecificCommand(org.infinispan.commands.SegmentSpecificCommand) MetadataImmortalCacheValue(org.infinispan.container.entries.metadata.MetadataImmortalCacheValue) ResponseCollectors(org.infinispan.remoting.transport.ResponseCollectors) Response(org.infinispan.remoting.responses.Response) ClusteringInterceptor(org.infinispan.interceptors.impl.ClusteringInterceptor) GetKeyValueCommand(org.infinispan.commands.read.GetKeyValueCommand) CacheException(org.infinispan.commons.CacheException) Iterator(java.util.Iterator) EvictCommand(org.infinispan.commands.write.EvictCommand) WriteOnlyManyCommand(org.infinispan.commands.functional.WriteOnlyManyCommand) PutMapCommand(org.infinispan.commands.write.PutMapCommand) ReadOnlyManyCommand(org.infinispan.commands.functional.ReadOnlyManyCommand) ComputeIfAbsentCommand(org.infinispan.commands.write.ComputeIfAbsentCommand) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) Configuration(org.infinispan.configuration.cache.Configuration) DistributionInfo(org.infinispan.distribution.DistributionInfo) Operation(org.infinispan.util.concurrent.DataOperationOrderer.Operation) WriteOnlyKeyCommand(org.infinispan.commands.functional.WriteOnlyKeyCommand) VisitableCommand(org.infinispan.commands.VisitableCommand) DeliverOrder(org.infinispan.remoting.inboundhandler.DeliverOrder) Collections(java.util.Collections) TimeService(org.infinispan.commons.time.TimeService) ScatteredVersionManager(org.infinispan.scattered.ScatteredVersionManager) EntryVersion(org.infinispan.container.versioning.EntryVersion) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue)

Example 4 with RepeatableReadEntry

use of org.infinispan.container.entries.RepeatableReadEntry in project infinispan by infinispan.

the class ScatteredDistributionInterceptor method handleWriteCommand.

private Object handleWriteCommand(InvocationContext ctx, DataWriteCommand command) throws Throwable {
    RepeatableReadEntry cacheEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
    EntryVersion seenVersion = getVersionOrNull(cacheEntry);
    LocalizedCacheTopology cacheTopology = checkTopology(command);
    DistributionInfo info = cacheTopology.getSegmentDistribution(command.getSegment());
    if (info.primary() == null) {
        throw OutdatedTopologyException.RETRY_NEXT_TOPOLOGY;
    }
    if (isLocalModeForced(command)) {
        RepeatableReadEntry contextEntry = cacheEntry;
        if (cacheEntry == null) {
            entryFactory.wrapExternalEntry(ctx, command.getKey(), null, false, true);
            contextEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
        }
        EntryVersion nextVersion = null;
        if (command.hasAnyFlag(FlagBitSets.PUT_FOR_STATE_TRANSFER)) {
        // we don't increment versions with state transfer
        } else if (info.isPrimary()) {
            if (!cacheTopology.isConnected() && command instanceof MetadataAwareCommand) {
                // Preload does not use functional commands which are not metadata-aware
                Metadata metadata = ((MetadataAwareCommand) command).getMetadata();
                svm.updatePreloadedEntryVersion(metadata.version());
            } else {
                // let's allow local-mode writes on primary owner, preserving versions
                nextVersion = svm.incrementVersion(info.segmentId());
            }
        }
        return commitSingleEntryOnReturn(ctx, command, contextEntry, nextVersion);
    }
    if (ctx.isOriginLocal()) {
        if (info.isPrimary()) {
            Object seenValue = cacheEntry.getValue();
            return invokeNextThenApply(ctx, command, (rCtx, rCommand, rv) -> handleWriteOnOriginPrimary(rCtx, rCommand, rv, cacheEntry, seenValue, seenVersion, cacheTopology, info));
        } else {
            // not primary owner
            CompletionStage<ValidResponse> rpcFuture = singleWriteOnRemotePrimary(info.primary(), command);
            return asyncValue(rpcFuture).thenApply(ctx, command, handleWritePrimaryResponse);
        }
    } else {
        // remote origin
        if (info.isPrimary()) {
            // TODO [ISPN-3918]: the previous value is unreliable as this could be second invocation
            return invokeNextThenApply(ctx, command, (rCtx, cmd, rv) -> {
                if (!cmd.isSuccessful()) {
                    if (log.isTraceEnabled())
                        log.tracef("Skipping the replication of the command as it did not succeed on primary owner (%s).", cmd);
                    return singleWriteResponse(rCtx, cmd, rv);
                }
                EntryVersion nextVersion = svm.incrementVersion(info.segmentId());
                Metadata metadata = addVersion(cacheEntry.getMetadata(), nextVersion);
                cacheEntry.setMetadata(metadata);
                CompletionStage<Void> stage;
                if (cmd.loadType() != DONT_LOAD) {
                    stage = commitSingleEntryIfNoChange(cacheEntry, rCtx, cmd);
                } else {
                    stage = commitSingleEntryIfNewer(cacheEntry, rCtx, cmd);
                }
                Object returnValue = cmd.acceptVisitor(ctx, new PrimaryResponseGenerator(cacheEntry, rv));
                return asyncValue(stage).thenApply(rCtx, cmd, (rCtx2, rCommand2, rv2) -> singleWriteResponse(rCtx, rCommand2, returnValue));
            });
        } else {
            // The origin is primary and we're merely backup saving the data
            assert cacheEntry == null || command.hasAnyFlag(FlagBitSets.SKIP_OWNERSHIP_CHECK);
            RepeatableReadEntry contextEntry;
            if (cacheEntry == null) {
                entryFactory.wrapExternalEntry(ctx, command.getKey(), null, false, true);
                contextEntry = (RepeatableReadEntry) ctx.lookupEntry(command.getKey());
            } else {
                contextEntry = cacheEntry;
            }
            return invokeNextThenApply(ctx, command, (rCtx, rCommand, rv) -> delayedNull(commitSingleEntryIfNewer(contextEntry, rCtx, rCommand)));
        }
    }
}
Also used : MetadataAwareCommand(org.infinispan.commands.MetadataAwareCommand) EntryVersion(org.infinispan.container.versioning.EntryVersion) RepeatableReadEntry(org.infinispan.container.entries.RepeatableReadEntry) ValidResponse(org.infinispan.remoting.responses.ValidResponse) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) EmbeddedMetadata(org.infinispan.metadata.EmbeddedMetadata) Metadata(org.infinispan.metadata.Metadata) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) DistributionInfo(org.infinispan.distribution.DistributionInfo)

Aggregations

RepeatableReadEntry (org.infinispan.container.entries.RepeatableReadEntry)4 DistributionInfo (org.infinispan.distribution.DistributionInfo)3 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)3 Metadata (org.infinispan.metadata.Metadata)3 ValidResponse (org.infinispan.remoting.responses.ValidResponse)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 MetadataAwareCommand (org.infinispan.commands.MetadataAwareCommand)2 RemoteMetadata (org.infinispan.container.entries.RemoteMetadata)2 EntryVersion (org.infinispan.container.versioning.EntryVersion)2 EmbeddedMetadata (org.infinispan.metadata.EmbeddedMetadata)2 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Set (java.util.Set)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 CompletionStage (java.util.concurrent.CompletionStage)1