Search in sources :

Example 1 with InboundTransferTask

use of org.infinispan.statetransfer.InboundTransferTask in project infinispan by infinispan.

the class ScatteredStateConsumerImpl method requestKeyTransfer.

private void requestKeyTransfer(IntSet segments) {
    boolean isTransferringKeys = false;
    synchronized (transferMapsLock) {
        List<Address> members = new ArrayList<>(cacheTopology.getActualMembers());
        // Reorder the member set to distibute load more evenly
        Collections.shuffle(members);
        for (Address source : members) {
            if (source.equals(rpcManager.getAddress())) {
                continue;
            }
            isTransferringKeys = true;
            InboundTransferTask inboundTransfer = new InboundTransferTask(segments, source, cacheTopology.getTopologyId(), rpcManager, commandsFactory, configuration.clustering().stateTransfer().timeout(), cacheName, true);
            addTransfer(inboundTransfer, segments);
            stateRequestExecutor.executeAsync(() -> {
                log.tracef("Requesting keys for segments %s from %s", inboundTransfer.getSegments(), inboundTransfer.getSource());
                return inboundTransfer.requestKeys().whenComplete((nil, e) -> onTaskCompletion(inboundTransfer));
            });
        }
    }
    if (!isTransferringKeys) {
        log.trace("No keys in transfer, finishing segments " + segments);
        for (int segment : segments) {
            svm.notifyKeyTransferFinished(segment, false, false);
        }
        notifyEndOfStateTransferIfNeeded();
    }
}
Also used : Address(org.infinispan.remoting.transport.Address) ArrayList(java.util.ArrayList) InboundTransferTask(org.infinispan.statetransfer.InboundTransferTask)

Example 2 with InboundTransferTask

use of org.infinispan.statetransfer.InboundTransferTask 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 3 with InboundTransferTask

use of org.infinispan.statetransfer.InboundTransferTask in project infinispan by infinispan.

the class StateReceiverTest method initTransferTaskMock.

private void initTransferTaskMock(CompletableFuture<Void> completableFuture) {
    InboundTransferTask task = mock(InboundTransferTask.class);
    when(task.requestSegments()).thenReturn(completableFuture);
    doReturn(task).when(stateReceiver).createTransferTask(any(Integer.class), any(Address.class), any(CacheTopology.class), any(Long.class));
}
Also used : TestAddress(org.infinispan.distribution.TestAddress) Address(org.infinispan.remoting.transport.Address) CacheTopology(org.infinispan.topology.CacheTopology) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) InboundTransferTask(org.infinispan.statetransfer.InboundTransferTask)

Example 4 with InboundTransferTask

use of org.infinispan.statetransfer.InboundTransferTask in project infinispan by infinispan.

the class StateReceiverTest method testRequestCanBeCancelledDuringTransfer.

@Test(expectedExceptions = CancellationException.class)
public void testRequestCanBeCancelledDuringTransfer() throws Exception {
    // Init transfer that blocks and call stop() so the future should complete with CancellationException
    InboundTransferTask task = mock(InboundTransferTask.class);
    when(task.requestSegments()).thenAnswer(invocationOnMock -> {
        TestingUtil.sleepThread(1000);
        return CompletableFuture.completedFuture(new HashMap<>());
    });
    doReturn(task).when(stateReceiver).createTransferTask(any(Integer.class), any(Address.class), any(CacheTopology.class), any(Long.class));
    CompletableFuture<List<Map<Address, CacheEntry<Object, Object>>>> future = stateReceiver.getAllReplicasForSegment(0, localizedCacheTopology, 10000);
    future.whenComplete((result, throwable) -> {
        assertNull(result);
        assertNotNull(throwable);
        assertTrue(throwable instanceof CancellationException);
    });
    stateReceiver.stop();
    future.get();
}
Also used : TestAddress(org.infinispan.distribution.TestAddress) Address(org.infinispan.remoting.transport.Address) CacheTopology(org.infinispan.topology.CacheTopology) LocalizedCacheTopology(org.infinispan.distribution.LocalizedCacheTopology) CancellationException(java.util.concurrent.CancellationException) List(java.util.List) ArrayList(java.util.ArrayList) InboundTransferTask(org.infinispan.statetransfer.InboundTransferTask) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) ImmortalCacheEntry(org.infinispan.container.entries.ImmortalCacheEntry) CacheEntry(org.infinispan.container.entries.CacheEntry) Test(org.testng.annotations.Test) AbstractInfinispanTest(org.infinispan.test.AbstractInfinispanTest)

Aggregations

Address (org.infinispan.remoting.transport.Address)4 InboundTransferTask (org.infinispan.statetransfer.InboundTransferTask)4 ArrayList (java.util.ArrayList)3 CacheTopology (org.infinispan.topology.CacheTopology)3 List (java.util.List)2 InternalCacheEntry (org.infinispan.container.entries.InternalCacheEntry)2 LocalizedCacheTopology (org.infinispan.distribution.LocalizedCacheTopology)2 TestAddress (org.infinispan.distribution.TestAddress)2 Flowable (io.reactivex.rxjava3.core.Flowable)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 PrimitiveIterator (java.util.PrimitiveIterator)1 ArrayBlockingQueue (java.util.concurrent.ArrayBlockingQueue)1 BlockingQueue (java.util.concurrent.BlockingQueue)1 CancellationException (java.util.concurrent.CancellationException)1 CompletionStage (java.util.concurrent.CompletionStage)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1