in geode-core/src/main/java/org/apache/geode/internal/jta/TransactionManagerImpl.java [217:392]
public void commit() throws HeuristicRollbackException, RollbackException,
HeuristicMixedException, SystemException {
if (!isActive) {
throw new SystemException(
"TransactionManager invalid");
}
int cozOfException = -1;
Transaction transactionImpl = getTransaction();
if (transactionImpl == null) {
String exception =
"Transaction is null, cannot commit a null transaction";
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception);
}
throw new IllegalStateException(exception);
}
GlobalTransaction gtx = getGlobalTransaction(transactionImpl);
if (gtx == null) {
String exception =
"Global Transaction is null, cannot commit a null global transaction";
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception);
}
throw new SystemException(exception);
}
boolean isCommit = false;
// ensure only one thread can commit. Use a synchronized block
// Asif
int status = -1;
if (((status = gtx.getStatus()) == Status.STATUS_ACTIVE)
|| status == Status.STATUS_MARKED_ROLLBACK) {
synchronized (gtx) {
if ((status = gtx.getStatus()) == Status.STATUS_ACTIVE) {
gtx.setStatus(Status.STATUS_COMMITTING);
isCommit = true;
} else if (status == Status.STATUS_MARKED_ROLLBACK) {
gtx.setStatus(Status.STATUS_ROLLING_BACK);
cozOfException = MARKED_ROLLBACK;
} else {
String exception =
String.format("transaction not active, cannot be committed. Transaction Status= %s",
status);
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception);
}
throw new IllegalStateException(exception);
}
}
} else {
String exception =
"transaction is not active and cannot be committed";
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception);
}
throw new IllegalStateException(exception);
}
// Only one thread can call commit (the first thread to do reach the block
// above).
// Before commiting the notifications to be done before the done are called
// the global transaction is called and then the after completion
// notifications
// are taken care of. The transactions associated to the global
// transactions are
// removed from the map and also the tread to transaction.
//
// Asif : Store the thrown Exception in case of commit .
// Reuse it for thrwing later.
// Asif TODO:Verify if it is a good practise
boolean isClean = false;
Exception e = null;
try {
((TransactionImpl) transactionImpl).notifyBeforeCompletion();
isClean = true;
} catch (Exception ge) {
// Asif : Just mark the Tranxn to setRollbackOnly to ensure Rollback
setRollbackOnly();
cozOfException = EXCEPTION_IN_NOTIFY_BEFORE_COMPLETION;
e = ge;
}
// TODO:Asif In case the status of transaction is marked as
// ROLLING_BACK , then we don't have to take a synch block
// As once the status is marked for ROLLING_BACK , setRollnbackonly
// will be harmless
if (isCommit) {
synchronized (gtx) {
if ((status = gtx.getStatus()) == Status.STATUS_COMMITTING) {
// Asif: Catch any exception encountered during commit
// and appropriately mark the exception code
try {
gtx.commit();
} catch (RollbackException rbe) {
e = rbe;
cozOfException = COMMIT_FAILED_SO_ROLLEDBAK;
} catch (SystemException se) {
e = se;
cozOfException = COMMIT_FAILED_ROLLBAK_ALSO_FAILED;
}
} else if (status == Status.STATUS_ROLLING_BACK) {
try {
gtx.rollback();
if (isClean) {
cozOfException = MARKED_ROLLBACK;
}
} catch (SystemException se) {
e = se;
cozOfException = ROLLBAK_FAILED;
}
}
}
} else {
try {
gtx.rollback();
} catch (SystemException se) {
e = se;
cozOfException = ROLLBAK_FAILED;
}
}
try {
((TransactionImpl) transactionImpl).notifyAfterCompletion(status = gtx.getStatus());
} catch (Exception ge) {
LogWriter writer = TransactionUtils.getLogWriter();
if (writer.infoEnabled()) {
writer.info(
String.format("Exception in notify after completion due to %s",
ge.getMessage()),
ge);
}
}
Thread thread = Thread.currentThread();
transactionMap.remove(thread);
gtxSet.remove(gtx);
if (status != Status.STATUS_COMMITTED) {
switch (cozOfException) {
case EXCEPTION_IN_NOTIFY_BEFORE_COMPLETION: {
String exception =
"Transaction rolled back because of Exception in notifyBeforeCompletion processing";
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception, e);
}
RollbackException re = new RollbackException(exception);
re.initCause(e);
throw re;
}
case MARKED_ROLLBACK: {
String exception =
"Transaction rolled back because a user marked it for Rollback";
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(exception, e);
}
throw new RollbackException(exception);
}
case COMMIT_FAILED_SO_ROLLEDBAK: {
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(e);
}
throw (RollbackException) e;
}
case COMMIT_FAILED_ROLLBAK_ALSO_FAILED:
case ROLLBAK_FAILED: {
LogWriter writer = TransactionUtils.getLogWriter();
if (VERBOSE) {
writer.fine(e);
}
throw (SystemException) e;
}
}
}
gtx.setStatus(Status.STATUS_NO_TRANSACTION);
}