[Zodb-checkins] CVS: ZODB3/BDBStorage - BDBFullStorage.py:1.75.2.4
Jeremy Hylton
cvs-admin at zope.org
Mon Nov 24 17:41:00 EST 2003
Update of /cvs-repository/ZODB3/BDBStorage
In directory cvs.zope.org:/tmp/cvs-serv32409/BDBStorage
Modified Files:
Tag: ZODB3-mvcc-2-branch
BDBFullStorage.py
Log Message:
Add loadNonCurrent() implementation after help from Barry.
This passes everything except checkAbortVersionNonCurrent. I'm not
sure how to figure out the serial number of a non-current revision
that was created by abortVersion.
=== ZODB3/BDBStorage/BDBFullStorage.py 1.75.2.3 => 1.75.2.4 ===
--- ZODB3/BDBStorage/BDBFullStorage.py:1.75.2.3 Sun Nov 23 16:39:23 2003
+++ ZODB3/BDBStorage/BDBFullStorage.py Mon Nov 24 17:40:54 2003
@@ -914,34 +914,90 @@
# Accessor interface
#
+ def _load(self, oid, serial, 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.
+ rec = self._metadata[oid+tid]
+ vid, nvrevid, lrevid = unpack('>8s8s8s', rec[:24])
+ if lrevid == DNE:
+ raise KeyError, 'Object does not exist: %r' % oid
+ # If the object isn't living in a version, or if the version the
+ # 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, ""
+ if self._versions.get(vid) == version:
+ return self._pickles[oid+lrevid], serial, 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, ""
+
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)
- # 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.
- rec = self._metadata[oid+tid]
- vid, nvrevid, lrevid = unpack('>8s8s8s', rec[:24])
- if lrevid == DNE:
- raise KeyError, 'Object does not exist: %r' % oid
- # If the object isn't living in a version, or if the version the
- # object is living in is the one that was requested, we simply
- # return the current revision's pickle.
- if vid == ZERO or self._versions.get(vid) == version:
- return self._pickles[oid+lrevid], serial, 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], serial, tid, ""
+ return self._load(oid, serial, tid, version)
finally:
self._lock_release()
def load(self, oid, version):
return self.loadEx(oid, version)[:2]
+
+ def loadNonCurrent(self, oid, tid):
+ self._lock_acquire()
+ try:
+ c = self._metadata.cursor()
+ try:
+ # The range search will return the smallest key greater
+ # than oid + tid. We need to look at the previous record.
+ try:
+ p = c.set_range(oid + tid)
+ 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)
+ # 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
+
+ next_tid = p[0][8:]
+ return self._noncurrent_search(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().
+ p = c.prev()
+ if p is None:
+ return None
+ key, rec = p
+ # If the previous record is for a different oid, then
+ # there is no matching record.
+ if key[:8] != oid:
+ return None
+ # It's possible that the range search hits oid, tid + 1 exactly,
+ # but only the first time.
+ if key == oid + tid:
+ return self._noncurrent_search(c, oid, tid, tid)
+ vid, nvrevid, lrevid = unpack(">8s8s8s", rec[:24])
+ if vid == ZERO:
+ revid = lrevid
+ else:
+ 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, tid, tid, end_tid
def _getSerialAndTidMissingOk(self, oid):
# For the object, return the curent serial number and transaction id
More information about the Zodb-checkins
mailing list