use of org.infinispan.transaction.xa.CacheTransaction in project infinispan by infinispan.
the class StateConsumerImpl method applyTransactions.
private void applyTransactions(Address sender, Collection<TransactionInfo> transactions, int topologyId) {
log.debugf("Applying %d transactions for cache %s transferred from node %s", transactions.size(), cacheName, sender);
if (isTransactional) {
for (TransactionInfo transactionInfo : transactions) {
GlobalTransaction gtx = transactionInfo.getGlobalTransaction();
if (rpcManager.getAddress().equals(gtx.getAddress())) {
// it is a transaction originated in this node. can happen with partition handling
continue;
}
// Mark the global transaction as remote. Only used for logging, hashCode/equals ignore it.
gtx.setRemote(true);
CacheTransaction tx = transactionTable.getLocalTransaction(gtx);
if (tx == null) {
tx = transactionTable.getRemoteTransaction(gtx);
if (tx == null) {
try {
// just in case, set the previous topology id to make the current topology id check for pending locks.
tx = transactionTable.getOrCreateRemoteTransaction(gtx, transactionInfo.getModifications(), topologyId - 1);
// Force this node to replay the given transaction data by making it think it is 1 behind
((RemoteTransaction) tx).setLookedUpEntriesTopology(topologyId - 1);
} catch (Throwable t) {
if (log.isTraceEnabled())
log.tracef(t, "Failed to create remote transaction %s", gtx);
}
}
}
if (tx != null) {
transactionInfo.getLockedKeys().forEach(tx::addBackupLockForKey);
}
}
}
}
use of org.infinispan.transaction.xa.CacheTransaction in project infinispan by infinispan.
the class StateProviderImpl method collectTransactionsToTransfer.
private void collectTransactionsToTransfer(Address destination, List<TransactionInfo> transactionsToTransfer, Collection<? extends CacheTransaction> transactions, IntSet segments, CacheTopology cacheTopology) {
int topologyId = cacheTopology.getTopologyId();
Set<Address> members = new HashSet<>(cacheTopology.getMembers());
// no need to filter out state transfer generated transactions because there should not be any such transactions running for any of the requested segments
for (CacheTransaction tx : transactions) {
final GlobalTransaction gtx = tx.getGlobalTransaction();
// Also skip transactions that originates after state transfer starts.
if (tx.getTopologyId() == topologyId || (transactionOriginatorChecker.isOriginatorMissing(gtx, members))) {
if (log.isTraceEnabled())
log.tracef("Skipping transaction %s as it was started in the current topology or by a leaver", tx);
continue;
}
// transfer only locked keys that belong to requested segments
Set<Object> filteredLockedKeys = new HashSet<>();
// avoids the warning about synchronizing in a local variable.
// and allows us to change the CacheTransaction internals without having to worry about it
Consumer<Object> lockFilter = key -> {
if (segments.contains(keyPartitioner.getSegment(key))) {
filteredLockedKeys.add(key);
}
};
tx.forEachLock(lockFilter);
tx.forEachBackupLock(lockFilter);
if (filteredLockedKeys.isEmpty()) {
if (log.isTraceEnabled())
log.tracef("Skipping transaction %s because the state requestor %s doesn't own any key", tx, destination);
continue;
}
if (log.isTraceEnabled())
log.tracef("Sending transaction %s to new owner %s", tx, destination);
List<WriteCommand> txModifications = tx.getModifications();
WriteCommand[] modifications = null;
if (!txModifications.isEmpty()) {
modifications = txModifications.toArray(new WriteCommand[0]);
}
// affected nodes set, so that the it receives the commit/rollback command. See ISPN-3389.
if (tx instanceof LocalTransaction) {
LocalTransaction localTx = (LocalTransaction) tx;
localTx.locksAcquired(Collections.singleton(destination));
if (log.isTraceEnabled())
log.tracef("Adding affected node %s to transferred transaction %s (keys %s)", destination, gtx, filteredLockedKeys);
}
transactionsToTransfer.add(new TransactionInfo(gtx, tx.getTopologyId(), modifications, filteredLockedKeys));
}
}
use of org.infinispan.transaction.xa.CacheTransaction in project infinispan by infinispan.
the class DefaultPendingLockManager method getTopologyId.
private int getTopologyId(TxInvocationContext<?> context) {
final CacheTransaction tx = context.getCacheTransaction();
boolean isFromStateTransfer = context.isOriginLocal() && ((LocalTransaction) tx).isFromStateTransfer();
// if the transaction is from state transfer it should not wait for the backup locks of other transactions
if (!isFromStateTransfer) {
final int topologyId = distributionManager.getCacheTopology().getTopologyId();
if (topologyId != TransactionTable.CACHE_STOPPED_TOPOLOGY_ID) {
if (transactionTable.getMinTopologyId() < topologyId) {
return topologyId;
}
}
}
return NO_PENDING_CHECK;
}
use of org.infinispan.transaction.xa.CacheTransaction in project infinispan by infinispan.
the class VersionedDistributionInterceptor method prepareOnAffectedNodes.
@Override
protected CompletionStage<Object> prepareOnAffectedNodes(TxInvocationContext<?> ctx, PrepareCommand command, Collection<Address> recipients) {
CompletionStage<Map<Address, Response>> remoteInvocation;
if (recipients != null) {
MapResponseCollector collector = MapResponseCollector.ignoreLeavers(recipients.size());
remoteInvocation = rpcManager.invokeCommand(recipients, command, collector, rpcManager.getSyncRpcOptions());
} else {
MapResponseCollector collector = MapResponseCollector.ignoreLeavers();
remoteInvocation = rpcManager.invokeCommandOnAll(command, collector, rpcManager.getSyncRpcOptions());
}
return remoteInvocation.handle((responses, t) -> {
transactionRemotelyPrepared(ctx);
CompletableFutures.rethrowExceptionIfPresent(t);
PrepareResponse prepareResponse = new PrepareResponse();
checkTxCommandResponses(responses, command, (TxInvocationContext<LocalTransaction>) ctx, recipients, prepareResponse);
// Now store newly generated versions from lock owners for use during the commit phase.
CacheTransaction ct = ctx.getCacheTransaction();
ct.setUpdatedEntryVersions(prepareResponse.mergeEntryVersions(ct.getUpdatedEntryVersions()));
return prepareResponse;
});
}
Aggregations