/*
* Same transaction
*/
return 0;
}
final TransactionStatus target = getStatus(tsv);
if (target == null) {
/*
* Target is gone
*/
return 0;
}
if (target.getTs() != tsv) {
/*
* By the time the selected TransactionStatus has been found, it may
* already be allocated to another transaction. If that's true the
* the original transaction must have committed. The following code
* checks the identity of the transaction on each iteration after
* short lock attempts.
*/
return 0;
}
if (target.getTc() > 0 && target.getTc() < source.getTs() || target.getTc() == ABORTED) {
/*
* Target is committed or aborted
*/
return 0;
}
final long start = System.currentTimeMillis();
/*
* Blocks until the target transaction finishes, either by committing or
* aborting.
*/
do {
try {
/*
* Link to target transaction, then test for deadlock. Abort
* immediately
*/
source.setDepends(target);
if (isDeadlocked(source)) {
_deadlockCounter.incrementAndGet();
return UNCOMMITTED;
}
if (target.wwLock(Math.min(timeout, SHORT_TIMEOUT))) {
try {
if (target.getTs() != tsv) {
return 0;
}
final long tc = target.getTc();
if (tc == ABORTED) {
return 0;
}
/*
* The following is true because the target's wwLock was
* acquired, which means it has either aborted or
* committed.
*/
if (tc < 0 || tc == UNCOMMITTED) {
throw new IllegalStateException("Commit incomplete");
}
/*
* true if and only if this is a concurrent transaction
*/
if (tc > source.getTs()) {
return tc;
} else {
return 0;
}
} finally {
target.wwUnlock();
}
} else {
if (timeout == 0) {
return TIMED_OUT;
}