GERONIMO-5558 Set commit status directly if no more resources after the preparing step

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/txmanager/trunk@990716 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/CommitTask.java b/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/CommitTask.java
index af245ec..a6fb482 100644
--- a/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/CommitTask.java
+++ b/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/CommitTask.java
@@ -22,12 +22,8 @@
 
 import java.util.Iterator;
 import java.util.List;
-import java.util.TimerTask;
 
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
 import javax.transaction.Status;
-import javax.transaction.SystemException;
 import javax.transaction.xa.XAException;
 import javax.transaction.xa.Xid;
 
@@ -63,8 +59,8 @@
         synchronized (this) {
             status = Status.STATUS_COMMITTING;
         }
-        for (Iterator i = rms.iterator(); i.hasNext();) {
-            TransactionBranch manager = (TransactionBranch) i.next();
+        for (Iterator<TransactionBranch> i = rms.iterator(); i.hasNext();) {
+            TransactionBranch manager = i.next();
             try {
                 try {
                     manager.getCommitter().commit(manager.getBranchId(), false);
@@ -108,7 +104,7 @@
             }
         }
         //if all resources were read only, we didn't write a prepare record.
-        if (rms.isEmpty() && status == Status.STATUS_COMMITTED) {
+        if (rms.isEmpty()) {
             try {
                 txLog.commit(xid, logMark);
                 synchronized (this) {
diff --git a/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java b/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
index 6811227..08f70fc 100644
--- a/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
+++ b/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
@@ -175,7 +175,7 @@
         }
 
         try {
-            TransactionBranch manager = (TransactionBranch) suspendedXaResources.remove(xaRes);
+            TransactionBranch manager = suspendedXaResources.remove(xaRes);
             if (manager != null) {
                 //we know about this one, it was suspended
                 xaRes.start(manager.getBranchId(), XAResource.TMRESUME);
@@ -230,13 +230,13 @@
             default:
                 throw new IllegalStateException("Status is " + getStateString(status));
         }
-        TransactionBranch manager = (TransactionBranch) activeXaResources.remove(xaRes);
+        TransactionBranch manager = activeXaResources.remove(xaRes);
         if (manager == null) {
             if (flag == XAResource.TMSUSPEND) {
                 throw new IllegalStateException("trying to suspend an inactive xaresource: " + xaRes);
             }
             //not active, and we are not trying to suspend.  We must be ending tx.
-            manager = (TransactionBranch) suspendedXaResources.remove(xaRes);
+            manager = suspendedXaResources.remove(xaRes);
             if (manager == null) {
                 throw new IllegalStateException("Resource not known to transaction: " + xaRes);
             }
@@ -263,7 +263,7 @@
             if (TransactionTimer.getCurrentTime() > timeout) {
                 status = Status.STATUS_MARKED_ROLLBACK;
                 timedout = true;
-            } 
+            }
 
             if (status == Status.STATUS_MARKED_ROLLBACK) {
                 rollbackResourcesDuringCommit(resourceManagers, false);
@@ -299,11 +299,11 @@
 
             // one-phase
             if (resourceManagers.size() == 1) {
-                TransactionBranch manager = (TransactionBranch) resourceManagers.getFirst();
+                TransactionBranch manager = resourceManagers.getFirst();
                 commitResource(manager);
                 return;
-            } 
-            
+            }
+
             boolean willCommit = false;
             try {
                 // two-phase
@@ -312,12 +312,19 @@
                 rollbackResources(resourceManagers);
                 throw e;
             }
-            
+
             // notify the RMs
             if (willCommit) {
+                //Re-check whether there are still left resourceMangers, as we might remove those Read-Only Resource in the voting process
+                if (resourceManagers.size() == 0) {
+                    synchronized (this) {
+                        status = Status.STATUS_COMMITTED;
+                    }
+                    return;
+                }
                 commitResources(resourceManagers);
             } else {
-                // set everRollback to true here because the rollback here is caused by 
+                // set everRollback to true here because the rollback here is caused by
                 // XAException during the above internalPrepare
                 rollbackResourcesDuringCommit(resourceManagers, true);
             }
@@ -418,19 +425,19 @@
                     rms.remove();
                 }
             } catch (XAException e) {
-                if (e.errorCode == XAException.XAER_RMERR 
+                if (e.errorCode == XAException.XAER_RMERR
                         || e.errorCode == XAException.XAER_PROTO
                         || e.errorCode == XAException.XAER_INVAL) {
                     throw (SystemException) new SystemException("Error during prepare; transaction was rolled back").initCause(e);
                 }
                 synchronized (this) {
                     status = Status.STATUS_MARKED_ROLLBACK;
-                    /* Per JTA spec,  If the resource manager wants to roll back the transaction, 
+                    /* Per JTA spec,  If the resource manager wants to roll back the transaction,
                     it should do so by throwing an appropriate XAException in the prepare method.
                     Also per OTS spec:
-                    The resource can return VoteRollback under any circumstances, including not having 
-                    any knowledge about the transaction (which might happen after a crash). If this 
-                    response is returned, the transaction must be rolled back. Furthermore, the Transaction 
+                    The resource can return VoteRollback under any circumstances, including not having
+                    any knowledge about the transaction (which might happen after a crash). If this
+                    response is returned, the transaction must be rolled back. Furthermore, the Transaction
                     Service is not required to perform any additional operations on this resource.*/
                     //rms.remove();
                     break;
@@ -593,12 +600,12 @@
                         // let's not set the cause here
                         log.info("Transaction has been heuristically rolled back " + manager.getCommitter() + "; continuing with rollback", e);
                         manager.getCommitter().forget(manager.getBranchId());
-                    } else if (e.errorCode == XAException.XA_RBROLLBACK 
-                            || e.errorCode == XAException.XAER_RMERR 
+                    } else if (e.errorCode == XAException.XA_RBROLLBACK
+                            || e.errorCode == XAException.XAER_RMERR
                             || e.errorCode == XAException.XAER_NOTA
                             || e.errorCode == XAException.XAER_RMFAIL) {
                         // let's not set the cause here because we expect the transaction to be rolled back eventually
-                        // TODO: for RMFAIL, it means resource unavailable temporarily.  
+                        // TODO: for RMFAIL, it means resource unavailable temporarily.
                         // do we need keep sending request to resource to make sure the roll back completes?
                     } else if (cause == null) {
                         cause = new SystemException(e.errorCode);
@@ -606,8 +613,8 @@
                 }
             }
         } catch (XAException e) {
-            throw (SystemException) new SystemException("Error during rolling back").initCause(e);            
-        }            
+            throw (SystemException) new SystemException("Error during rolling back").initCause(e);
+        }
 
         synchronized (this) {
             status = Status.STATUS_ROLLEDBACK;
@@ -644,14 +651,14 @@
                         log.error("Transaction has been heuristically committed " + manager.getCommitter() + "; continuing with rollback", e);
                         cause = e;
                         manager.getCommitter().forget(manager.getBranchId());
-                    } else if (e.errorCode == XAException.XA_RBROLLBACK 
+                    } else if (e.errorCode == XAException.XA_RBROLLBACK
                             || e.errorCode == XAException.XAER_RMERR
                             || e.errorCode == XAException.XAER_NOTA
                             || e.errorCode == XAException.XAER_RMFAIL) {
                         // XAException.XA_RBROLLBACK during commit/rollback, thus RollbackException is expected
                         // XAException.XAER_RMERR means transaction branch error and transaction has been rolled back
                         // let's not set the cause here because we expect the transaction to be rolled back eventually
-                        // TODO: for RMFAIL, it means resource unavailable temporarily.  
+                        // TODO: for RMFAIL, it means resource unavailable temporarily.
                         // do we need keep sending request to resource to make sure the roll back completes?
                     } else if (cause == null) {
                         cause = e;
@@ -659,13 +666,13 @@
                 }
             }
         } catch (XAException e) {
-            throw (SystemException) new SystemException("System error during commit/rolling back").initCause(e);            
+            throw (SystemException) new SystemException("System error during commit/rolling back").initCause(e);
         }
-        
+
         synchronized (this) {
             status = Status.STATUS_ROLLEDBACK;
         }
-        
+
         if (cause == null) {
             throw (RollbackException) new RollbackException("Unable to commit: transaction marked for rollback").initCause(cause);
         } else {
@@ -673,12 +680,12 @@
                 throw (HeuristicMixedException) new HeuristicMixedException("HeuristicMixed error during commit/rolling back").initCause(cause);
             } else if (cause.errorCode == XAException.XA_HEURMIX) {
                 throw (HeuristicMixedException) new HeuristicMixedException("HeuristicMixed error during commit/rolling back").initCause(cause);
-            } else {            
+            } else {
                 throw (SystemException) new SystemException("System Error during commit/rolling back").initCause(cause);
-            } 
+            }
         }
     }
-    
+
     private void commitResource(TransactionBranch manager) throws RollbackException, HeuristicRollbackException, HeuristicMixedException, SystemException{
         XAException cause = null;
         try {
@@ -693,7 +700,7 @@
                 synchronized (this) {
                     status = Status.STATUS_ROLLEDBACK;
                 }
-                
+
                 if (e.errorCode == XAException.XA_HEURRB) {
                     cause = e;
                     manager.getCommitter().forget(manager.getBranchId());
@@ -706,20 +713,20 @@
                     // let's not throw an exception as the transaction has been committed
                     log.info("Transaction has been heuristically committed");
                     manager.getCommitter().forget(manager.getBranchId());
-                } else if (e.errorCode == XAException.XA_RBROLLBACK 
-                        || e.errorCode == XAException.XAER_RMERR 
+                } else if (e.errorCode == XAException.XA_RBROLLBACK
+                        || e.errorCode == XAException.XAER_RMERR
                         || e.errorCode == XAException.XAER_NOTA) {
-                    // Per XA spec, XAException.XAER_RMERR from commit means An error occurred in 
-                    // committing the work performed on behalf of the transaction branch 
-                    // and the branch's work has been rolled back. 
+                    // Per XA spec, XAException.XAER_RMERR from commit means An error occurred in
+                    // committing the work performed on behalf of the transaction branch
+                    // and the branch's work has been rolled back.
                     // XAException.XAER_NOTA:  assume the DB took a unilateral rollback decision and forgot the transaction
                     log.info("Transaction has been rolled back");
                     cause = e;
-                    // throw (RollbackException) new RollbackException("Error during one-phase commit").initCause(e);                        
+                    // throw (RollbackException) new RollbackException("Error during one-phase commit").initCause(e);
                 } else {
                     cause = e;
                     //throw (SystemException) new SystemException("Error during one-phase commit").initCause(e);
-                }                    
+                }
             }
         } catch (XAException e) {
             if (e.errorCode == XAException.XAER_NOTA) {
@@ -729,22 +736,22 @@
                 throw (SystemException) new SystemException("Error during one phase commit").initCause(e);
             }
         }
-        
+
         if (cause != null) {
             if (cause.errorCode == XAException.XA_HEURRB) {
                 throw (HeuristicRollbackException) new HeuristicRollbackException("Error during two phase commit").initCause(cause);
             } else if (cause.errorCode == XAException.XA_HEURMIX) {
                 throw (HeuristicMixedException) new HeuristicMixedException("Error during two phase commit").initCause(cause);
-            } else if (cause.errorCode == XAException.XA_RBROLLBACK 
-                    || cause.errorCode == XAException.XAER_RMERR 
+            } else if (cause.errorCode == XAException.XA_RBROLLBACK
+                    || cause.errorCode == XAException.XAER_RMERR
                     || cause.errorCode == XAException.XAER_NOTA) {
                 throw (RollbackException) new RollbackException("Error during two phase commit").initCause(cause);
             } else {
                 throw (SystemException) new SystemException("Error during two phase commit").initCause(cause);
-            } 
+            }
         }
     }
-    
+
     private void commitResources(List<TransactionBranch> rms) throws HeuristicRollbackException, HeuristicMixedException, SystemException {
         CommitTask commitTask = new CommitTask(xid, rms, logMark, retryScheduler, txnLog);
         synchronized (this) {