[Zope-Checkins] CVS: ZODB3/BDBStorage - BDBFullStorage.py:1.75.2.7 BDBMinimalStorage.py:1.32.2.1

Jeremy Hylton cvs-admin at zope.org
Tue Dec 2 02:11:00 EST 2003


Update of /cvs-repository/ZODB3/BDBStorage
In directory cvs.zope.org:/tmp/cvs-serv24432/BDBStorage

Modified Files:
      Tag: ZODB3-mvcc-2-branch
	BDBFullStorage.py BDBMinimalStorage.py 
Log Message:
First cut at removal of serial numbers.
Rename loadNonCurrent() to loadBefore() (Jim's suggestion).

A few tests fail, but it's close enough to share the code with Tim.

In all case, the _p_serial attribute of a Persistent object matches
the id of the transaction that wrote the current revision.  Within the
storage API, we eliminate the abortVersion case where the txn id is
greater than the serial number.

Rename as many variables and attributes from serial to tid, with the
exception of store() and restore() arguments.  They're being passed in
from a client, which is getting the value from _p_serial; it makes
some sense there.

When tid and serial were both returned, eliminate serial and just use
tid.  

Replace "serial" with "tid" in some methods names, but not all.  I'll
get to the rest tomorrow.  The remaining ones are just used a lot.

Add XXX comment about now-bogus ZEO protocol that passes identical
serialnos for every object committed.


=== ZODB3/BDBStorage/BDBFullStorage.py 1.75.2.6 => 1.75.2.7 ===
--- ZODB3/BDBStorage/BDBFullStorage.py:1.75.2.6	Mon Dec  1 10:16:07 2003
+++ ZODB3/BDBStorage/BDBFullStorage.py	Tue Dec  2 02:10:29 2003
@@ -59,18 +59,11 @@
         #
         # The Full storage uses the following tables:
         #
-        # serials -- {oid -> [serial | serial+tid]}
-        #     Maps oids to serial numbers, to make it easy to look up the
-        #     serial number for the current revision of the object.  The value
+        # serials -- {oid -> [tid]}
+        #     Maps oids to txn ids, to make it easy to look up the
+        #     txn id for the current revision of the object.  The value
         #     combined with the oid provides a revision id (revid) which is
-        #     used to point into the other tables.  Usually the serial is the
-        #     tid of the transaction that modified the object, except in the
-        #     case of abortVersion().  Here, the serial number of the object
-        #     won't change (by definition), but of course the abortVersion()
-        #     happens in a new transaction so the tid pointer must change.  To
-        #     handle this rare case, the value in the serials table can be a
-        #     16-byte value, in which case it will contain both the serial
-        #     number and the tid pointer.
+        #     used to point into the other tables.
         #
         # metadata -- {oid+tid -> vid+nvrevid+lrevid+previd}
         #     Maps object revisions to object metadata.  This mapping is used
@@ -385,7 +378,7 @@
         self._withtxn(self._doabort, tid)
 
     def _docommit(self, txn, tid):
-        self._pending.put(self._serial, COMMIT, txn)
+        self._pending.put(self._tid, COMMIT, txn)
         # Almost all the data's already written by now so we don't need to do
         # much more than update reference counts.  Even there, our work is
         # easy because we're not going to decref anything here.
@@ -399,7 +392,7 @@
                 oid = rec[0]
                 rec = co.next()
                 # Get the pointer to the live pickle data for this revision
-                metadata = self._metadata[oid + self._serial]
+                metadata = self._metadata[oid + self._tid]
                 lrevid = unpack('>8s', metadata[16:24])[0]
                 # Incref all objects referenced by this pickle, but watch out
                 # for the George Bailey Event, which has no pickle.
@@ -457,10 +450,10 @@
         self._txnMetadata.put(tid, data, txn=txn)
 
     def _begin(self, tid, u, d, e):
-        self._withtxn(self._dobegin, self._serial, u, d, e)
+        self._withtxn(self._dobegin, self._tid, u, d, e)
 
     def _finish(self, tid, u, d, e):
-        self._withtxn(self._docommit, self._serial)
+        self._withtxn(self._docommit, self._tid)
         self._ltid = tid
 
     #
@@ -475,20 +468,20 @@
         # a single transaction.  It's not clear though under what
         # situations that can occur or what the semantics ought to be.
         # For now, we'll assume this doesn't happen.
-        oserial, orevid = self._getSerialAndTidMissingOk(oid)
-        if oserial is None:
+        prev = tid = self._getTidMissingOk(oid)
+        if tid is None:
             # There's never been a previous revision of this object.
-            oserial = ZERO
-        elif serial <> oserial:
+            prev = ZERO
+        elif serial != tid:
             # The object exists in the database, but the serial number
             # given in the call is not the same as the last stored serial
             # number.  First, attempt application level conflict
             # resolution, and if that fails, raise a ConflictError.
-            data = self.tryToResolveConflict(oid, oserial, serial, data)
+            data = self.tryToResolveConflict(oid, tid, serial, data)
             if data:
                 conflictresolved = True
             else:
-                raise POSException.ConflictError(serials=(oserial, serial))
+                raise POSException.ConflictError(serials=(tid, serial))
         # Do we already know about this version?  If not, we need to record
         # the fact that a new version is being created.  version will be the
         # empty string when the transaction is storing on the non-version
@@ -499,8 +492,8 @@
         # the object.  We need to get the tid of the previous transaction to
         # modify this object.  If that transaction is in a version, it must
         # be the same version as we're making this change in now.
-        if orevid:
-            rec = self._metadata[oid+orevid]
+        if tid:
+            rec = self._metadata[oid + prev]
             ovid, onvrevid = unpack('>8s8s', rec[:16])
             if ovid == ZERO:
                 # The last revision of this object was made on the
@@ -508,8 +501,8 @@
                 # made.  But if we're storing this change on a version then
                 # the non-version revid will be the previous revid
                 if version:
-                    nvrevid = orevid
-            elif ovid <> vid:
+                    nvrevid = prev
+            elif ovid != vid:
                 # 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(
@@ -521,16 +514,16 @@
                 # revision of the object.
                 nvrevid = onvrevid
         # Now optimistically store data to all the tables
-        newserial = self._serial
+        newserial = self._tid
         revid = oid + newserial
         self._serials.put(oid, newserial, txn=txn)
         self._pickles.put(revid, data, txn=txn)
-        self._metadata.put(revid, vid+nvrevid+newserial+oserial, txn=txn)
+        self._metadata.put(revid, vid+nvrevid+newserial+prev, txn=txn)
         self._txnoids.put(newserial, oid, txn=txn)
         # Update the object revisions table, but only if this store isn't
         # the first one of this object in a new version.
         if not version or ovid <> ZERO:
-            self._objrevs.put(newserial+oid, oserial, txn=txn)
+            self._objrevs.put(newserial+oid, prev, txn=txn)
         # Update the log tables
         self._oids.put(oid, PRESENT, txn=txn)
         if vid <> ZERO:
@@ -554,10 +547,10 @@
             self._lock_release()
 
     def _dorestore(self, txn, oid, serial, data, version, prev_txn):
-        tid = self._serial
+        tid = self._tid
         vid = nvrevid = ovid = ZERO
         prevrevid = prev_txn
-        # self._serial contains the transaction id as set by
+        # self._tid contains the transaction id as set by
         # BaseStorage.tpc_begin().
         revid = oid + tid
         # Calculate and write the entries for version ids
@@ -567,7 +560,7 @@
         # weren't told what to believe, via prev_txn
         if prevrevid is None:
             # Get the metadata for the current revision of the object
-            cserial, crevid = self._getSerialAndTidMissingOk(oid)
+            crevid = self._getTidMissingOk(oid)
             if crevid is None:
                 # There's never been a previous revision of this object
                 prevrevid = ZERO
@@ -606,12 +599,7 @@
             # updated in _docommit().
             self._pickles.put(revid, data, txn=txn)
             lrevid = tid
-        # Update the serials table, but if the transaction id is different
-        # than the serial number, we need to write our special long record
-        if serial <> tid:
-            self._serials.put(oid, serial+tid, txn=txn)
-        else:
-            self._serials.put(oid, serial, txn=txn)
+        self._serials.put(oid, serial, txn=txn)
         # Update the rest of the tables
         self._metadata.put(revid, vid+nvrevid+lrevid+prevrevid, txn=txn)
         self._txnoids.put(tid, oid, txn=txn)
@@ -630,7 +618,7 @@
         # differences:
         #
         # - serial is the serial number of /this/ revision, not of the
-        #   previous revision.  It is used instead of self._serial, which is
+        #   previous revision.  It is used instead of self._tid, which is
         #   ignored.
         #
         # - Nothing is returned
@@ -703,7 +691,7 @@
                 # This object was modified
                 rtnoids[oid] = True
                 # Calculate the values for the new transaction metadata
-                serial, tid = self._getSerialAndTid(oid)
+                tid = self._getTid(oid)
                 meta = self._metadata[oid+tid]
                 curvid, nvrevid = unpack('>8s8s', meta[:16])
                 assert curvid == vid
@@ -720,13 +708,8 @@
                     # non-version data that might have an lrevid.
                     lrevid = DNE
                 # Write all the new data to the serials and metadata tables.
-                # Note that in an abortVersion the serial number of the object
-                # must be the serial number used in the non-version data,
-                # while the transaction id is the current transaction.  This
-                # is the one case where serial <> tid, and a special record
-                # must be written to the serials table for this.
-                newserial = self._serial
-                self._serials.put(oid, nvrevid+newserial, txn=txn)
+                newserial = self._tid
+                self._serials.put(oid, newserial, txn=txn)
                 self._metadata.put(oid+newserial, ZERO+ZERO+lrevid+tid,
                                    txn=txn)
                 self._txnoids.put(newserial, oid, txn=txn)
@@ -749,7 +732,7 @@
             # fine in practice since the number of versions should be quite
             # small over the lifetime of the database.  Maybe we can figure
             # out a way to do this in the pack operations.
-            return self._serial, rtnoids.keys()
+            return self._tid, rtnoids.keys()
         finally:
             c.close()
 
@@ -799,7 +782,7 @@
                 # This object was modified
                 rtnoids[oid] = True
                 # Calculate the values for the new transaction metadata
-                serial, tid = self._getSerialAndTid(oid)
+                tid = self._getTid(oid)
                 meta = self._metadata[oid+tid]
                 curvid, nvrevid, lrevid = unpack('>8s8s8s', meta[:24])
                 assert curvid == svid
@@ -808,7 +791,7 @@
                 # source version.
                 if not dest:
                     nvrevid = ZERO
-                newserial = self._serial
+                newserial = self._tid
                 self._serials.put(oid, newserial, txn=txn)
                 self._metadata.put(oid+newserial, dvid+nvrevid+lrevid+tid,
                                    txn=txn)
@@ -824,7 +807,7 @@
                     self._objrevs.put(newserial+oid, nvrevid, txn=txn)
                 c.delete()
                 rec = c.next()
-            return self._serial, rtnoids.keys()
+            return self._tid, rtnoids.keys()
         finally:
             c.close()
 
@@ -853,7 +836,7 @@
         self._lock_acquire()
         try:
             # Let KeyErrors percolate up
-            serial, tid = self._getSerialAndTid(oid)
+            tid = self._getTid(oid)
             vid = self._metadata[oid+tid][:8]
             if vid == ZERO:
                 # Not in a version
@@ -914,7 +897,7 @@
     # Accessor interface
     #
 
-    def _load(self, oid, serial, tid, version):
+    def _load(self, oid, tid, version):
         # Get the metadata associated with this revision of the object.
         # All we really need is the vid, the non-version revid and the
         # pickle pointer revid.
@@ -926,29 +909,29 @@
         # object is living in is the one that was requested, we simply
         # return the current revision's pickle.
         if vid == ZERO:
-            return self._pickles[oid+lrevid], serial, tid, ""
+            return self._pickles[oid+lrevid], tid, ""
         if self._versions.get(vid) == version:
-            return self._pickles[oid+lrevid], serial, tid, version
+            return self._pickles[oid+lrevid], tid, version
         # The object was living in a version, but not the one requested.
         # Semantics here are to return the non-version revision.  Allow
         # KeyErrors to percolate up (meaning there's no non-version rev).
         lrevid = self._metadata[oid+nvrevid][16:24]
-        return self._pickles[oid+lrevid], lrevid, tid, ""
+        return self._pickles[oid+lrevid], tid, ""
 
     def loadEx(self, oid, version):
         self._lock_acquire()
         try:
             # Get the current revision information for the object.  As per the
             # protocol, let Key errors percolate up.
-            serial, tid = self._getSerialAndTid(oid)
-            return self._load(oid, serial, tid, version)
+            tid = self._getTid(oid)
+            return self._load(oid, tid, version)
         finally:
             self._lock_release()
 
     def load(self, oid, version):
         return self.loadEx(oid, version)[:2]
 
-    def loadNonCurrent(self, oid, tid):
+    def loadBefore(self, oid, tid):
         self._lock_acquire()
         try:
             c = self._metadata.cursor()
@@ -960,22 +943,21 @@
                 except db.DBNotFoundError:
                     # If tid > cur tid for oid, then we'll get a not-found
                     # error.  Perhaps the current tid is sufficient?
-                    cur_serial, cur_tid = self._getSerialAndTid(oid)
+                    cur_tid = self._getTid(oid)
                     # if cur_tid >= tid, set_range() would have worked
                     assert cur_tid < tid
-                    data, serial, tid, version = self._load(oid, cur_serial,
-                                                            cur_tid, "")
-                    return data, serial, cur_tid, None
+                    data, tid, ver = self._load(oid, cur_tid, "")
+                    return data, cur_tid, None
 
                 next_tid = p[0][8:]
-                return self._noncurrent_search(c, oid, tid, next_tid)
+                return self._search_before(c, oid, tid, next_tid)
             finally:
                 c.close()
         finally:
             self._lock_release()
 
-    def _noncurrent_search(self, c, oid, tid, end_tid):
-        # Operates on the cursor created by loadNonCurrent().
+    def _search_before(self, c, oid, tid, end_tid):
+        # Operates on the cursor created by loadBefore().
         p = c.prev()
         if p is None:
             return None
@@ -995,11 +977,9 @@
             revid = nvrevid
         data = self._pickles[oid+revid]
         tid = key[8:]
-        # XXX What about abortVersion?  Does that give a different
-        # serial no than tid?
-        return data, revid, tid, end_tid
+        return data, tid, end_tid
 
-    def _getSerialAndTidMissingOk(self, oid):
+    def _getTidMissingOk(self, oid):
         # For the object, return the curent serial number and transaction id
         # of the last transaction that modified the object.  Usually these
         # will be the same, unless the last transaction was an abortVersion.
@@ -1033,30 +1013,27 @@
                 serials.append(rec[1])
                 rec = c.next_dup()
             if not serials:
-                return None, None
+                return None
             if len(serials) == 1:
-                data = serials[0]
+                return serials[0]
             else:
-                pending = self._pending.get(self._serial)
+                pending = self._pending.get(self._tid)
                 assert pending in (ABORT, COMMIT), 'pending: %s' % pending
                 if pending == ABORT:
-                    data = serials[0]
+                    return serials[0]
                 else:
-                    data = serials[1]
-            if len(data) == 8:
-                return data, data
-            return data[:8], data[8:]
+                    return serials[1]
         finally:
             c.close()
 
-    def _getSerialAndTid(self, oid):
+    def _getTid(self, oid):
         # For the object, return the curent serial number and transaction id
         # of the last transaction that modified the object.  Usually these
         # will be the same, unless the last transaction was an abortVersion
-        serial, tid = self._getSerialAndTidMissingOk(oid)
-        if serial is None and tid is None:
+        tid = self._getTidMissingOk(oid)
+        if tid is None:
             raise KeyError, 'Object does not exist: %r' % oid
-        return serial, tid
+        return tid
 
     def _loadSerialEx(self, oid, serial):
         # Just like loadSerial, except that it returns the pickle data, the
@@ -1096,12 +1073,12 @@
         # irrespective of any versions.
         self._lock_acquire()
         try:
-            serial, tid = self._getSerialAndTid(oid)
+            tid = self._getTid(oid)
             # See if the object has been uncreated
             lrevid = unpack('>8s', self._metadata[oid+tid][16:24])[0]
             if lrevid == DNE:
                 raise KeyError
-            return serial
+            return tid
         finally:
             self._lock_release()
 
@@ -1214,7 +1191,7 @@
                 # that would be restored if we were undoing the current
                 # revision.  Otherwise, we attempt application level conflict
                 # resolution.  If that fails, we raise an exception.
-                cserial, ctid = self._getSerialAndTid(oid)
+                ctid = self._getTid(oid)
                 if ctid == tid:
                     newrevs.append(self._undo_current_tid(oid, ctid))
                 else:
@@ -1226,8 +1203,8 @@
         # new metadata records (and potentially new pickle records).
         rtnoids = {}
         for oid, metadata, data in newrevs:
-            newserial = self._serial
-            revid = oid + self._serial
+            newserial = self._tid
+            revid = oid + self._tid
             # If the data pickle is None, then this undo is simply
             # re-using a pickle stored earlier.  All we need to do then is
             # bump the pickle refcount to reflect this new reference,
@@ -1255,7 +1232,7 @@
             rtnoids[oid] = True
             # Add this object revision to the autopack table
             self._objrevs.put(newserial+oid, prevrevid, txn=txn)
-        return self._serial, rtnoids.keys()
+        return self._tid, rtnoids.keys()
 
     def transactionalUndo(self, tid, transaction):
         if self._is_read_only:
@@ -1349,7 +1326,7 @@
             # start with the most recent revision of the object, then search
             # the transaction records backwards until we find enough records.
             history = []
-            serial, tid = self._getSerialAndTid(oid)
+            tid = self._getTid(oid)
             # BAW: Again, let KeyErrors percolate up
             while len(history) < size:
                 # Some information comes out of the revision metadata...
@@ -1374,7 +1351,7 @@
                 d = {'time'       : TimeStamp(tid).timeTime(),
                      'user_name'  : user,
                      'description': desc,
-                     'serial'     : serial,
+                     'tid'        : tid,
                      'version'    : retvers,
                      'size'       : len(data),
                      }
@@ -1698,7 +1675,7 @@
         # BAW: Maybe this could probably be more efficient by not doing so
         # much searching, but it would also be more complicated, so the
         # tradeoff should be measured.
-        serial, tid = self._getSerialAndTid(oid)
+        tid = self._getTid(oid)
         c = self._metadata.cursor(txn=txn)
         try:
             rec = c.set_range(oid)
@@ -1710,11 +1687,11 @@
                     # We found the end of the metadata records for this
                     # object prior to the pack time.
                     break
-                serial = ctid
+                tid = ctid
                 rec = c.next()
         finally:
             c.close()
-        return serial
+        return tid
 
     def _rootset(self, packtid, txn):
         # Find the root set for reachability purposes.  A root set is a tuple
@@ -1816,7 +1793,7 @@
                     raise PackStop, 'stopped in _sweep()'
                 oid = rec[0]
                 rec = c.next()
-                serial, tid = self._getSerialAndTid(oid)
+                tid = self._getTid(oid)
                 # If the current revision of this object newer than the
                 # packtid, we'll ignore this object since we only care about
                 # root reachability as of the pack time.
@@ -2040,7 +2017,7 @@
     # Object Id
     oid = None
     # Object serial number (i.e. revision id)
-    serial = None
+    tid = None
     # Version string
     version = None
     # Data pickle
@@ -2048,9 +2025,9 @@
     # The pointer to the transaction containing the pickle data, if not None
     data_txn = None
 
-    def __init__(self, oid, serial, version, data, data_txn):
+    def __init__(self, oid, tid, version, data, data_txn):
         self.oid = oid
-        self.serial = serial
+        self.tid = tid
         self.version = version
         self.data = data
         self.data_txn = data_txn


=== ZODB3/BDBStorage/BDBMinimalStorage.py 1.32 => 1.32.2.1 ===
--- ZODB3/BDBStorage/BDBMinimalStorage.py:1.32	Thu Oct  2 14:17:32 2003
+++ ZODB3/BDBStorage/BDBMinimalStorage.py	Tue Dec  2 02:10:29 2003
@@ -158,10 +158,10 @@
         self._pending.truncate(txn)
 
     def _abort(self):
-        self._withtxn(self._doabort, self._serial)
+        self._withtxn(self._doabort, self._tid)
 
     def _docommit(self, txn, tid):
-        self._pending.put(self._serial, COMMIT, txn)
+        self._pending.put(self._tid, COMMIT, txn)
         deltas = {}
         co = cs = None
         try:
@@ -248,7 +248,7 @@
         # will be aborted.
         txn = self._env.txn_begin()
         try:
-            self._pending.put(self._serial, ABORT, txn)
+            self._pending.put(self._tid, ABORT, txn)
         except:
             txn.abort()
             raise
@@ -269,7 +269,7 @@
                 raise POSException.ConflictError(serials=(oserial, serial))
         # Optimistically write to the serials and pickles table.  Be sure
         # to also update the oids table for this object too.
-        newserial = self._serial
+        newserial = self._tid
         self._serials.put(oid, newserial, txn=txn)
         self._pickles.put(oid+newserial, data, txn=txn)
         self._oids.put(oid, PRESENT, txn=txn)
@@ -303,7 +303,7 @@
         # _docommit() twiddles the pending flag to COMMIT now since after the
         # vote call, we promise that the changes will be committed, no matter
         # what.  The recovery process will check this.
-        self._withtxn(self._docommit, self._serial)
+        self._withtxn(self._docommit, self._tid)
 
     #
     # Accessor interface
@@ -338,7 +338,7 @@
                 return None
             if len(serials) == 1:
                 return serials[0]
-            pending = self._pending.get(self._serial)
+            pending = self._pending.get(self._tid)
             assert pending in (ABORT, COMMIT)
             if pending == ABORT:
                 return serials[0]
@@ -361,7 +361,7 @@
             self._lock_release()
 
     def modifiedInVersion(self, oid):
-        # So BaseStorage.getSerial() just works.  Note that this storage
+        # So BaseStorage.getTid() just works.  Note that this storage
         # doesn't support versions.
         return ''
 
@@ -546,7 +546,7 @@
     # versionEmpty(self, version)
     # versions(self, max=None)
     # loadSerial(self, oid, serial)
-    # getSerial(self, oid)
+    # getTid(self, oid)
     # transactionalUndo(self, tid, transaction)
     # undoLog(self, first=0, last=-20, filter=None)
     # history(self, oid, version=None, size=1, filter=None)




More information about the Zope-Checkins mailing list