### Eclipse Workspace Patch 1.0 #P jackrabbit-core Index: src/main/java/org/apache/jackrabbit/core/TransactionContext.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/TransactionContext.java (revision 1063240) +++ src/main/java/org/apache/jackrabbit/core/TransactionContext.java (working copy) @@ -70,6 +70,11 @@ private final int timeout; /** + * Indicates if this {@link TransactionContext} has timed out internally + */ + private boolean timedOut = false; + + /** * The Xid */ private final Xid xid; @@ -144,9 +149,11 @@ * all resources. If some resource reports an error on prepare, * automatically rollback changes on all other resources. Throw exception * at the end if errors were found. + * @param onePhaseOptimized if true this prepare comes from a onePhase optimized Transaction. + * Internal Timeout-Task will be started. * @throws XAException if an error occurs */ - public synchronized void prepare() throws XAException { + public synchronized void prepare(boolean onePhaseOptimized) throws XAException { bindCurrentXid(); status = STATUS_PREPARING; beforeOperation(); @@ -176,8 +183,10 @@ throw e; } - // start rollback task in case the commit is never issued - timer.schedule(this, timeout * 1000, Integer.MAX_VALUE); + if (onePhaseOptimized) { + // start rollback task in case the commit is never issued + timer.schedule(this, timeout * 1000, Integer.MAX_VALUE); + } } /** @@ -185,12 +194,18 @@ * all resources. If some resource reports an error on commit, * automatically rollback changes on all other resources. Throw * exception at the end if some commit failed. + * @param true if the commit comes from a onePhase optimized Transaction. * @throws XAException if an error occurs */ - public synchronized void commit() throws XAException { + public synchronized void commit(boolean onePhase) throws XAException { if (status == STATUS_ROLLED_BACK) { - throw new XAException(XAException.XA_RBTIMEOUT); + if (onePhase && timedOut) { + throw new XAException(XAException.XA_RBTIMEOUT); + } else { + throw new XAException(XAException.XA_HEURRB); + } } + boolean heuristicCommit = false; bindCurrentXid(); status = STATUS_COMMITTING; beforeOperation(); @@ -207,6 +222,7 @@ } else { try { resource.commit(this); + heuristicCommit = true; } catch (TransactionException e) { txe = e; } @@ -215,14 +231,21 @@ afterOperation(); status = STATUS_COMMITTED; - // cancel the rollback task - cancel(); + if (onePhase) { + // cancel the rollback task only in onePhase Transactions + cancel(); + } cleanCurrentXid(); if (txe != null) { - XAException e = new XAException(XAException.XA_RBOTHER); - e.initCause(txe); - throw e; + XAException e = null; + if (heuristicCommit) { + e = new XAException(XAException.XA_HEURMIX); + } else { + e = new XAException(XAException.XA_HEURRB); + } + e.initCause(txe); + throw e; } } @@ -233,7 +256,7 @@ */ public synchronized void rollback() throws XAException { if (status == STATUS_ROLLED_BACK) { - throw new XAException(XAException.XA_RBTIMEOUT); + throw new XAException(XAException.XA_RBOTHER); } bindCurrentXid(); status = STATUS_ROLLING_BACK; @@ -273,6 +296,7 @@ } catch (XAException e) { /* ignore */ } + timedOut = true; log.warn("Transaction rolled back because timeout expired."); } // cancel the rollback task Index: src/main/java/org/apache/jackrabbit/core/XASessionImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (revision 1063240) +++ src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (working copy) @@ -309,7 +309,7 @@ if (tx == null) { throw new XAException(XAException.XAER_NOTA); } - tx.prepare(); + tx.prepare(false); return XA_OK; } @@ -322,9 +322,9 @@ throw new XAException(XAException.XAER_NOTA); } if (onePhase) { - tx.prepare(); + tx.prepare(onePhase); } - tx.commit(); + tx.commit(onePhase); txGlobal.remove(xid); }