geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From djen...@apache.org
Subject svn commit: rev 55097 - in geronimo/trunk/modules/transaction/src: java/org/apache/geronimo/transaction/log java/org/apache/geronimo/transaction/manager test/org/apache/geronimo/transaction/manager
Date Tue, 19 Oct 2004 20:35:47 GMT
Author: djencks
Date: Tue Oct 19 13:35:46 2004
New Revision: 55097

Added:
   geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/ProtocolTest.java
Modified:
   geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/log/HOWLLog.java
   geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
   geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/MockResource.java
   geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/TestTransactionManager.java
Log:
fix GERONIMO-385 and add some tests

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/log/HOWLLog.java
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/log/HOWLLog.java
(original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/log/HOWLLog.java
Tue Oct 19 13:35:46 2004
@@ -264,13 +264,14 @@
 
     public void commit(Xid xid, Object logMark) throws LogException {
         //the data is theoretically unnecessary but is included to help with debugging and
because HOWL currently requires it.
-        byte[][] data = new byte[4][];
-        data[0] = new byte[]{COMMIT};
-        data[1] = intToBytes(xid.getFormatId());
-        data[2] = xid.getGlobalTransactionId();
-        data[3] = xid.getBranchQualifier();
+//        byte[][] data = new byte[4][];
+//        data[0] = new byte[]{COMMIT};
+//        data[1] = intToBytes(xid.getFormatId());
+//        data[2] = xid.getGlobalTransactionId();
+//        data[3] = xid.getBranchQualifier();
         try {
-            logger.putDone(data, (XACommittingTx) logMark);
+//            logger.putDone(data, (XACommittingTx) logMark);
+            logger.putDone(null, (XACommittingTx) logMark);
         } catch (LogClosedException e) {
             throw (IllegalStateException) new IllegalStateException().initCause(e);
         } catch (LogRecordSizeException e) {
@@ -286,13 +287,14 @@
 
     public void rollback(Xid xid, Object logMark) throws LogException {
         //the data is theoretically unnecessary but is included to help with debugging and
because HOWL currently requires it.
-        byte[][] data = new byte[4][];
-        data[0] = new byte[]{ROLLBACK};
-        data[1] = intToBytes(xid.getFormatId());
-        data[2] = xid.getGlobalTransactionId();
-        data[3] = xid.getBranchQualifier();
+//        byte[][] data = new byte[4][];
+//        data[0] = new byte[]{ROLLBACK};
+//        data[1] = intToBytes(xid.getFormatId());
+//        data[2] = xid.getGlobalTransactionId();
+//        data[3] = xid.getBranchQualifier();
         try {
-            logger.putDone(data, (XACommittingTx) logMark);
+//            logger.putDone(data, (XACommittingTx) logMark);
+            logger.putDone(null, (XACommittingTx) logMark);
         } catch (LogClosedException e) {
             throw (IllegalStateException) new IllegalStateException().initCause(e);
         } catch (LogRecordSizeException e) {

Modified: geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
==============================================================================
--- geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
(original)
+++ geronimo/trunk/modules/transaction/src/java/org/apache/geronimo/transaction/manager/TransactionImpl.java
Tue Oct 19 13:35:46 2004
@@ -24,6 +24,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.IdentityHashMap;
 
 import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
@@ -50,10 +51,11 @@
     private final XidFactory xidFactory;
     private final Xid xid;
     private final TransactionLog txnLog;
+    private final List syncList = new ArrayList(5);
+    private final LinkedList resourceManagers = new LinkedList();
+    private final IdentityHashMap activeXaResources = new IdentityHashMap(3);
+    private final IdentityHashMap suspendedXaResources = new IdentityHashMap(3);
     private int status = Status.STATUS_NO_TRANSACTION;
-    private List syncList = new ArrayList(5);
-    private LinkedList resourceManagers = new LinkedList();
-    private Map xaResources = new HashMap(3);
     private Object logMark;
 
     TransactionImpl(XidFactory xidFactory, TransactionLog txnLog) throws SystemException
{
@@ -131,14 +133,25 @@
                 throw new IllegalStateException("Status is " + getStateString(status));
         }
 
+        if (activeXaResources.containsKey(xaRes)) {
+            throw new IllegalStateException("xaresource: " + xaRes + " is already enlisted!");
+        }
+
         try {
+            TransactionBranch manager = (TransactionBranch) suspendedXaResources.remove(xaRes);
+            if (manager != null) {
+                //we know about this one, it was suspended
+                xaRes.start(manager.getBranchId(), XAResource.TMRESUME);
+                activeXaResources.put(xaRes, manager);
+                return true;
+            }
+            //it is not suspended.
             for (Iterator i = resourceManagers.iterator(); i.hasNext();) {
-                TransactionBranch manager = (TransactionBranch) i.next();
+                manager = (TransactionBranch) i.next();
                 boolean sameRM;
                 //if the xares is already known, we must be resuming after a suspend.
                 if (xaRes == manager.getCommitter()) {
-                    xaRes.start(manager.getBranchId(), XAResource.TMRESUME);
-                    return true;
+                    throw new IllegalStateException("xaRes " + xaRes + " is a committer but
is not active or suspended");
                 }
                 //Otherwise, see if this is a new xares for the same resource manager
                 try {
@@ -149,14 +162,14 @@
                 }
                 if (sameRM) {
                     xaRes.start(manager.getBranchId(), XAResource.TMJOIN);
-                    xaResources.put(xaRes, manager);
+                    activeXaResources.put(xaRes, manager);
                     return true;
                 }
             }
-
+            //we know nothing about this XAResource or resource manager
             Xid branchId = xidFactory.createBranch(xid, resourceManagers.size() + 1);
             xaRes.start(branchId, XAResource.TMNOFLAGS);
-            addBranchXid(xaRes,  branchId);
+            activeXaResources.put(xaRes, addBranchXid(xaRes,  branchId));
             return true;
         } catch (XAException e) {
             log.warn("Unable to enlist XAResource " + xaRes, e);
@@ -165,6 +178,9 @@
     }
 
     public synchronized boolean delistResource(XAResource xaRes, int flag) throws IllegalStateException,
SystemException {
+        if (!(flag == XAResource.TMFAIL || flag == XAResource.TMSUCCESS || flag == XAResource.TMSUSPEND))
{
+            throw new IllegalStateException("invalid flag for delistResource: " + flag);
+        }
         if (xaRes == null) {
             throw new IllegalArgumentException("XAResource is null");
         }
@@ -175,12 +191,23 @@
             default:
                 throw new IllegalStateException("Status is " + getStateString(status));
         }
-        TransactionBranch manager = (TransactionBranch) xaResources.remove(xaRes);
+        TransactionBranch manager = (TransactionBranch) activeXaResources.remove(xaRes);
         if (manager == null) {
-            throw new IllegalStateException("Resource not enlisted");
+            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);
+            if (manager == null) {
+                throw new IllegalStateException("Resource not known to transaction: " + xaRes);
+            }
         }
+
         try {
             xaRes.end(manager.getBranchId(), flag);
+            if (flag == XAResource.TMSUSPEND) {
+                suspendedXaResources.put(xaRes, manager);
+            }
             return true;
         } catch (XAException e) {
             log.warn("Unable to delist XAResource " + xaRes, e);
@@ -460,12 +487,17 @@
     }
 
     private void endResources() {
+        endResources(activeXaResources);
+        endResources(suspendedXaResources);
+    }
+
+    private void endResources(IdentityHashMap resourceMap) {
         while (true) {
             XAResource xaRes;
             TransactionBranch manager;
             int flags;
             synchronized (this) {
-                Set entrySet = xaResources.entrySet();
+                Set entrySet = resourceMap.entrySet();
                 if (entrySet.isEmpty()) {
                     return;
                 }
@@ -473,7 +505,7 @@
                 xaRes = (XAResource) entry.getKey();
                 manager = (TransactionBranch) entry.getValue();
                 flags = (status == Status.STATUS_MARKED_ROLLBACK) ? XAResource.TMFAIL : XAResource.TMSUCCESS;
-                xaResources.remove(xaRes);
+                resourceMap.remove(xaRes);
             }
             try {
                 xaRes.end(manager.getBranchId(), flags);
@@ -578,10 +610,12 @@
         }
     }
 
-    public void addBranchXid(XAResource xaRes, Xid branchId) {
+    //when used from recovery, do not add manager to active or suspended resource maps.
+    // The xaresources have already been ended with TMSUCCESS.
+    public TransactionBranch addBranchXid(XAResource xaRes, Xid branchId) {
         TransactionBranch manager = new TransactionBranch(xaRes, branchId);
         resourceManagers.add(manager);
-        xaResources.put(xaRes, manager);
+        return manager;
     }
 
     private static class TransactionBranch implements TransactionBranchInfo {

Modified: geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/MockResource.java
==============================================================================
--- geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/MockResource.java
(original)
+++ geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/MockResource.java
Tue Oct 19 13:35:46 2004
@@ -25,19 +25,19 @@
 import javax.transaction.xa.Xid;
 
 /**
- *
- *
  * @version $Rev$ $Date$
  */
 public class MockResource implements NamedXAResource {
     private String xaResourceName = "mockResource";
-    private Xid xid;
+    private Xid currentXid;
     private MockResourceManager manager;
     private int timeout = 0;
     private boolean prepared;
     private boolean committed;
     private boolean rolledback;
     private Set preparedXids = new HashSet();
+    private Set knownXids = new HashSet();
+    private Set finishedXids = new HashSet();//end was called with TMSUCCESS or TMFAIL
 
     public MockResource(MockResourceManager manager, String xaResourceName) {
         this.manager = manager;
@@ -52,12 +52,18 @@
         return false;
     }
 
-    public Xid getXid() {
-        return xid;
+    public Xid getCurrentXid() {
+        return currentXid;
     }
 
     public void start(Xid xid, int flags) throws XAException {
-        if (this.xid != null) {
+        if (this.currentXid != null) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
+        if (flags == XAResource.TMRESUME && !knownXids.contains(xid)) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
+        if (finishedXids.contains(xid)) {
             throw new XAException(XAException.XAER_PROTO);
         }
         if ((flags & XAResource.TMJOIN) != 0) {
@@ -65,28 +71,52 @@
         } else {
             manager.newTx(xid, this);
         }
-        this.xid = xid;
+        this.currentXid = xid;
+        if (!knownXids.contains(xid)) {
+            knownXids.add(xid);
+        }
     }
 
     public void end(Xid xid, int flags) throws XAException {
-        if (this.xid != xid) {
-            throw new XAException(XAException.XAER_INVAL);
+        if (!knownXids.contains(xid)) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
+        if (flags == XAResource.TMSUSPEND) {
+            if (currentXid == null) {
+                throw new XAException(XAException.XAER_PROTO);
+            } else if (this.currentXid != xid) {
+                throw new XAException(XAException.XAER_PROTO);
+            }
+        } else if (flags == XAResource.TMFAIL || flags == XAResource.TMSUCCESS) {
+            if (finishedXids.contains(xid)) {
+                throw new XAException(XAException.XAER_PROTO);
+            }
+            finishedXids.add(xid);
         }
-        this.xid = null;
+        this.currentXid = null;
     }
 
     public int prepare(Xid xid) throws XAException {
+        if (!finishedXids.contains(xid)) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
         prepared = true;
         preparedXids.add(xid);
         return XAResource.XA_OK;
     }
 
     public void commit(Xid xid, boolean onePhase) throws XAException {
+        if (!finishedXids.contains(xid)) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
         preparedXids.remove(xid);
         committed = true;
     }
 
     public void rollback(Xid xid) throws XAException {
+        if (!finishedXids.contains(xid)) {
+            throw new XAException(XAException.XAER_PROTO);
+        }
         rolledback = true;
         preparedXids.remove(xid);
         manager.forget(xid, this);

Added: geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/ProtocolTest.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/ProtocolTest.java
Tue Oct 19 13:35:46 2004
@@ -0,0 +1,68 @@
+package org.apache.geronimo.transaction.manager;
+
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAResource;
+
+import junit.framework.TestCase;
+import org.apache.geronimo.transaction.log.UnrecoverableLog;
+
+/**
+ */
+public class ProtocolTest extends TestCase {
+
+    XidFactory xidFactory = new XidFactoryImpl("test".getBytes());
+    TransactionManagerImpl tm;
+    MockResourceManager mrm1, mrm2;
+    MockResource mr11, mr12, mr21, mr22;
+
+    protected void setUp() throws Exception {
+        tm = new TransactionManagerImpl(10, new UnrecoverableLog(), xidFactory);
+        mrm1 = new MockResourceManager(true);
+        mrm2 = new MockResourceManager(true);
+        mr11 = new MockResource(mrm1, "mr11");
+        mr12 = new MockResource(mrm1, "mr12");
+        mr21 = new MockResource(mrm2, "mr21");
+        mr22 = new MockResource(mrm2, "mr22");
+    }
+
+    public void testOnePhaseCommit() throws Exception {
+        tm.begin();
+        Transaction tx = tm.getTransaction();
+        tx.enlistResource(mr11);
+        tx.delistResource(mr11, XAResource.TMSUSPEND);
+        tm.commit();
+    }
+
+    public void testOnePhaseCommiTwoResources() throws Exception {
+        tm.begin();
+        Transaction tx = tm.getTransaction();
+        tx.enlistResource(mr11);
+        tx.delistResource(mr11, XAResource.TMSUSPEND);
+        tx.enlistResource(mr12);
+        tx.delistResource(mr12, XAResource.TMSUSPEND);
+        tm.commit();
+    }
+    public void testTwoPhaseCommit() throws Exception {
+        tm.begin();
+        Transaction tx = tm.getTransaction();
+        tx.enlistResource(mr11);
+        tx.delistResource(mr11, XAResource.TMSUSPEND);
+        tx.enlistResource(mr21);
+        tx.delistResource(mr21, XAResource.TMSUSPEND);
+        tm.commit();
+    }
+    public void testTwoPhaseCommit4Resources() throws Exception {
+        tm.begin();
+        Transaction tx = tm.getTransaction();
+        tx.enlistResource(mr11);
+        tx.delistResource(mr11, XAResource.TMSUSPEND);
+        tx.enlistResource(mr12);
+        tx.delistResource(mr12, XAResource.TMSUSPEND);
+        tx.enlistResource(mr21);
+        tx.delistResource(mr21, XAResource.TMSUSPEND);
+        tx.enlistResource(mr22);
+        tx.delistResource(mr22, XAResource.TMSUSPEND);
+        tm.commit();
+    }
+
+}

Modified: geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/TestTransactionManager.java
==============================================================================
--- geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/TestTransactionManager.java
(original)
+++ geronimo/trunk/modules/transaction/src/test/org/apache/geronimo/transaction/manager/TestTransactionManager.java
Tue Oct 19 13:35:46 2004
@@ -97,18 +97,18 @@
         MockResource res1 = rm1.getResource("rm1");
         tm.begin();
         tx = tm.getTransaction();
-        assertNull(res1.getXid());
+        assertNull(res1.getCurrentXid());
         assertTrue(tx.enlistResource(res1));
-        assertNotNull(res1.getXid());
+        assertNotNull(res1.getCurrentXid());
         assertTrue(tx.delistResource(res1, XAResource.TMFAIL));
-        assertNull(res1.getXid());
+        assertNull(res1.getCurrentXid());
         tm.rollback();
 
         tm.begin();
         tx = tm.getTransaction();
         assertTrue(tx.enlistResource(res1));
         tm.rollback();
-        assertNull(res1.getXid());
+        assertNull(res1.getCurrentXid());
     }
 
     protected void setUp() throws Exception {

Mime
View raw message