[Zodb-checkins] CVS: ZODB4/src/zodb/storage - bdbfull.py:1.12.4.3

Barry Warsaw barry@wooz.org
Wed, 12 Mar 2003 12:25:23 -0500


Update of /cvs-repository/ZODB4/src/zodb/storage
In directory cvs.zope.org:/tmp/cvs-serv10406

Modified Files:
      Tag: opaque-pickles-branch
	bdbfull.py 
Log Message:
Rename the table from _referents to _references for consistency.

Rename _dotxnundo() to _doundo() since transactional undo is the only
kind there is now.

_undo_current_tid(): Return the references record as the 4th element.
Here it'll always be None (since data is also always None), but...

_undo_to_same_pickle(): ...here it will be the references string when
data is returned from conflict resolution.  We need to fix the api for
conflict resolution to return the references as well.  Later.

_doundo(): When storing data, we also need to store the references.
Otherwise assert that whenever data is None, refs are also None.

_loadSerialEx(): The references we want must match th data we're
returning, so that's oid+lrevid, not oid+serial.  Usually they're the
same, but they're not in the face of backpointers.  If there are no
references at that revision, return the empty list, otherwise we need
to splitrefs() the string.


=== ZODB4/src/zodb/storage/bdbfull.py 1.12.4.2 => 1.12.4.3 ===
--- ZODB4/src/zodb/storage/bdbfull.py:1.12.4.2	Mon Mar 10 14:36:23 2003
+++ ZODB4/src/zodb/storage/bdbfull.py	Wed Mar 12 12:25:23 2003
@@ -108,7 +108,7 @@
         #     object, so it is never decremented except at pack time.  When it
         #     goes to zero, the object is automatically deleted.
         #
-        # referents -- {oid+tid -> oid+oid+...}
+        # references -- {oid+tid -> oid+oid+...}
         #     For each revision of the object, these are the oids of the
         #     objects referred to in the data record, as a list of 8-byte
         #     oids, concatenated together.
@@ -338,8 +338,8 @@
                 vid = self._metadata[revid][:8]
                 self._metadata.delete(revid, txn=txn)
                 self._pickles.delete(revid, txn=txn)
-                if self._referents.has_key(revid):
-                    self._referents.delete(revid, txn=txn)
+                if self._references.has_key(revid):
+                    self._references.delete(revid, txn=txn)
                 # Clean up the object revisions table
                 try:
                     cr.set(oid+tid)
@@ -416,9 +416,9 @@
                 # for the George Bailey Event, which has no pickle.
                 if lrevid <> DNE:
                     revid = oid + lrevid
-                    referents = self._referents.get(revid, txn=txn)
-                    if referents:
-                        self._update(deltas, referents, 1)
+                    references = self._references.get(revid, txn=txn)
+                    if references:
+                        self._update(deltas, references, 1)
                     # Incref this pickle; there's a new revision pointing to it
                     refcount = self._pickleRefcounts.get(revid, ZERO, txn=txn)
                     self._pickleRefcounts.put(revid, incr(refcount, 1),
@@ -444,7 +444,7 @@
             # if co.close() were to fail.  In practice this shouldn't happen.
             if co: co.close()
             if cs: cs.close()
-        # Now incref all referents
+        # Now incref all references
         for oid, delta in deltas.items():
             refcount = self._refcounts.get(oid, ZERO, txn=txn)
             self._refcounts.put(oid, incr(refcount, delta), txn=txn)
@@ -543,11 +543,11 @@
         newserial = self._serial
         revid = oid + newserial
         self._serials.put(oid, newserial, txn=txn)
-        # Store object referents, but only if the list is non-empty
+        # Store object references, but only if the list is non-empty
         if refs:
-            referents = EMPTYSTRING.join(refs)
-            assert len(referents) % 8 == 0
-            self._referents.put(revid, referents, txn=txn)
+            references = EMPTYSTRING.join(refs)
+            assert len(references) % 8 == 0
+            self._references.put(revid, references, txn=txn)
         self._pickles.put(revid, data, txn=txn)
         self._metadata.put(revid, vid+nvrevid+newserial+oserial, txn=txn)
         self._txnoids.put(newserial, oid, txn=txn)
@@ -637,7 +637,7 @@
         # Update the rest of the tables
         self._metadata.put(revid, vid+nvrevid+lrevid+prevrevid, txn=txn)
         if refs:
-            self._referents.put(revid, EMPTYSTRING.join(refs), txn=txn)
+            self._references.put(revid, EMPTYSTRING.join(refs), txn=txn)
         self._txnoids.put(tid, oid, txn=txn)
         self._oids.put(oid, PRESENT, txn=txn)
         if vid <> ZERO:
@@ -1049,7 +1049,7 @@
                 # the iterator code, so that it can pass this information on.
                 backpointer = lrevid
             # Also return the list of oids referred to by this object
-            refs = self._referents.get(revid)
+            refs = self._references.get(oid+lrevid)
             if refs is None:
                 refs = []
             else:
@@ -1083,6 +1083,9 @@
     #
 
     def _undo_current_tid(self, oid, ctid):
+        # Returns (oid, metadata record, None, None).  The last two represent
+        # the data and the references, both of which will always be None
+        # because there's no conflict resolution necessary.
         vid, nvrevid, lrevid, prevrevid = unpack(
             '>8s8s8s8s', self._metadata[oid+ctid])
         # We can always undo the last transaction.  The prevrevid pointer
@@ -1099,7 +1102,7 @@
                 # conditions: either we're undoing the creation of the object,
                 # or the object creation transaction has been packed away.
                 # Checking the current record's prevrevid will tell us.
-                return oid, vid+nvrevid+DNE+ctid, None
+                return oid, vid+nvrevid+DNE+ctid, None, None
             # BAW: If the serial number of this object record is the same as
             # the serial we're being asked to undo, then I think we have a
             # problem (since the storage invariant is that it doesn't retain
@@ -1107,11 +1110,15 @@
             # same transaction).
             assert mrec[0][8:] <> ctid, 'storage invariant violated'
             # All is good, so just restore this metadata record
-            return oid, mrec[1], None
+            return oid, mrec[1], None, None
         finally:
             mdc.close()
 
     def _undo_to_same_pickle(self, oid, tid, ctid):
+        # Returns (oid, metadata record, data, refs).  Data and refs will both
+        # always be None unless conflict resolution was necessary and
+        # succeeded.
+        #
         # We need to compare the lrevid (pickle pointers) of the transaction
         # previous to the current one, and the transaction previous to the one
         # we want to undo.  If their lrevids are the same, it's undoable
@@ -1123,7 +1130,7 @@
             # from there is the zombification of the object, i.e. the last
             # transaction for this object.
             vid, nvrevid = unpack('>8s8s', self._metadata[oid+tid][:16])
-            return oid, vid+nvrevid+DNE+ctid, None
+            return oid, vid+nvrevid+DNE+ctid, None, None
         elif target_prevrevid == ZERO or last_prevrevid == ZERO:
             # The object's revision is in it's initial creation state but
             # we're asking for an undo of something other than the initial
@@ -1137,20 +1144,23 @@
         # undone.  Note that we take a short cut here, since we really want to
         # test pickle equality, but this is good enough for now.
         if target_lrevid == last_lrevid:
-            return oid, target_metadata, None
+            return oid, target_metadata, None, None
         # Check previous transactionalUndos done in this transaction
         elif target_lrevid == self._prevrevids.get(oid):
-            return oid, target_metadata, None
+            return oid, target_metadata, None, None
         else:
             # Attempt application level conflict resolution
             try:
+                # XXX this needs to be converted to opaque pickles
                 data = self.resolveConflict(
                     oid, ctid, tid, self._pickles[oid+target_lrevid])
+                from zodb.serialize import findrefs
+                refs = ''.join(findrefs(data))
             except ConflictError:
                 raise UndoError, 'Cannot undo transaction'
-            return oid, target_metadata, data
+            return oid, target_metadata, data, refs
 
-    def _dotxnundo(self, txn, tid):
+    def _doundo(self, txn, tid):
         # First, make sure the transaction isn't protected by a pack.
         packtime = self._last_packtime()
         if tid <= packtime:
@@ -1180,7 +1190,7 @@
         # about to undo, and everything looks good.  So now we'll write the
         # new metadata records (and potentially new pickle records).
         rtnoids = {}
-        for oid, metadata, data in newrevs:
+        for oid, metadata, data, refs in newrevs:
             newserial = self._serial
             revid = oid + self._serial
             # If the data pickle is None, then this undo is simply
@@ -1190,8 +1200,14 @@
             # store the new pickle data and calculate the new lrevid.
             vid, nvrevid, ign, prevrevid = unpack('>8s8s8s8s', metadata)
             if data is not None:
+                # data and refs go hand in hand
+                assert refs is not None
                 self._pickles.put(revid, data, txn=txn)
+                self._references.put(revid, refs, txn=txn)
                 metadata = vid+nvrevid+newserial+prevrevid
+            else:
+                # data and refs go hand in hand
+                assert refs is None
             # We need to write all the new records for an object changing in
             # this transaction.  Note that we only write to th serials table
             # if prevrevids hasn't already seen this object, otherwise we'll
@@ -1217,7 +1233,7 @@
             raise StorageTransactionError(self, transaction)
         self._lock_acquire()
         try:
-            return self._withtxn(self._dotxnundo, tid)
+            return self._withtxn(self._doundo, tid)
         finally:
             self._lock_release()
 
@@ -1430,8 +1446,8 @@
                     if self._metadata.has_key(orevid):
                         metadata = self._metadata[orevid]
                         self._metadata.delete(orevid, txn=txn)
-                        if self._referents.has_key(orevid):
-                            self._referents.delete(orevid, txn=txn)
+                        if self._references.has_key(orevid):
+                            self._references.delete(orevid, txn=txn)
                         # Decref the pickle
                         self._decrefPickle(oid, metadata[16:24], txn)
                     try:
@@ -1464,10 +1480,10 @@
             self._pickleRefcounts.delete(revid, txn=txn)
             self._pickles.delete(revid, txn=txn)
             # And decref all objects pointed to by this pickle
-            referents = self._referents.get(revid, txn=txn)
-            if referents:
+            references = self._references.get(revid, txn=txn)
+            if references:
                 deltas = {}
-                self._update(deltas, referents, -1)
+                self._update(deltas, references, -1)
                 self._decref(deltas, txn)
         else:
             self._pickleRefcounts.put(revid, p64(refcount), txn=txn)
@@ -1605,9 +1621,9 @@
                     data = self._pickles[oid+lrevid]
                     # Now get the oids of all the objects referenced by this
                     # object revision
-                    referents = self._referents.get(oid+lrevid)
-                    if referents:
-                        for oid in splitrefs(referents):
+                    references = self._references.get(oid+lrevid)
+                    if references:
+                        for oid in splitrefs(references):
                             self._oidqueue.append(oid, txn)
             # Pop the next oid off the queue and do it all again
             rec = self._oidqueue.consume(txn)