[Zodb-checkins] CVS: ZODB4/BDBStorage - BDBFullStorage.py:2.3

Barry Warsaw barry@wooz.org
Mon, 16 Dec 2002 16:00:13 -0500


Update of /cvs-repository/ZODB4/BDBStorage
In directory cvs.zope.org:/tmp/cvs-serv6050

Modified Files:
	BDBFullStorage.py 
Log Message:
_dostore(): Fix the VersionLockError to the constructor interface used
in zodb4.

_dorestore(): Forward porting fix from zodb3, namely that if prev_txn
points to a non-existant transaction, just ignore it.


=== ZODB4/BDBStorage/BDBFullStorage.py 2.2 => 2.3 ===
--- ZODB4/BDBStorage/BDBFullStorage.py:2.2	Fri Dec  6 15:41:30 2002
+++ ZODB4/BDBStorage/BDBFullStorage.py	Mon Dec 16 16:00:12 2002
@@ -498,11 +498,11 @@
                 if version:
                     nvrevid = orevid
             elif ovid <> vid:
+                # Figure out the version name for the exception
+                oversion = self._versions[ovid]
                 # We're trying to make a change on a version that's different
                 # than the version the current revision is on.  Nuh uh.
-                raise POSException.VersionLockError(
-                    'version mismatch for object %s (was: %s, got: %s)' %
-                    tuple(map(u64, (oid, ovid, vid))))
+                raise POSException.VersionLockError(oid, oversion)
             else:
                 # We're making another change to this object on this version.
                 # The non-version revid is the same as for the previous
@@ -562,20 +562,28 @@
         # Get the metadata for the previous revision, so that we can dig out
         # the non-version revid, but only if there /is/ a previous revision
         if prevrevid <> ZERO:
-            ovid, onvrevid = unpack(
-                '>8s8s', self._metadata[oid+prevrevid][:16])
-            if ovid == ZERO:
-                # The last revision of this object was made on the
-                # non-version, we don't care where the current change is
-                # made.  But if we're storing this change on a version then
-                # the non-version revid will be the previous revid
-                if version:
-                    nvrevid = prevrevid
+            try:
+                ovid, onvrevid = unpack(
+                    '>8s8s', self._metadata[oid+prevrevid][:16])
+            except KeyError:
+                # prev_txn is just a hint.  If the transaction it points to
+                # does not exist, perhaps because it's been packed away, just
+                # ignore it.  Also, check to see if the data matches.  If
+                # not...
+                prevrevid = ZERO
             else:
-                # We're making another change to this object on this version.
-                # The non-version revid is the same as for the previous
-                # revision of the object.
-                nvrevid = onvrevid
+                if ovid == ZERO:
+                    # The last revision of this object was made on the
+                    # non-version, we don't care where the current change is
+                    # made.  But if we're storing this change on a version
+                    # then the non-version revid will be the previous revid
+                    if version:
+                        nvrevid = prevrevid
+                else:
+                    # We're making another change to this object on this
+                    # version.  The non-version revid is the same as for the
+                    # previous revision of the object.
+                    nvrevid = onvrevid
         # Check for George Bailey Events
         if data is None:
             lrevid = DNE
@@ -616,8 +624,14 @@
         # - data can be None, which indicates a George Bailey object
         #   (i.e. one who's creation has been transactionally undone).
         #
-        # If prev_txn is not None, it should contain the same data as
-        # the argument data.  If it does, write a backpointer to it.
+        # prev_txn is a backpointer.  In the original database, it's possible
+        # that the data was actually living in a previous transaction.  This
+        # can happen for transactional undo and other operations, and is used
+        # as a space saving optimization.  Under some circumstances the
+        # prev_txn may not actually exist in the target database (i.e. self)
+        # for example, if it's been packed away.  In that case, the prev_txn
+        # should be considered just a hint, and is ignored if the transaction
+        # doesn't exist.
         if transaction is not self._transaction:
             raise POSException.StorageTransactionError(self, transaction)
         self._lock_acquire()