[Zodb-checkins] CVS: ZODB4/Transaction - Manager.py:1.3 Transaction.py:1.4

Jeremy Hylton jeremy@zope.com
Wed, 11 Dec 2002 14:48:35 -0500


Update of /cvs-repository/ZODB4/Transaction
In directory cvs.zope.org:/tmp/cvs-serv17509/Transaction

Modified Files:
	Manager.py Transaction.py 
Log Message:
Fix suddenly appearing transaction errors in MTStorage.

There were assertion errors and complaints about a dict resizing
during iteration.  There are two fixes:

- Make it illegal to join a txn once 2PC begins.
- Add a Failed state and mark a txn as failed if an error occurs
  during prepare.  It is legal to abort a failed transaction.

XXX Maybe Failed is the wrong word.


=== ZODB4/Transaction/Manager.py 1.2 => 1.3 ===
--- ZODB4/Transaction/Manager.py:1.2	Mon Oct  7 19:25:43 2002
+++ ZODB4/Transaction/Manager.py	Wed Dec 11 14:48:34 2002
@@ -22,12 +22,18 @@
 
     def commit(self, txn):
         assert txn._status is Status.ACTIVE
+        txn._status = Status.PREPARING
         prepare_ok = True
         zLOG.LOG("txn", zLOG.DEBUG, "%s: prepare" % txn)
-        for r in txn._resources:
-            if prepare_ok and not r.prepare(txn):
-                prepare_ok = False
+        try:
+            for r in txn._resources:
+                if prepare_ok and not r.prepare(txn):
+                    prepare_ok = False
+        except:
+            txn._status = Status.FAILED
+            raise
         txn._status = Status.PREPARED
+        # XXX An error below is intolerable.  What state to use?
         if prepare_ok:
             self._commit(txn)
         else:
@@ -42,7 +48,8 @@
 
     def abort(self, txn):
         zLOG.LOG("txn", zLOG.DEBUG, "%s: abort" % txn)
-        assert txn._status in (Status.ACTIVE, Status.PREPARED)
+        assert txn._status in (Status.ACTIVE, Status.PREPARED, Status.FAILED)
+        txn._status = Status.PREPARING
         for r in txn._resources:
             r.abort(txn)
         txn._status = Status.ABORTED


=== ZODB4/Transaction/Transaction.py 1.3 => 1.4 ===
--- ZODB4/Transaction/Transaction.py:1.3	Fri Nov 15 16:42:09 2002
+++ ZODB4/Transaction/Transaction.py	Wed Dec 11 14:48:34 2002
@@ -4,6 +4,7 @@
 __metaclass__ = type
 
 from ITransaction import ITransaction
+from Exceptions import TransactionError
 
 class Set(dict):
 
@@ -13,8 +14,11 @@
 class Status:
 
     ACTIVE = "Active"
+    PREPARING = "Preparing"
     PREPARED = "Prepared"
+    FAILED = "Failed"
     COMMITTED = "Committed"
+    ABORTING = "Aborting"
     ABORTED = "Aborted"
 
 class Transaction:
@@ -58,6 +62,9 @@
     def join(self, resource):
         """resource is participating in the transaction."""
         assert self._manager is not None
+        if self._status != Status.ACTIVE:
+            raise TransactionError("Can't join transaction. Status=%s" %
+                                   self._status)
         self._resources.add(resource)
 
     def status(self):