use of org.infinispan.commands.remote.CheckTransactionRpcCommand in project infinispan by infinispan.
the class TransactionTable method cleanupTimedOutTransactions.
private void cleanupTimedOutTransactions() {
if (log.isTraceEnabled())
log.tracef("About to cleanup remote transactions older than %d ms", configuration.transaction().completedTxTimeout());
long beginning = timeService.time();
long cutoffCreationTime = beginning - TimeUnit.MILLISECONDS.toNanos(configuration.transaction().completedTxTimeout());
List<GlobalTransaction> toKill = new ArrayList<>();
Map<Address, Collection<GlobalTransaction>> toCheck = new HashMap<>();
// Check remote transactions.
for (Map.Entry<GlobalTransaction, RemoteTransaction> e : remoteTransactions.entrySet()) {
GlobalTransaction gtx = e.getKey();
RemoteTransaction remoteTx = e.getValue();
// concurrent map doesn't accept null values
assert remoteTx != null;
if (log.isTraceEnabled()) {
log.tracef("Checking transaction %s", gtx);
}
// Check the time.
long creationTime = remoteTx.getCreationTime();
if (creationTime - cutoffCreationTime >= 0) {
// transaction still valid
continue;
}
if (transactionOriginatorChecker.isOriginatorMissing(gtx)) {
// originator no longer available. Transaction can be rolled back.
long duration = timeService.timeDuration(creationTime, beginning, TimeUnit.MILLISECONDS);
log.remoteTransactionTimeout(gtx, duration);
toKill.add(gtx);
} else {
// originator alive or hot rod transaction
Address orig = gtx.getAddress();
if (rpcManager.getMembers().contains(orig)) {
// originator still in view. Check if the transaction is valid.
Collection<GlobalTransaction> addressCheckList = toCheck.computeIfAbsent(orig, k -> new ArrayList<>());
addressCheckList.add(gtx);
}
// else, it is a hot rod transaction. don't kill it since the server reaper will take appropriate action
}
}
// check if the transaction is running on originator
for (Map.Entry<Address, Collection<GlobalTransaction>> entry : toCheck.entrySet()) {
CheckTransactionRpcCommand cmd = commandsFactory.buildCheckTransactionRpcCommand(entry.getValue());
RpcOptions rpcOptions = rpcManager.getSyncRpcOptions();
rpcManager.invokeCommand(entry.getKey(), cmd, CheckTransactionRpcCommand.responseCollector(), rpcOptions).thenAccept(this::killAllTransactionsAsync);
}
// Rollback the orphaned transactions and release any held locks.
killAllTransactionsAsync(toKill);
}
use of org.infinispan.commands.remote.CheckTransactionRpcCommand in project infinispan by infinispan.
the class NoLockLostOnLongTxTest method testCheckTransactionRpcCommand.
public void testCheckTransactionRpcCommand() throws Exception {
// default cache is transactional
Cache<String, String> cache0 = cache(0);
Cache<String, String> cache1 = cache(1);
CommandsFactory factory = cache0.getAdvancedCache().getComponentRegistry().getCommandsFactory();
RpcManager rpcManager = cache0.getAdvancedCache().getRpcManager();
RpcOptions rpcOptions = rpcManager.getSyncRpcOptions();
ResponseCollector<Collection<GlobalTransaction>> collector = CheckTransactionRpcCommand.responseCollector();
Address remoteAddress = cache1.getAdvancedCache().getRpcManager().getAddress();
TransactionTable transactionTable = cache1.getAdvancedCache().getComponentRegistry().getTransactionTable();
CheckTransactionRpcCommand rpcCommand = factory.buildCheckTransactionRpcCommand(Collections.emptyList());
Collection<GlobalTransaction> result = rpcManager.invokeCommand(remoteAddress, rpcCommand, collector, rpcOptions).toCompletableFuture().join();
assertTrue("Expected an empty collection but got: " + result, result.isEmpty());
TransactionManager tm = cache1.getAdvancedCache().getTransactionManager();
tm.begin();
cache1.put("k", "v");
rpcCommand = factory.buildCheckTransactionRpcCommand(transactionTable.getLocalGlobalTransaction());
result = rpcManager.invokeCommand(remoteAddress, rpcCommand, collector, rpcOptions).toCompletableFuture().join();
assertTrue("Expected an empty collection but got: " + result, result.isEmpty());
tm.commit();
GlobalTransaction nonExistingGtx = new GlobalTransaction(remoteAddress, false);
nonExistingGtx.setId(-1);
Collection<GlobalTransaction> list = Collections.singletonList(nonExistingGtx);
rpcCommand = factory.buildCheckTransactionRpcCommand(list);
result = rpcManager.invokeCommand(remoteAddress, rpcCommand, collector, rpcOptions).toCompletableFuture().join();
assertEquals("Wrong list returned.", list, result);
}
Aggregations