Search in sources :

Example 1 with TransactionTable

use of org.infinispan.transaction.impl.TransactionTable in project infinispan by infinispan.

the class StateConsumerImpl method onTopologyUpdate.

@Override
public CompletionStage<CompletionStage<Void>> onTopologyUpdate(CacheTopology cacheTopology, boolean isRebalance) {
    final ConsistentHash newWriteCh = cacheTopology.getWriteConsistentHash();
    final CacheTopology previousCacheTopology = this.cacheTopology;
    final ConsistentHash previousWriteCh = previousCacheTopology != null ? previousCacheTopology.getWriteConsistentHash() : null;
    IntSet newWriteSegments = getOwnedSegments(newWriteCh);
    Address address = rpcManager.getAddress();
    final boolean isMember = cacheTopology.getMembers().contains(address);
    final boolean wasMember = previousWriteCh != null && previousWriteCh.getMembers().contains(address);
    if (log.isTraceEnabled())
        log.tracef("Received new topology for cache %s, isRebalance = %b, isMember = %b, topology = %s", cacheName, isRebalance, isMember, cacheTopology);
    if (!ownsData && isMember) {
        ownsData = true;
    } else if (ownsData && !isMember) {
        // This can happen after a merge, if the local node was in a minority partition.
        ownsData = false;
    }
    // If a member leaves/crashes immediately after a rebalance was started, the new CH_UPDATE
    // command may be executed before the REBALANCE_START command, so it has to start the rebalance.
    boolean addedPendingCH = cacheTopology.getPendingCH() != null && wasMember && previousCacheTopology.getPendingCH() == null;
    boolean startConflictResolution = !isRebalance && cacheTopology.getPhase() == CacheTopology.Phase.CONFLICT_RESOLUTION;
    boolean startStateTransfer = isRebalance || (addedPendingCH && !startConflictResolution);
    if (startStateTransfer && !isRebalance) {
        if (log.isTraceEnabled())
            log.tracef("Forcing startRebalance = true");
    }
    CompletionStage<Void> stage = CompletableFutures.completedNull();
    if (startStateTransfer) {
        // Only update the rebalance topology id when starting the rebalance, as we're going to ignore any state
        // response with a smaller topology id
        stateTransferTopologyId.compareAndSet(NO_STATE_TRANSFER_IN_PROGRESS, cacheTopology.getTopologyId());
        conflictManager.cancelVersionRequests();
        if (cacheNotifier.hasListener(DataRehashed.class)) {
            stage = cacheNotifier.notifyDataRehashed(cacheTopology.getCurrentCH(), cacheTopology.getPendingCH(), cacheTopology.getUnionCH(), cacheTopology.getTopologyId(), true);
        }
    }
    stage = stage.thenCompose(ignored -> {
        if (startConflictResolution) {
            // This stops state being applied from a prior rebalance and also prevents tracking from being stopped
            stateTransferTopologyId.set(NO_STATE_TRANSFER_IN_PROGRESS);
        }
        // Make sure we don't send a REBALANCE_CONFIRM command before we've added all the transfer tasks
        // even if some of the tasks are removed and re-added
        waitingForState.set(false);
        stateTransferFuture = new CompletableFuture<>();
        beforeTopologyInstalled(cacheTopology.getTopologyId(), previousWriteCh, newWriteCh);
        if (!configuration.clustering().cacheMode().isInvalidation()) {
            // Owned segments
            dataContainer.addSegments(newWriteSegments);
            // TODO Should we throw an exception if addSegments() returns false?
            return ignoreValue(persistenceManager.addSegments(newWriteSegments));
        }
        return CompletableFutures.completedNull();
    });
    stage = stage.thenCompose(ignored -> {
        // Tracking is stopped once the state transfer completes (i.e. all the entries have been inserted)
        if (startStateTransfer || startConflictResolution) {
            if (commitManager.isTracking(PUT_FOR_STATE_TRANSFER)) {
                log.debug("Starting state transfer but key tracking is already enabled");
            } else {
                if (log.isTraceEnabled())
                    log.tracef("Start keeping track of keys for state transfer");
                commitManager.startTrack(PUT_FOR_STATE_TRANSFER);
            }
        }
        // Ensures writes to the data container use the right consistent hash
        // Writers block on the state transfer shared lock, so we keep the exclusive lock as short as possible
        stateTransferLock.acquireExclusiveTopologyLock();
        try {
            this.cacheTopology = cacheTopology;
            distributionManager.setCacheTopology(cacheTopology);
        } finally {
            stateTransferLock.releaseExclusiveTopologyLock();
        }
        stateTransferLock.notifyTopologyInstalled(cacheTopology.getTopologyId());
        inboundInvocationHandler.checkForReadyTasks();
        xSiteStateTransferManager.onTopologyUpdated(cacheTopology, isStateTransferInProgress());
        if (!wasMember && isMember) {
            return fetchClusterListeners(cacheTopology);
        }
        return CompletableFutures.completedNull();
    });
    stage = stage.thenCompose(ignored -> {
        // fetch transactions and data segments from other owners if this is enabled
        if (startConflictResolution || (!isTransactional && !isFetchEnabled)) {
            return CompletableFutures.completedNull();
        }
        IntSet addedSegments, removedSegments;
        if (previousWriteCh == null) {
            // If we have any segments assigned in the initial CH, it means we are the first member.
            // If we are not the first member, we can only add segments via rebalance.
            removedSegments = IntSets.immutableEmptySet();
            addedSegments = IntSets.immutableEmptySet();
            if (log.isTraceEnabled()) {
                log.tracef("On cache %s we have: added segments: %s", cacheName, addedSegments);
            }
        } else {
            IntSet previousSegments = getOwnedSegments(previousWriteCh);
            if (newWriteSegments.size() == numSegments) {
                // Optimization for replicated caches
                removedSegments = IntSets.immutableEmptySet();
            } else {
                removedSegments = IntSets.mutableCopyFrom(previousSegments);
                removedSegments.removeAll(newWriteSegments);
            }
            // This is a rebalance, we need to request the segments we own in the new CH.
            addedSegments = IntSets.mutableCopyFrom(newWriteSegments);
            addedSegments.removeAll(previousSegments);
            if (log.isTraceEnabled()) {
                log.tracef("On cache %s we have: new segments: %s; old segments: %s", cacheName, newWriteSegments, previousSegments);
                log.tracef("On cache %s we have: added segments: %s; removed segments: %s", cacheName, addedSegments, removedSegments);
            }
            // remove inbound transfers for segments we no longer own
            cancelTransfers(removedSegments);
            // Scattered cache gets added segments on the first CH_UPDATE, and we want to keep these
            if (!startStateTransfer && !addedSegments.isEmpty() && !configuration.clustering().cacheMode().isScattered()) {
                // If the last owner of a segment leaves the cluster, a new set of owners is assigned,
                // but the new owners should not try to retrieve the segment from each other.
                // If this happens during a rebalance, we might have already sent our rebalance
                // confirmation, so the coordinator won't wait for us to retrieve those segments anyway.
                log.debugf("Not requesting segments %s because the last owner left the cluster", addedSegments);
                addedSegments.clear();
            }
            // check if any of the existing transfers should be restarted from a different source because
            // the initial source is no longer a member
            restartBrokenTransfers(cacheTopology, addedSegments);
        }
        IntSet transactionOnlySegments = computeTransactionOnlySegments(cacheTopology, address);
        return handleSegments(startStateTransfer, addedSegments, removedSegments, transactionOnlySegments);
    });
    stage = stage.thenCompose(ignored -> {
        int stateTransferTopologyId = this.stateTransferTopologyId.get();
        if (log.isTraceEnabled())
            log.tracef("Topology update processed, stateTransferTopologyId = %d, startRebalance = %s, pending CH = %s", (Object) stateTransferTopologyId, startStateTransfer, cacheTopology.getPendingCH());
        if (stateTransferTopologyId != NO_STATE_TRANSFER_IN_PROGRESS && !startStateTransfer && !cacheTopology.getPhase().isRebalance()) {
            // we have received a topology update without a pending CH, signalling the end of the rebalance
            boolean changed = this.stateTransferTopologyId.compareAndSet(stateTransferTopologyId, NO_STATE_TRANSFER_IN_PROGRESS);
            // but we only want to notify the @DataRehashed listeners once
            if (changed) {
                stopApplyingState(stateTransferTopologyId);
                if (cacheNotifier.hasListener(DataRehashed.class)) {
                    return cacheNotifier.notifyDataRehashed(previousCacheTopology.getCurrentCH(), previousCacheTopology.getPendingCH(), previousCacheTopology.getUnionCH(), cacheTopology.getTopologyId(), false);
                }
            }
        }
        return CompletableFutures.completedNull();
    });
    return handleAndCompose(stage, (ignored, throwable) -> {
        if (log.isTraceEnabled()) {
            log.tracef("Unlock State Transfer in Progress for topology ID %s", cacheTopology.getTopologyId());
        }
        stateTransferLock.notifyTransactionDataReceived(cacheTopology.getTopologyId());
        inboundInvocationHandler.checkForReadyTasks();
        // Only set the flag here, after all the transfers have been added to the transfersBySource map
        if (stateTransferTopologyId.get() != NO_STATE_TRANSFER_IN_PROGRESS && isMember) {
            waitingForState.set(true);
        }
        notifyEndOfStateTransferIfNeeded();
        // and after notifyTransactionDataReceived - otherwise the RollbackCommands would block.
        try {
            if (transactionTable != null) {
                transactionTable.cleanupLeaverTransactions(rpcManager.getTransport().getMembers());
            }
        } catch (Exception e) {
            // Do not fail state transfer when the cleanup fails. See ISPN-7437 for details.
            log.transactionCleanupError(e);
        }
        commandAckCollector.onMembersChange(newWriteCh.getMembers());
        // and STABLE does not have to be confirmed at all
        switch(cacheTopology.getPhase()) {
            case READ_ALL_WRITE_ALL:
            case READ_NEW_WRITE_ALL:
                stateTransferFuture.complete(null);
        }
        // and the other partition was available) or when L1 is enabled.
        if ((isMember || wasMember) && cacheTopology.getPhase() == CacheTopology.Phase.NO_REBALANCE) {
            int numSegments = newWriteCh.getNumSegments();
            IntSet removedSegments = IntSets.mutableEmptySet(numSegments);
            IntSet newSegments = getOwnedSegments(newWriteCh);
            for (int i = 0; i < numSegments; ++i) {
                if (!newSegments.contains(i)) {
                    removedSegments.set(i);
                }
            }
            return removeStaleData(removedSegments).thenApply(ignored1 -> {
                conflictManager.restartVersionRequests();
                // rethrow the original exception, if any
                CompletableFutures.rethrowExceptionIfPresent(throwable);
                return stateTransferFuture;
            });
        }
        CompletableFutures.rethrowExceptionIfPresent(throwable);
        return CompletableFuture.completedFuture(stateTransferFuture);
    });
}
Also used : ComponentName(org.infinispan.factories.annotations.ComponentName) CacheNotFoundResponse(org.infinispan.remoting.responses.CacheNotFoundResponse) LogFactory(org.infinispan.util.logging.LogFactory) Cache(org.infinispan.Cache) Scopes(org.infinispan.factories.scopes.Scopes) Map(java.util.Map) SKIP_SHARED_CACHE_STORE(org.infinispan.context.Flag.SKIP_SHARED_CACHE_STORE) Transaction(javax.transaction.Transaction) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) CACHE_MODE_LOCAL(org.infinispan.context.Flag.CACHE_MODE_LOCAL) Set(java.util.Set) CacheTopology(org.infinispan.topology.CacheTopology) IntSet(org.infinispan.commons.util.IntSet) CompletionStage(java.util.concurrent.CompletionStage) SuccessfulResponse(org.infinispan.remoting.responses.SuccessfulResponse) AsyncInterceptorChain(org.infinispan.interceptors.AsyncInterceptorChain) FakeJTATransaction(org.infinispan.transaction.impl.FakeJTATransaction) CacheTransaction(org.infinispan.transaction.xa.CacheTransaction) TriangleOrderManager(org.infinispan.distribution.TriangleOrderManager) InternalCacheEntry(org.infinispan.container.entries.InternalCacheEntry) PersistenceManager(org.infinispan.persistence.manager.PersistenceManager) CommandAckCollector(org.infinispan.util.concurrent.CommandAckCollector) EnumUtil(org.infinispan.commons.util.EnumUtil) ArrayList(java.util.ArrayList) Start(org.infinispan.factories.annotations.Start) PassthroughSingleResponseCollector(org.infinispan.remoting.transport.impl.PassthroughSingleResponseCollector) PRIVATE(org.infinispan.persistence.manager.PersistenceManager.AccessMode.PRIVATE) Configurations(org.infinispan.configuration.cache.Configurations) SingleResponseCollector(org.infinispan.remoting.transport.impl.SingleResponseCollector) Address(org.infinispan.remoting.transport.Address) InvocationContextFactory(org.infinispan.context.InvocationContextFactory) SKIP_OWNERSHIP_CHECK(org.infinispan.context.Flag.SKIP_OWNERSHIP_CHECK) Executor(java.util.concurrent.Executor) RollbackCommand(org.infinispan.commands.tx.RollbackCommand) ClusterListenerReplicateCallable(org.infinispan.notifications.cachelistener.cluster.ClusterListenerReplicateCallable) Publisher(org.reactivestreams.Publisher) ValidResponse(org.infinispan.remoting.responses.ValidResponse) CacheNotifier(org.infinispan.notifications.cachelistener.CacheNotifier) InternalConflictManager(org.infinispan.conflict.impl.InternalConflictManager) Inject(org.infinispan.factories.annotations.Inject) AtomicLong(java.util.concurrent.atomic.AtomicLong) InvalidateCommand(org.infinispan.commands.write.InvalidateCommand) GlobalTransaction(org.infinispan.transaction.xa.GlobalTransaction) DistributionManager(org.infinispan.distribution.DistributionManager) AggregateCompletionStage(org.infinispan.util.concurrent.AggregateCompletionStage) IntSets(org.infinispan.commons.util.IntSets) Stop(org.infinispan.factories.annotations.Stop) InvocationContext(org.infinispan.context.InvocationContext) LocalTxInvocationContext(org.infinispan.context.impl.LocalTxInvocationContext) ComponentRef(org.infinispan.factories.impl.ComponentRef) CompletableFutures(org.infinispan.util.concurrent.CompletableFutures) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SKIP_REMOTE_LOOKUP(org.infinispan.context.Flag.SKIP_REMOTE_LOOKUP) Scope(org.infinispan.factories.scopes.Scope) PERSISTENCE(org.infinispan.util.logging.Log.PERSISTENCE) RpcOptions(org.infinispan.remoting.rpc.RpcOptions) PrepareCommand(org.infinispan.commands.tx.PrepareCommand) CommandsFactory(org.infinispan.commands.CommandsFactory) CompletionStages.handleAndCompose(org.infinispan.util.concurrent.CompletionStages.handleAndCompose) Predicate(java.util.function.Predicate) LocalPublisherManager(org.infinispan.reactive.publisher.impl.LocalPublisherManager) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) LockingMode(org.infinispan.transaction.LockingMode) List(java.util.List) PerCacheInboundInvocationHandler(org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler) LocalTransaction(org.infinispan.transaction.impl.LocalTransaction) PutKeyValueCommand(org.infinispan.commands.write.PutKeyValueCommand) LocalTopologyManager(org.infinispan.topology.LocalTopologyManager) GuardedBy(net.jcip.annotations.GuardedBy) IGNORE_RETURN_VALUES(org.infinispan.context.Flag.IGNORE_RETURN_VALUES) SKIP_XSITE_BACKUP(org.infinispan.context.Flag.SKIP_XSITE_BACKUP) DataRehashed(org.infinispan.notifications.cachelistener.annotation.DataRehashed) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionStages(org.infinispan.util.concurrent.CompletionStages) PUT_FOR_STATE_TRANSFER(org.infinispan.context.Flag.PUT_FOR_STATE_TRANSFER) HashSet(java.util.HashSet) FlagBitSets(org.infinispan.context.impl.FlagBitSets) InternalMetadataImpl(org.infinispan.metadata.impl.InternalMetadataImpl) KeyPartitioner(org.infinispan.distribution.ch.KeyPartitioner) IRAC_STATE(org.infinispan.context.Flag.IRAC_STATE) Log(org.infinispan.util.logging.Log) Response(org.infinispan.remoting.responses.Response) Flowable(io.reactivex.rxjava3.core.Flowable) Iterator(java.util.Iterator) InternalDataContainer(org.infinispan.container.impl.InternalDataContainer) RpcManager(org.infinispan.remoting.rpc.RpcManager) TransactionMode(org.infinispan.transaction.TransactionMode) Completable(io.reactivex.rxjava3.core.Completable) NON_BLOCKING_EXECUTOR(org.infinispan.factories.KnownComponentNames.NON_BLOCKING_EXECUTOR) CompletionStages.ignoreValue(org.infinispan.util.concurrent.CompletionStages.ignoreValue) PrimitiveIterator(java.util.PrimitiveIterator) TimeUnit(java.util.concurrent.TimeUnit) IllegalLifecycleStateException(org.infinispan.commons.IllegalLifecycleStateException) CacheRpcCommand(org.infinispan.commands.remote.CacheRpcCommand) XSiteStateTransferManager(org.infinispan.xsite.statetransfer.XSiteStateTransferManager) SKIP_LOCKING(org.infinispan.context.Flag.SKIP_LOCKING) RemoteTransaction(org.infinispan.transaction.impl.RemoteTransaction) Configuration(org.infinispan.configuration.cache.Configuration) DistributionInfo(org.infinispan.distribution.DistributionInfo) DeliverOrder(org.infinispan.remoting.inboundhandler.DeliverOrder) TransactionManager(javax.transaction.TransactionManager) Collections(java.util.Collections) TransactionTable(org.infinispan.transaction.impl.TransactionTable) LimitedExecutor(org.infinispan.executors.LimitedExecutor) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) CompletableFuture(java.util.concurrent.CompletableFuture) CacheTopology(org.infinispan.topology.CacheTopology) Address(org.infinispan.remoting.transport.Address) IntSet(org.infinispan.commons.util.IntSet) DataRehashed(org.infinispan.notifications.cachelistener.annotation.DataRehashed) IllegalLifecycleStateException(org.infinispan.commons.IllegalLifecycleStateException)

Example 2 with TransactionTable

use of org.infinispan.transaction.impl.TransactionTable in project infinispan by infinispan.

the class TxReplayTest method checkIfTransactionExists.

private void checkIfTransactionExists(Cache<Object, Object> cache) {
    TransactionTable table = TestingUtil.extractComponent(cache, TransactionTable.class);
    assertFalse("Expected a remote transaction.", table.getRemoteTransactions().isEmpty());
}
Also used : TransactionTable(org.infinispan.transaction.impl.TransactionTable)

Example 3 with TransactionTable

use of org.infinispan.transaction.impl.TransactionTable in project infinispan by infinispan.

the class TxCompletionNotificationCommand method invokeAsync.

@Override
public CompletionStage<?> invokeAsync(ComponentRegistry componentRegistry) throws Throwable {
    if (log.isTraceEnabled())
        log.tracef("Processing completed transaction %s", gtx);
    RemoteTransaction remoteTx = null;
    RecoveryManager recoveryManager = componentRegistry.getRecoveryManager().running();
    if (recoveryManager != null) {
        // recovery in use
        if (xid != null) {
            remoteTx = (RemoteTransaction) recoveryManager.removeRecoveryInformation(xid);
        } else {
            remoteTx = (RemoteTransaction) recoveryManager.removeRecoveryInformation(internalId);
        }
    }
    if (remoteTx == null && gtx != null) {
        TransactionTable txTable = componentRegistry.getTransactionTableRef().running();
        remoteTx = txTable.removeRemoteTransaction(gtx);
    }
    if (remoteTx == null)
        return CompletableFutures.completedNull();
    forwardCommandRemotely(componentRegistry.getStateTransferManager(), remoteTx);
    LockManager lockManager = componentRegistry.getLockManager().running();
    lockManager.unlockAll(remoteTx.getLockedKeys(), remoteTx.getGlobalTransaction());
    return CompletableFutures.completedNull();
}
Also used : RecoveryManager(org.infinispan.transaction.xa.recovery.RecoveryManager) LockManager(org.infinispan.util.concurrent.locks.LockManager) RemoteTransaction(org.infinispan.transaction.impl.RemoteTransaction) TransactionTable(org.infinispan.transaction.impl.TransactionTable)

Example 4 with TransactionTable

use of org.infinispan.transaction.impl.TransactionTable in project infinispan by infinispan.

the class InDoubtWithCommitFailsTest method test.

private void test(boolean commit) {
    assert recoveryOps(0).showInDoubtTransactions().isEmpty();
    TransactionTable tt0 = cache(0).getAdvancedCache().getComponentRegistry().getComponent(TransactionTable.class);
    EmbeddedTransaction dummyTransaction = beginAndSuspendTx(cache(0));
    prepareTransaction(dummyTransaction);
    assert tt0.getLocalTxCount() == 1;
    try {
        if (commit) {
            commitTransaction(dummyTransaction);
        } else {
            rollbackTransaction(dummyTransaction);
        }
        assert false : "exception expected";
    } catch (Exception e) {
    // expected
    }
    assertEquals(tt0.getLocalTxCount(), 1);
    assertEquals(countInDoubtTx(recoveryOps(0).showInDoubtTransactions()), 1);
    assertEquals(countInDoubtTx(recoveryOps(1).showInDoubtTransactions()), 1);
}
Also used : EmbeddedTransaction(org.infinispan.transaction.tm.EmbeddedTransaction) TransactionTable(org.infinispan.transaction.impl.TransactionTable) CacheException(org.infinispan.commons.CacheException)

Example 5 with TransactionTable

use of org.infinispan.transaction.impl.TransactionTable in project infinispan by infinispan.

the class SimpleCacheRecoveryAdminTest method checkProperlyCleanup.

@Override
protected void checkProperlyCleanup(final int managerIndex) {
    eventually(() -> TestingUtil.extractLockManager(cache(managerIndex, "test")).getNumberOfLocksHeld() == 0);
    final TransactionTable tt = TestingUtil.extractComponent(cache(managerIndex, "test"), TransactionTable.class);
    eventuallyEquals(0, tt::getRemoteTxCount);
    eventuallyEquals(0, tt::getLocalTxCount);
    final RecoveryManager rm = TestingUtil.extractComponent(cache(managerIndex, "test"), RecoveryManager.class);
    eventually(() -> rm.getInDoubtTransactions().size() == 0);
    eventually(() -> rm.getPreparedTransactionsFromCluster().all().length == 0);
}
Also used : RecoveryManager(org.infinispan.transaction.xa.recovery.RecoveryManager) TransactionTable(org.infinispan.transaction.impl.TransactionTable)

Aggregations

TransactionTable (org.infinispan.transaction.impl.TransactionTable)50 TransactionManager (javax.transaction.TransactionManager)10 DistributionManager (org.infinispan.distribution.DistributionManager)8 RemoteTransaction (org.infinispan.transaction.impl.RemoteTransaction)7 GlobalTransaction (org.infinispan.transaction.xa.GlobalTransaction)7 ConfigurationBuilder (org.infinispan.configuration.cache.ConfigurationBuilder)6 Transaction (javax.transaction.Transaction)5 InternalDataContainer (org.infinispan.container.impl.InternalDataContainer)5 RpcManager (org.infinispan.remoting.rpc.RpcManager)5 Address (org.infinispan.remoting.transport.Address)5 RecoveryManager (org.infinispan.transaction.xa.recovery.RecoveryManager)5 CompletionStage (java.util.concurrent.CompletionStage)4 Cache (org.infinispan.Cache)4 InvocationContextFactory (org.infinispan.context.InvocationContextFactory)4 MagicKey (org.infinispan.distribution.MagicKey)4 EmbeddedTransaction (org.infinispan.transaction.tm.EmbeddedTransaction)4 Collection (java.util.Collection)3 CommandsFactory (org.infinispan.commands.CommandsFactory)3 TestingUtil.getTransactionTable (org.infinispan.test.TestingUtil.getTransactionTable)3 LocalTopologyManager (org.infinispan.topology.LocalTopologyManager)3