[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):