Return-Path: Delivered-To: apmail-geronimo-scm-archive@www.apache.org Received: (qmail 6411 invoked from network); 17 Dec 2008 19:14:09 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 17 Dec 2008 19:14:09 -0000 Received: (qmail 90115 invoked by uid 500); 17 Dec 2008 19:14:21 -0000 Delivered-To: apmail-geronimo-scm-archive@geronimo.apache.org Received: (qmail 90074 invoked by uid 500); 17 Dec 2008 19:14:21 -0000 Mailing-List: contact scm-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list scm@geronimo.apache.org Received: (qmail 90065 invoked by uid 99); 17 Dec 2008 19:14:21 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Dec 2008 11:14:21 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Dec 2008 19:14:07 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D5A8623888F1; Wed, 17 Dec 2008 11:13:47 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r727474 - /geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java Date: Wed, 17 Dec 2008 19:13:47 -0000 To: scm@geronimo.apache.org From: linsun@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20081217191347.D5A8623888F1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: linsun Date: Wed Dec 17 11:13:47 2008 New Revision: 727474 URL: http://svn.apache.org/viewvc?rev=727474&view=rev Log: GERONIMO-4471 improve heuristic exception handling in rollback when txmanager.commit is called Modified: geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java Modified: geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java URL: http://svn.apache.org/viewvc/geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java?rev=727474&r1=727473&r2=727474&view=diff ============================================================================== --- geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java (original) +++ geronimo/components/txmanager/branches/geronimo-txmanager-parent-2.1/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/TransactionImpl.java Wed Dec 17 11:13:47 2008 @@ -265,7 +265,7 @@ } if (status == Status.STATUS_MARKED_ROLLBACK) { - rollbackResources(resourceManagers); + rollbackResourcesDuringCommit(resourceManagers, false); if (timedout) { throw new RollbackException("Transaction timeout"); } else { @@ -333,8 +333,9 @@ if (willCommit) { commitResources(resourceManagers); } else { - rollbackResources(resourceManagers); - throw new RollbackException("Unable to commit"); + // set everRollback to true here because the rollback here is caused by + // XAException during the above internalPrepare + rollbackResourcesDuringCommit(resourceManagers, true); } } catch (XAException e) { throw (SystemException) new SystemException("Error during commit").initCause(e); @@ -438,8 +439,13 @@ } catch (XAException e) { synchronized (this) { status = Status.STATUS_MARKED_ROLLBACK; - //TODO document why this is true from the spec. - //XAException during prepare means we can assume resource is rolled back. + /* 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 + Service is not required to perform any additional operations on this resource.*/ rms.remove(); break; } @@ -609,6 +615,60 @@ throw cause; } } + + private void rollbackResourcesDuringCommit(List rms, boolean everRb) throws HeuristicMixedException, RollbackException, SystemException { + XAException cause = null; + boolean everRolledback = everRb; + synchronized (this) { + status = Status.STATUS_ROLLING_BACK; + } + try { + for (Iterator i = rms.iterator(); i.hasNext();) { + TransactionBranch manager = (TransactionBranch) i.next(); + try { + manager.getCommitter().rollback(manager.getBranchId()); + everRolledback = true; + } catch (XAException e) { + if (e.errorCode == XAException.XA_HEURRB) { + // let's not set the cause here + log.error("Transaction has been heuristically rolled back " + manager.getCommitter() + "; continuing with rollback", e); + everRolledback = true; + manager.getCommitter().forget(manager.getBranchId()); + } else if (e.errorCode == XAException.XA_HEURMIX) { + log.error("Transaction has been heuristically committed and rolled back " + manager.getCommitter() + "; continuing with rollback", e); + cause = e; + everRolledback = true; + manager.getCommitter().forget(manager.getBranchId()); + } else if (e.errorCode == XAException.XA_HEURCOM) { + log.error("Transaction has been heuristically committed " + manager.getCommitter() + "; continuing with rollback", e); + cause = e; + manager.getCommitter().forget(manager.getBranchId()); + } else if (cause == null) { + cause = e; + } + } + } + } catch (XAException e) { + throw (SystemException) new SystemException("Error during rolling back").initCause(e); + } + + synchronized (this) { + status = Status.STATUS_ROLLEDBACK; + } + + if (cause == null) { + throw (RollbackException) new RollbackException("Error during two phase commit").initCause(cause); + } else { + if (cause.errorCode == XAException.XA_HEURCOM && everRolledback) { + throw (HeuristicMixedException) new HeuristicMixedException("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 { + throw (SystemException) new SystemException("Error during two phase commit").initCause(cause); + } + } + } + private void commitResources(List rms) throws HeuristicRollbackException, HeuristicMixedException, SystemException { XAException cause = null;