Transaction child, child1;
switch (isTxnValid(TXN_COMMITING)) {
case 0:
break;
case 1:
throw new ChaiDBException(ErrorCode.IN_RECOVER_PROCESS);
case 2:
throw new ChaiDBException(ErrorCode.RECOMMITED_FAILURE);
case 3:
throw new ChaiDBException(ErrorCode.REABORTTED_FAILURE);
case 4:
break;
case 5:
break;
}
//Set status to committed
status = TXN_COMMITING;
/*
* Commit any unresolved children. If there's an error, abort any
* unresolved children and the parent.
*/
Enumeration childTxns = this.getChilds().elements();
while (childTxns.hasMoreElements()) {
child = (Transaction) childTxns.nextElement();
try {
child.commit();
} catch (ChaiDBException txnAbortedEx) { //If one child txn isn't committed successfully, all childs txns will be aborted.
logger.error(txnAbortedEx);
Enumeration childTxns1 = this.getChilds().elements();
while (childTxns1.hasMoreElements()) {
child1 = (Transaction) childTxns1.nextElement();
try {
child1.abort();
} catch (ChaiDBException e) {
logger.error(e);
// preserving all the previous abort reports -ranjeet
ChaiDBException highLevel = new ChaiDBException(ErrorCode.ABORT_FAILURE, txnAbortedEx);
throw highLevel;
}
}//end while
try {
this.abort(); // Abort itself parent.
} catch (ChaiDBException e) {
logger.error(e);
// preserving all the previous abort reports -ranjeet
ChaiDBException highLevel = new ChaiDBException(ErrorCode.ABORT_FAILURE, txnAbortedEx);
throw highLevel;
}
throw new ChaiDBException(ErrorCode.COMMIT_FAILURE, txnAbortedEx);
}//end try
}//end while
try {
//At first we precommit the memory log
lnkTransactionManager.getMemLogManager().preCommit(txnId);
/*
* If there are any log records, write a log record and sync the log,
* else do no log writes. If the commit is for a child transaction,
* we do not need to commit the child synchronously since it may still
* abort (if its parent aborts), and otherwise its parent or ultimate
* ancestor will write synchronously.
*
* I'd rather return a logging error than a flag-wrong error, so if
* the log routines fail, set "ret" without regard to previous value.
*/
if (!(lastLsn.getFileId() == 0)) {
bpm.flushChangedDocRoot(kCtx);
if (this.parent == null) {
int flag = 0;
if ((this.flags & Transaction.TXN_NOSYNC) != 0) {
flag = Transaction.TXN_NOSYNC;
} else if ((this.flags & Transaction.TXN_SYNC) != 0) {
flag = Transaction.TXN_SYNC;
}
//Comment it out. Maybe it is caused long txn.
//The commit log record has inserted into log file.
//But before it will be removed from active txn list, there
//are some activity need to done, include memlogMgr.commit(),
//release resources, put locks etc. Once one of activity
//throw exception, the txn will never be removed from active txn list.
//I will move it into endTxn.
//(new TxnRegopLogRecord(TXN_COMMIT,(new Date()).getTime(),this.txnId)).log(flag);
} else { /* Log the commit in the parent! */
(new TxnChildLogRecord(txnId, lastLsn, this.parent.getTxnId())).log(); //pending ?!
parent.setFlags(TXN_CHILDCOMMIT);
}
} //end if (!(lastLsn.getFileId() == 0))
lnkTransactionManager.getMemLogManager().commit(txnId);
} catch (ChaiDBException ie) {
logger.error(ie);
throw ie;
} catch (Exception excp) {
logger.error(excp);
throw new ChaiDBException(ErrorCode.TXN_ERROR_BASE, excp);
} finally {
status = Transaction.TXN_RUNNING;
}
endTxn(isCommit);