[Zope-Checkins] CVS: StandaloneZODB/ZODB - BaseStorage.py:1.17.4.1

Barry Warsaw barry@wooz.org
Wed, 23 Jan 2002 16:40:26 -0500


Update of /cvs-repository/StandaloneZODB/ZODB
In directory cvs.zope.org:/tmp/cvs-serv12050

Modified Files:
      Tag: Recovery
	BaseStorage.py 
Log Message:
copyTransactionsFrom(): This method is broken when copying
transactions that span commitVersion(), abortVersion() or
transactionalUndo(), because these three methods make updates to the
database that cannot be mimicked with a store() call.

We're defining a new API method called recover() that looks a lot like
store() but which has some important differences:

- The `serial' argument to recover() names the serial number of the
  /current/ object revision, not the previous one.

- recover() skips various consistency checks that store() performs,
  including the checks for ConflictError and VersionLockError.  Thus
  it believes the data its given, which /must/ be known to be accurate
  (or you could end up corrupting your storage).  Also, it ought to be
  a bit faster since it does less work than store().

- recover() doesn't return anything.

So, when the concrete storage implements the recover() API -- i.e. it
has a `recover' attribute -- copyTransactionsFrom() will use that
instead of store() to copy the transactions.  It will still fall back
to using store() if recover() is unavailable, but then ConflictErrors
or VersionLockErrors may be raised.


=== StandaloneZODB/ZODB/BaseStorage.py 1.17 => 1.17.4.1 ===
         _ts=None
         ok=1
-        preindex={}; preget=preindex.get   # waaaa
+        preindex={};
+        preget=preindex.get   # waaaa
+        # recover() is a new storage API method which has an identical
+        # signature to store() except that it does not return anything.
+        # Semantically, recover() is also identical to store() except that it
+        # doesn't do the ConflictError or VersionLockError consistency
+        # checks.  The reason to use recover() over store() in this method is
+        # that store() cannot be used to copy transactions spanning a version
+        # commit or abort, or over transactional undos.
+        #
+        # We'll use recover() if it's available, otherwise we'll fall back to
+        # using store().  However, if we use store, then
+        # copyTransactionsFrom() may fail with VersionLockError or
+        # ConflictError.
+        if hasattr(self, 'recover'):
+            recovering = 1
+        else:
+            recovering = 0
         for transaction in other.iterator():
             
             tid=transaction.tid
@@ -252,9 +269,12 @@
             for r in transaction:
                 oid=r.oid
                 if verbose: print `oid`, r.version, len(r.data)
-                pre=preget(oid, None)
-                s=self.store(oid, pre, r.data, r.version, transaction)
-                preindex[oid]=s
+                if recovering:
+                    self.recover(oid, r.serial, r.data, r.version, transaction)
+                else:
+                    pre=preget(oid, None)
+                    s=self.store(oid, pre, r.data, r.version, transaction)
+                    preindex[oid]=s
                 
             self.tpc_vote(transaction)
             self.tpc_finish(transaction)