if (joinvec == null) {
if (modifyTxnState(ABORTED))
return;
else
throw new
CannotAbortException("Transaction already COMMITTED");
}
int numparts = joinvec.size();
ParticipantHandle[] phs = new ParticipantHandle[numparts];
joinvec.copyInto(phs);
ClientLog log = logmgr.logFor(str.id);
//When attempting to abort, if someone has already
//committed the transaction, then throw an Exception.
//
//If an abort is possible, and you find that an AbortJob
//is already in progress, let the existing AbortJob
//proceed.
//
//If an abort is possible, but a PrepareJob is in progress,
//go ahead an halt the PrepareJob and replace it with
//an AbortJob.
if (modifyTxnState(ABORTED)) {
log.write(new AbortRecord(phs));
synchronized (jobLock) {
if (!(job instanceof AbortJob)) {
if (job != null)
job.stop();
job = new AbortJob(str, threadpool, wm, log, phs);
job.scheduleTasks();
}
}
} else {
throw new CannotAbortException("Transaction already COMMITTED");
}
//This code waits for an AbortJob to complete and
//computes its resulting outcome. In addition,
//the wait time is enforced. Should the wait time
//expire, a SettlerTask is scheduled on a thread
//pool. The SettlerTask is needed to complete
//the abort (instruct participants to roll-back)
//on behalf of the thread which exits when
//the TimeoutExpiredException is thrown.
long now = System.currentTimeMillis();
long transpired = now - starttime;
Integer result = new Integer(ACTIVE);
boolean aborted = false;
long remainder = waitFor - transpired;
try {
synchronized (jobLock) {
if (remainder<= 0 || !job.isCompleted(remainder)) {
settler.noteUnsettledTxn(str.id);
throw new TimeoutExpiredException(
"timeout expired",false);
} else {
result = (Integer) job.computeResult();
aborted = true;
}
}
} catch (ResultNotReadyException rnre) {
//should not happen, so flag as error
} catch (JobNotStartedException jnse) {
//error
} catch (JobException je) {
settler.noteUnsettledTxn(str.id);
throw new TimeoutExpiredException("timeout expired", false);
}
if (!aborted)
throw new InternalManagerException("TxnManagerTransaction: " +
"abort: AbortJob got bad state: " +
TxnConstants.getName(result.intValue()));
log.invalidate();
} catch (RuntimeException rte) {
if (transactionsLogger.isLoggable(Level.SEVERE)) {
transactionsLogger.log(Level.SEVERE,
"Problem aborting transaction",
rte);
}
throw new InternalManagerException("TxnManagerTransaction: " +
"abort: fatal error");
} catch (LogException le) {
if (transactionsLogger.isLoggable(Level.FINEST)) {
transactionsLogger.log(Level.FINEST,
"Problem persisting transaction",
le);
}
throw new CannotAbortException("Unable to log");
}
if (operationsLogger.isLoggable(Level.FINER)) {
operationsLogger.exiting(TxnManagerTransaction.class.getName(),
"abort");
}