[Zodb-checkins] CVS: Zope3/lib/python/ZODB - DB.py:1.57

Jeremy Hylton jeremy@zope.com
Wed, 4 Dec 2002 16:50:10 -0500

Update of /cvs-repository/Zope3/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv17589/lib/python/ZODB

Modified Files:
Log Message:
Fix all sorts of gratuitous errors in undo and versions calls.

Fix SimpleDataManager's prepare() method to return True if tpc_vote()
doesn't raise an exception.  tpc_vote() has no return value, so this
code could never have voted yes.

Add an _prepare() hook that is called between the tpc_begin() and the
tpc_vote().  Subclasses can use the hook to do real work during 2PC.

The abort() and commit() methods must actually call tpc_abort() and
tpc_finish() on the storage to commit the transaction.  Subclasses
must be sure to call this method if they override abort() or finish().

In subclasses for undo and versions, move the real work to _prepare().

=== Zope3/lib/python/ZODB/DB.py 1.56 => 1.57 ===
--- Zope3/lib/python/ZODB/DB.py:1.56	Tue Dec  3 12:24:12 2002
+++ Zope3/lib/python/ZODB/DB.py	Wed Dec  4 16:50:09 2002
@@ -16,21 +16,23 @@
+__metaclass__ = type
 import cPickle, cStringIO, sys
-import POSException
-from Connection import Connection
 from threading import Lock
 from time import time, ctime
-from zLOG import LOG, ERROR
+from types import StringType
+from ZODB import POSException
+from ZODB.Connection import Connection
 from ZODB.Serialize import getDBRoot
 from ZODB.ZTransaction import Transaction
 from ZODB.utils import z64
-from Transaction import get_transaction
+from zLOG import LOG, ERROR, BLATHER
+from Transaction import get_transaction
 from Transaction.IDataManager import IDataManager
-from types import StringType
 class DB:
     """The Object Database
@@ -161,7 +163,7 @@
         # Notify connections
         for cc in self._allocated:
             if cc is not connection:
-                self.invalidateConnection(cc, version, oid)
+                self.invalidateConnection(cc, oid, version)
         if self._temps:
             # t accumulates all the connections that aren't closed.
@@ -317,15 +319,23 @@
     def prepare(self, txn):
-        if self._storage.tpc_vote(txn):
-            return True
-        else:
+        try:
+            self._prepare(txn)
+            self._storage.tpc_vote(txn)
+        except POSException.StorageError, err:
+            LOG("DB", BLATHER, "Error during prepare: %s" % err)
             return False
+        else:
+            return True
     def abort(self, txn):
-        pass
+        self._storage.tpc_abort(txn)
     def commit(self, txn):
+        self._storage.tpc_finish(txn)
+    def _prepare(self, txn):
+        # Hook for clients to perform action during 2PC
 class CommitVersion(SimpleDataManager):
@@ -336,36 +346,46 @@
         self._version = version
         self._dest = dest
+    def _prepare(self, txn):
+        self._oids = self._storage.commitVersion(self._version, self._dest,
+                                                 txn)
     def commit(self, txn):
-        oids = db._storage.commitVersion(self._version, dest, txn)
-        for oid in oids:
+        super(CommitVersion, self).commit(txn)
+        for oid in self._oids:
             self._db.invalidate(oid, version=self._dest)
         if self._dest:
             # the code above just invalidated the dest version.
             # now we need to invalidate the source!
-            for oid in oids:
+            for oid in self._oids:
                 self._db.invalidate(oid, version=self._version)
 class AbortVersion(SimpleDataManager):
     """An object that will see to version abortion."""
     def __init__(self, db, version):
-        super(CommitVersion, self).__init__(db)
+        super(AbortVersion, self).__init__(db)
         self._version = version
+    def _prepare(self, txn):
+        self._oids = self._storage.abortVersion(self._version, txn)
     def commit(self, txn):
-        oids = self._db._storage.abortVersion(version, txn)
-        for oid in oids:
+        super(AbortVersion, self).commit(txn)
+        for oid in self._oids:
             self._db.invalidate(oid, version=self._version)
 class TransactionalUndo(SimpleDataManager):
     """An object that will see to transactional undo."""
     def __init__(self, db, tid):
-        super(CommitVersion, self).__init__(db)
+        super(TransactionalUndo, self).__init__(db)
         self._tid = tid
+    def _prepare(self, txn):
+        self._oids = self._storage.transactionalUndo(self._tid, txn)
-    def commit(self, reallyme, t):
-        oids = self._db._storage.transactionalUndo(self._tid, t)
-        for oid in oids:
+    def commit(self, txn):
+        super(TransactionalUndo, self).commit(txn)
+        for oid in self._oids: