Search in sources :

Example 1 with RemoteMetadata

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

the class ScatteredStateConsumerImpl method onTaskCompletion.

@Override
protected void onTaskCompletion(InboundTransferTask inboundTransfer) {
    // a bit of overkill since we start these tasks for single segment
    IntSet completedSegments = IntSets.immutableEmptySet();
    if (log.isTraceEnabled())
        log.tracef("Inbound transfer finished %s: %s", inboundTransfer, inboundTransfer.isCompletedSuccessfully() ? "successfully" : "unsuccessfuly");
    synchronized (transferMapsLock) {
        // transferMapsLock is held when all the tasks are added so we see that all of them are done
        for (PrimitiveIterator.OfInt iter = inboundTransfer.getSegments().iterator(); iter.hasNext(); ) {
            int segment = iter.nextInt();
            List<InboundTransferTask> transfers = transfersBySegment.get(segment);
            if (transfers == null) {
                // It is possible that two task complete concurrently, one of them checks is all tasks
                // for given segments have been completed successfully and (finding out that it's true)
                // removes the transfer for given segment. The second task arrives and finds out that
                // its record int transfersBySegment is gone, but that's OK, as the segment has been handled.
                log.tracef("Transfers for segment %d have not been found.", segment);
            } else {
                // We are removing here rather than in removeTransfer, because we need to know if we're the last
                // finishing task.
                transfers.remove(inboundTransfer);
                if (transfers.isEmpty()) {
                    transfersBySegment.remove(segment);
                    if (log.isTraceEnabled()) {
                        log.tracef("All transfer tasks for segment %d have completed.", segment);
                    }
                    svm.notifyKeyTransferFinished(segment, inboundTransfer.isCompletedSuccessfully(), inboundTransfer.isCancelled());
                    switch(completedSegments.size()) {
                        case 0:
                            completedSegments = IntSets.immutableSet(segment);
                            break;
                        case 1:
                            completedSegments = IntSets.mutableCopyFrom(completedSegments);
                        // Intentional falls through
                        default:
                            completedSegments.set(segment);
                    }
                }
            }
        }
    }
    if (completedSegments.isEmpty()) {
        log.tracef("Not requesting any values yet because no segments have been completed.");
    } else if (inboundTransfer.isCompletedSuccessfully()) {
        log.tracef("Requesting values from segments %s, for in-memory keys", completedSegments);
        dataContainer.forEach(completedSegments, ice -> {
            // TODO: could the version be null in here?
            if (ice.getMetadata() instanceof RemoteMetadata) {
                Address backup = ((RemoteMetadata) ice.getMetadata()).getAddress();
                retrieveEntry(ice.getKey(), backup);
                for (Address member : cacheTopology.getActualMembers()) {
                    if (!member.equals(backup)) {
                        invalidate(ice.getKey(), ice.getMetadata().version(), member);
                    }
                }
            } else {
                backupEntry(ice);
                for (Address member : nonBackupAddresses) {
                    invalidate(ice.getKey(), ice.getMetadata().version(), member);
                }
            }
        });
        // With passivation, some key could be activated here and we could miss it,
        // but then it should be broadcast-loaded in PrefetchInvalidationInterceptor
        Publisher<MarshallableEntry<Object, Object>> persistencePublisher = persistenceManager.publishEntries(completedSegments, k -> dataContainer.peek(k) == null, true, true, Configurations::isStateTransferStore);
        try {
            blockingSubscribe(Flowable.fromPublisher(persistencePublisher).doOnNext(me -> {
                try {
                    Metadata metadata = me.getMetadata();
                    if (metadata instanceof RemoteMetadata) {
                        Address backup = ((RemoteMetadata) metadata).getAddress();
                        retrieveEntry(me.getKey(), backup);
                        for (Address member : cacheTopology.getActualMembers()) {
                            if (!member.equals(backup)) {
                                invalidate(me.getKey(), metadata.version(), member);
                            }
                        }
                    } else {
                        backupEntry(entryFactory.create(me.getKey(), me.getValue(), me.getMetadata()));
                        for (Address member : nonBackupAddresses) {
                            invalidate(me.getKey(), metadata.version(), member);
                        }
                    }
                } catch (CacheException e) {
                    log.failedLoadingValueFromCacheStore(me.getKey(), e);
                }
            }));
        } catch (CacheException e) {
            PERSISTENCE.failedLoadingKeysFromCacheStore(e);
        }
    }
    boolean lastTransfer = false;
    synchronized (transferMapsLock) {
        inboundSegments.removeAll(completedSegments);
        log.tracef("Unfinished inbound segments: " + inboundSegments);
        if (inboundSegments.isEmpty()) {
            lastTransfer = true;
        }
    }
    if (lastTransfer) {
        for (Map.Entry<Address, BlockingQueue<Object>> pair : retrievedEntries.entrySet()) {
            BlockingQueue<Object> queue = pair.getValue();
            List<Object> keys = new ArrayList<>(queue.size());
            queue.drainTo(keys);
            if (!keys.isEmpty()) {
                getValuesAndApply(pair.getKey(), keys);
            }
        }
        List<InternalCacheEntry<?, ?>> entries = new ArrayList<>(backupQueue.size());
        backupQueue.drainTo(entries);
        if (!entries.isEmpty()) {
            backupEntries(entries);
        }
        for (Map.Entry<Address, BlockingQueue<KeyAndVersion>> pair : invalidations.entrySet()) {
            BlockingQueue<KeyAndVersion> queue = pair.getValue();
            List<KeyAndVersion> list = new ArrayList<>(queue.size());
            queue.drainTo(list);
            if (!list.isEmpty()) {
                invalidate(list, pair.getKey());
            }
        }
    }
    // we must not remove the transfer before the requests for values are sent
    // as we could notify the end of rebalance too soon
    removeTransfer(inboundTransfer);
    if (lastTransfer) {
        if (log.isTraceEnabled())
            log.tracef("Inbound transfer removed, chunk counter is %s", chunkCounter.get());
        if (chunkCounter.get() == 0) {
            // No values to transfer after all the keys were received, we can end state transfer immediately
            notifyEndOfStateTransferIfNeeded();
        }
    }
}
Also used : IntSets(org.infinispan.commons.util.IntSets) LogFactory(org.infinispan.util.logging.LogFactory) EntryVersion(org.infinispan.container.versioning.EntryVersion) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) ClusteredGetAllCommand(org.infinispan.commands.remote.ClusteredGetAllCommand) CONTAINER(org.infinispan.util.logging.Log.CONTAINER) CompletableFutures(org.infinispan.util.concurrent.CompletableFutures) Map(java.util.Map) PERSISTENCE(org.infinispan.util.logging.Log.PERSISTENCE) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) BlockingQueue(java.util.concurrent.BlockingQueue) CacheTopology(org.infinispan.topology.CacheTopology) ComponentStatus(org.infinispan.lifecycle.ComponentStatus) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) IntSet(org.infinispan.commons.util.IntSet) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) PutKeyValueCommand(org.infinispan.commands.write.PutKeyValueCommand) InboundTransferTask(org.infinispan.statetransfer.InboundTransferTask) GuardedBy(net.jcip.annotations.GuardedBy) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue) InvalidateVersionsCommand(org.infinispan.commands.write.InvalidateVersionsCommand) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) HashMap(java.util.HashMap) Metadata(org.infinispan.metadata.Metadata) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) MapResponseCollector(org.infinispan.remoting.transport.impl.MapResponseCollector) FlagBitSets(org.infinispan.context.impl.FlagBitSets) InternalMetadataImpl(org.infinispan.metadata.impl.InternalMetadataImpl) Configurations(org.infinispan.configuration.cache.Configurations) SingleResponseCollector(org.infinispan.remoting.transport.impl.SingleResponseCollector) Log(org.infinispan.util.logging.Log) MarshallableEntry(org.infinispan.persistence.spi.MarshallableEntry) Address(org.infinispan.remoting.transport.Address) Response(org.infinispan.remoting.responses.Response) InternalEntryFactory(org.infinispan.container.impl.InternalEntryFactory) CacheException(org.infinispan.commons.CacheException) Flowable(io.reactivex.rxjava3.core.Flowable) Iterator(java.util.Iterator) Publisher(org.reactivestreams.Publisher) PutMapCommand(org.infinispan.commands.write.PutMapCommand) SimpleClusteredVersion(org.infinispan.container.versioning.SimpleClusteredVersion) Inject(org.infinispan.factories.annotations.Inject) StateConsumerImpl(org.infinispan.statetransfer.StateConsumerImpl) PrimitiveIterator(java.util.PrimitiveIterator) AtomicLong(java.util.concurrent.atomic.AtomicLong) CacheRpcCommand(org.infinispan.commands.remote.CacheRpcCommand) Collections(java.util.Collections) ScatteredVersionManager(org.infinispan.scattered.ScatteredVersionManager) SuspectException(org.infinispan.remoting.transport.jgroups.SuspectException) Address(org.infinispan.remoting.transport.Address) CacheException(org.infinispan.commons.CacheException) IntSet(org.infinispan.commons.util.IntSet) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) Metadata(org.infinispan.metadata.Metadata) ArrayList(java.util.ArrayList) InboundTransferTask(org.infinispan.statetransfer.InboundTransferTask) BlockingQueue(java.util.concurrent.BlockingQueue) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) PrimitiveIterator(java.util.PrimitiveIterator) Publisher(org.reactivestreams.Publisher) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap)

Example 2 with RemoteMetadata

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

the class ScatteredDistributionInterceptor method updateEntryIfNoChange.

private boolean updateEntryIfNoChange(RepeatableReadEntry entry) {
    // We cannot delegate the dataContainer.compute() to entry.commit() as we need to reliably
    // retrieve previous value and metadata, but the entry API does not provide these.
    dataContainer.compute(entry.getKey(), (key, oldEntry, factory) -> {
        // newMetadata is null in case of local-mode write on non-primary owners
        Metadata newMetadata = entry.getMetadata();
        if (oldEntry == null) {
            if (entry.getOldValue() != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Non-null value in context, not committing");
                }
                throw new ConcurrentChangeException();
            }
            if (entry.getValue() == null && newMetadata == null) {
                if (log.isTraceEnabled()) {
                    log.trace("No previous record and this is a removal, not committing anything.");
                }
                return null;
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Committing new entry " + entry);
                }
                entry.setCommitted();
                return factory.create(entry);
            }
        }
        Metadata oldMetadata = oldEntry.getMetadata();
        EntryVersion oldVersion = oldMetadata == null ? null : oldMetadata.version();
        Metadata seenMetadata = entry.getOldMetadata();
        EntryVersion seenVersion = seenMetadata == null ? null : seenMetadata.version();
        if (oldVersion == null) {
            if (seenVersion != null) {
                if (log.isTraceEnabled()) {
                    log.tracef("Current version is null but seen version is %s, throwing", seenVersion);
                }
                throw new ConcurrentChangeException();
            }
        } else if (seenVersion == null) {
            if (oldEntry.canExpire() && oldEntry.isExpired(timeService.wallClockTime())) {
                if (log.isTraceEnabled()) {
                    log.trace("Current entry is expired and therefore we haven't seen it");
                }
            } else {
                if (log.isTraceEnabled()) {
                    log.tracef("Current version is %s but seen version is null, throwing", oldVersion);
                }
                throw new ConcurrentChangeException();
            }
        } else if (seenVersion.compareTo(oldVersion) != InequalVersionComparisonResult.EQUAL) {
            if (log.isTraceEnabled()) {
                log.tracef("Current version is %s but seen version is %s, throwing", oldVersion, seenVersion);
            }
            throw new ConcurrentChangeException();
        }
        InequalVersionComparisonResult comparisonResult;
        if (oldVersion == null || newMetadata == null || newMetadata.version() == null || (comparisonResult = oldMetadata.version().compareTo(newMetadata.version())) == InequalVersionComparisonResult.BEFORE || (oldMetadata instanceof RemoteMetadata && comparisonResult == InequalVersionComparisonResult.EQUAL)) {
            if (log.isTraceEnabled()) {
                log.tracef("Committing entry %s, replaced %s", entry, oldEntry);
            }
            entry.setCommitted();
            if (entry.getValue() != null || newMetadata != null) {
                return factory.create(entry);
            } else {
                return null;
            }
        } else {
            if (log.isTraceEnabled()) {
                log.tracef("Not committing %s, current entry is %s", entry, oldEntry);
            }
            return oldEntry;
        }
    });
    return entry.isCommitted();
}
Also used : RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) EntryVersion(org.infinispan.container.versioning.EntryVersion) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) EmbeddedMetadata(org.infinispan.metadata.EmbeddedMetadata) Metadata(org.infinispan.metadata.Metadata) InequalVersionComparisonResult(org.infinispan.container.versioning.InequalVersionComparisonResult)

Example 3 with RemoteMetadata

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

the class ScatteredDistributionInterceptor method updateEntryIfNewer.

private boolean updateEntryIfNewer(RepeatableReadEntry entry) {
    // We cannot delegate the dataContainer.compute() to entry.commit() as we need to reliably
    // retrieve previous value and metadata, but the entry API does not provide these.
    dataContainer.compute(entry.getKey(), (key, oldEntry, factory) -> {
        // newMetadata is null in case of local-mode write
        Metadata newMetadata = entry.getMetadata();
        if (oldEntry == null) {
            if (entry.getValue() == null && newMetadata == null) {
                if (log.isTraceEnabled()) {
                    log.trace("No previous record and this is a removal, not committing anything.");
                }
                return null;
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Committing new entry " + entry);
                }
                entry.setCommitted();
                return factory.create(entry);
            }
        }
        Metadata oldMetadata = oldEntry.getMetadata();
        InequalVersionComparisonResult comparisonResult;
        if (oldMetadata == null || oldMetadata.version() == null || newMetadata == null || newMetadata.version() == null || (comparisonResult = oldMetadata.version().compareTo(newMetadata.version())) == InequalVersionComparisonResult.BEFORE || (oldMetadata instanceof RemoteMetadata && comparisonResult == InequalVersionComparisonResult.EQUAL)) {
            if (log.isTraceEnabled()) {
                log.tracef("Committing entry %s, replaced %s", entry, oldEntry);
            }
            entry.setCommitted();
            if (entry.getValue() != null || newMetadata != null) {
                return factory.create(entry);
            } else {
                return null;
            }
        } else {
            if (log.isTraceEnabled()) {
                log.tracef("Not committing %s, current entry is %s", entry, oldEntry);
            }
            return oldEntry;
        }
    });
    return entry.isCommitted();
}
Also used : RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) EmbeddedMetadata(org.infinispan.metadata.EmbeddedMetadata) Metadata(org.infinispan.metadata.Metadata) InequalVersionComparisonResult(org.infinispan.container.versioning.InequalVersionComparisonResult)

Example 4 with RemoteMetadata

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

the class AbstractAnchoredKeysTest method assertLocation.

protected void assertLocation(Object key, Address expectedAddress, Object expectedValue) {
    for (Cache<Object, Object> cache : caches()) {
        Address address = cache.getAdvancedCache().getRpcManager().getAddress();
        Object storedKey = cache.getAdvancedCache().getKeyDataConversion().toStorage(key);
        InternalCacheEntry<Object, Object> entry = cache.getAdvancedCache().getDataContainer().peek(storedKey);
        if (address.equals(expectedAddress)) {
            Object storedValue = entry != null ? entry.getValue() : null;
            Object value = cache.getAdvancedCache().getValueDataConversion().fromStorage(storedValue);
            assertEquals("Wrong value for " + key + " on " + address, expectedValue, value);
            Metadata metadata = entry != null ? entry.getMetadata() : null;
            assertFalse("No location expected for " + key + " on " + address + ", got " + metadata, metadata instanceof RemoteMetadata);
        } else {
            assertNull("No value expected for key " + key + " on " + address, entry.getValue());
            Address location = ((RemoteMetadata) entry.getMetadata()).getAddress();
            assertEquals("Wrong location for " + key + " on " + address, expectedAddress, location);
        }
    }
}
Also used : RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) Address(org.infinispan.remoting.transport.Address) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) Metadata(org.infinispan.metadata.Metadata)

Example 5 with RemoteMetadata

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

the class PrefetchInterceptor method retrieveRemoteValues.

// TODO: this is not completely aligned with single-entry prefetch
private <C extends VisitableCommand & TopologyAffectedCommand> InvocationStage retrieveRemoteValues(InvocationContext ctx, C originCommand, List<?> keys) {
    if (log.isTraceEnabled()) {
        log.tracef("Prefetching entries for keys %s using broadcast", keys);
    }
    ClusteredGetAllCommand<?, ?> command = commandsFactory.buildClusteredGetAllCommand(keys, FlagBitSets.SKIP_OWNERSHIP_CHECK, null);
    command.setTopologyId(originCommand.getTopologyId());
    CompletionStage<Map<Address, Response>> rpcFuture = rpcManager.invokeCommandOnAll(command, MapResponseCollector.ignoreLeavers(), rpcManager.getSyncRpcOptions());
    return asyncValue(rpcFuture).thenApplyMakeStage(ctx, originCommand, (rCtx, topologyAffectedCommand, rv) -> {
        Map<Address, Response> responseMap = (Map<Address, Response>) rv;
        InternalCacheValue<V>[] maxValues = new InternalCacheValue[keys.size()];
        for (Response response : responseMap.values()) {
            if (!response.isSuccessful()) {
                throw OutdatedTopologyException.RETRY_NEXT_TOPOLOGY;
            }
            InternalCacheValue<V>[] values = ((SuccessfulResponse<InternalCacheValue<V>[]>) response).getResponseValue();
            int i = 0;
            for (InternalCacheValue<V> icv : values) {
                if (icv != null) {
                    Metadata metadata = icv.getMetadata();
                    if (metadata instanceof RemoteMetadata) {
                        // not sure if this can happen, but let's be on the safe side
                        throw OutdatedTopologyException.RETRY_NEXT_TOPOLOGY;
                    }
                    if (maxValues[i] == null) {
                        maxValues[i] = icv;
                    } else if (metadata != null && metadata.version() != null) {
                        Metadata maxMetadata;
                        if ((maxMetadata = maxValues[i].getMetadata()) == null || maxMetadata.version() == null || maxMetadata.version().compareTo(metadata.version()) == InequalVersionComparisonResult.BEFORE) {
                            maxValues[i] = icv;
                        }
                    }
                }
                ++i;
            }
        }
        Map<Object, InternalCacheValue<V>> map = new HashMap<>(keys.size());
        for (int i = 0; i < maxValues.length; ++i) {
            if (maxValues[i] != null) {
                map.put(keys.get(i), maxValues[i]);
            }
        }
        if (log.isTraceEnabled()) {
            log.tracef("Prefetched values are %s", map);
        }
        if (map.isEmpty()) {
            return CompletableFutures.completedNull();
        }
        // from the main command correct.
        for (Map.Entry<Object, InternalCacheValue<V>> entry : map.entrySet()) {
            entryFactory.wrapExternalEntry(rCtx, entry.getKey(), entry.getValue().toInternalCacheEntry(entry.getKey()), true, true);
        }
        PutMapCommand putMapCommand = commandsFactory.buildPutMapCommand(map, null, STATE_TRANSFER_FLAGS);
        putMapCommand.setTopologyId(topologyAffectedCommand.getTopologyId());
        return invokeNext(rCtx, putMapCommand);
    });
}
Also used : SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) Address(org.infinispan.remoting.transport.Address) HashMap(java.util.HashMap) RemoteMetadata(org.infinispan.container.entries.RemoteMetadata) Metadata(org.infinispan.metadata.Metadata) InternalCacheValue(org.infinispan.container.entries.InternalCacheValue) SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) Response(org.infinispan.remoting.responses.Response) PutMapCommand(org.infinispan.commands.write.PutMapCommand) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

RemoteMetadata (org.infinispan.container.entries.RemoteMetadata)11 Metadata (org.infinispan.metadata.Metadata)9 Address (org.infinispan.remoting.transport.Address)6 HashMap (java.util.HashMap)4 Map (java.util.Map)4 InternalCacheValue (org.infinispan.container.entries.InternalCacheValue)3 EntryVersion (org.infinispan.container.versioning.EntryVersion)3 Response (org.infinispan.remoting.responses.Response)3 SuccessfulResponse (org.infinispan.remoting.responses.SuccessfulResponse)3 Flowable (io.reactivex.rxjava3.core.Flowable)2 Collection (java.util.Collection)2 Iterator (java.util.Iterator)2 List (java.util.List)2 CompletionStage (java.util.concurrent.CompletionStage)2 PutKeyValueCommand (org.infinispan.commands.write.PutKeyValueCommand)2 PutMapCommand (org.infinispan.commands.write.PutMapCommand)2 IntSet (org.infinispan.commons.util.IntSet)2 IntSets (org.infinispan.commons.util.IntSets)2 Configurations (org.infinispan.configuration.cache.Configurations)2 InternalCacheEntry (org.infinispan.container.entries.InternalCacheEntry)2