private void rollbackSuspended(Predicate<TransactionMarker> predicate) { Set<Long> candidateTransactionIdsToRollback = new HashSet<Long>(); for (Map.Entry<Long, TransactionMarker> entry : registry.entrySet()) { TransactionMarker marker = entry.getValue(); if (marker.isSuspended() && predicate.accept(marker)) { candidateTransactionIdsToRollback.add(entry.getKey()); } } for (long id : candidateTransactionIdsToRollback) { TransactionHandle handle; try { handle = acquire(id); } catch (TransactionLifecycleException invalidTransactionId) { // Allow this - someone snatched the transaction from under our feet, continue; } try { handle.forceRollback(); log.info(format("Transaction with id %d has been automatically rolled back.", id)); } catch (Throwable e) { log.error(format("Transaction with id %d failed to roll back.", id), e); } finally { forget(id); } } }
@Override public void forget(long id) { TransactionMarker marker = registry.get(id); if (null == marker) { throw new IllegalStateException("Could not finish unregistered transaction"); } if (marker.isSuspended()) { throw new IllegalStateException("Cannot finish suspended registered transaction"); } if (!registry.remove(id, marker)) { throw new IllegalStateException( "Trying to finish transaction that has been concurrently finished or suspended"); } }
@Override public long release(long id, TransactionHandle transactionHandle) { TransactionMarker marker = registry.get(id); if (null == marker) { throw new IllegalStateException("Trying to suspend unregistered transaction"); } if (marker.isSuspended()) { throw new IllegalStateException("Trying to suspend transaction that was already suspended"); } SuspendedTransaction suspendedTx = new SuspendedTransaction(marker.getActiveTransaction(), transactionHandle); if (!registry.replace(id, marker, suspendedTx)) { throw new IllegalStateException( "Trying to suspend transaction that has been concurrently suspended"); } return computeNewExpiryTime(suspendedTx.getLastActiveTimestamp()); }