[Zodb-checkins] CVS: ZODB3/bsddb3Storage/bsddb3Storage - Minimal.py:1.12.4.5
Barry Warsaw
barry@wooz.org
Thu, 19 Sep 2002 18:07:47 -0400
Update of /cvs-repository/ZODB3/bsddb3Storage/bsddb3Storage
In directory cvs.zope.org:/tmp/cvs-serv14493
Modified Files:
Tag: bdb-nolocks
Minimal.py
Log Message:
Code reorg and comment clean up.
=== ZODB3/bsddb3Storage/bsddb3Storage/Minimal.py 1.12.4.4 => 1.12.4.5 ===
--- ZODB3/bsddb3Storage/bsddb3Storage/Minimal.py:1.12.4.4 Tue Sep 17 18:08:41 2002
+++ ZODB3/bsddb3Storage/bsddb3Storage/Minimal.py Thu Sep 19 18:07:47 2002
@@ -41,12 +41,13 @@
def _setupDBs(self):
# Data Type Assumptions:
#
- # - object ids (oid) are 8-bytes
- # - object revision ids (revid), aka serial numbers, are 8-bytes
- # - transaction ids (tid) are 8-bytes
- # - data pickles are of arbitrary length
+ # - Object ids (oid) are 8-bytes
+ # - Objects have revisions, with each revision being identified by a
+ # unique serial number.
+ # - Transaction ids (tid) are 8-bytes
+ # - Data pickles are of arbitrary length
#
- # The minimal storage uses the following tables:
+ # The Minimal storage uses the following tables:
#
# serials -- {oid -> [serial]}
# Maps oids to serial numbers. Each oid can be mapped to 1 or 2
@@ -55,7 +56,7 @@
# pending flag (see below).
#
# pickles -- {oid+serial -> pickle}
- # Maps the oid plus the serial number to the object's data pickle.
+ # Maps the object revisions to the revision's pickle data.
#
# refcounts -- {oid -> count}
# Maps the oid to the reference count for the object. This
@@ -63,19 +64,18 @@
# goes to zero, the object is automatically deleted.
#
# oids -- [oid]
- # This is just a list of oids of objects that are modified in the
- # current transaction.
+ # This is a list of oids of objects that are modified in the
+ # current uncommitted transaction.
#
- # pending -- |tid -> 'A' | 'C'|
+ # pending -- tid -> 'A' | 'C'
# This is an optional flag which says what to do when the database
# is recovering from a crash. The flag is normally 'A' which
- # means any pending data should be aborted. After a tpc_vote()
- # but before the end of the tpc_finish(), this flag will be 'C'
- # which means, upon recovery/restart, all pending data should be
- # committed. Outside of any transaction (e.g. before the
- # tpc_begin()), there will be no pending entry. It is a database
- # invariant that if the pending table is empty, the oids table
- # must also be empty.
+ # means any pending data should be aborted. At the start of the
+ # tpc_finish() this flag will be changed to 'C' which means, upon
+ # recovery/restart, all pending data should be committed. Outside
+ # of any transaction (e.g. before the tpc_begin()), there will be
+ # no pending entry. It is a database invariant that if the
+ # pending table is empty, the oids table must also be empty.
#
self._serials = self._setupDB('serials', db.DB_DUP)
self._pickles = self._setupDB('pickles')
@@ -101,6 +101,14 @@
finally:
self._lock_release()
+ def close(self):
+ self._serials.close()
+ self._pickles.close()
+ self._refcounts.close()
+ self._oids.close()
+ self._pending.close()
+ BerkeleyBase.close(self)
+
def _do(self, meth, tid):
txn = self._env.txn_begin()
try:
@@ -133,7 +141,7 @@
# And delete the pickle table entry for this revision.
self._pickles.delete(oid+tid, txn=txn)
finally:
- # There's a small window of opportunity for leakinga cursor here,
+ # There's a small window of opportunity for leaking a cursor here,
# if co.close() were to fail. In practice this shouldn't happen.
if co: co.close()
if cs: cs.close()
@@ -162,16 +170,16 @@
cs.delete()
data = self._pickles.get(oid+stid, txn=txn)
assert data is not None
- _update(deltas, data, -1)
+ self._update(deltas, data, -1)
self._pickles.delete(oid+stid, txn=txn)
srec = cs.next_dup()
# Now add incref deltas for all objects referenced by the new
# revision of this object.
data = self._pickles.get(oid+tid, txn=txn)
assert data is not None
- _update(deltas, data, 1)
+ self._update(deltas, data, 1)
finally:
- # There's a small window of opportunity for leakinga cursor here,
+ # There's a small window of opportunity for leaking a cursor here,
# if co.close() were to fail. In practice this shouldn't happen.
if co: co.close()
if cs: cs.close()
@@ -193,7 +201,7 @@
# pickle, we need to decref all the objects referenced by it.
current = self._getCurrentSerial(oid)
data = self._pickles.get(oid+current, txn=txn)
- _update(newdeltas, data, -1)
+ self._update(newdeltas, data, -1)
# And delete the serials, pickle and refcount entries. At
# this point, I believe we should have just one serial entry.
self._serials.delete(oid, txn=txn)
@@ -212,43 +220,6 @@
# will be aborted.
self._pending[self._serial] = ABORT
- def _getCurrentSerial(self, oid):
- # BAW: We must have the application level lock here.
- c = self._serials.cursor()
- try:
- # There can be zero, one, or two entries in the serials table for
- # this oid. If there are no entries, raise a KeyError (we know
- # nothing about this object).
- #
- # If there is exactly one entry then this has to be the entry for
- # the object, regardless of the pending flag.
- #
- # If there are two entries, then we need to look at the pending
- # flag to decide which to return (there /better/ be a pending flag
- # set!). If the pending flag is COMMIT then we've already voted
- # so the second one is the good one. If the pending flag is ABORT
- # then we haven't yet committed to this transaction so the first
- # one is the good one.
- serials = []
- try:
- rec = c.set(oid)
- except db.DBNotFoundError:
- rec = None
- while rec:
- serials.append(rec[1])
- rec = c.next_dup()
- if not serials:
- return None
- if len(serials) == 1:
- return serials[0]
- pending = self._pending.get(self._serial)
- assert pending in (ABORT, COMMIT)
- if pending == ABORT:
- return serials[0]
- return serials[1]
- finally:
- c.close()
-
def store(self, oid, serial, data, version, transaction):
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
@@ -286,9 +257,6 @@
# Return the new serial number for the object
return newserial
- def _vote(self):
- pass
-
def _finish(self, tid, u, d, e):
# Twiddle the pending flag to COMMIT now since after the vote call, we
# promise that the changes will be committed, no matter what. The
@@ -299,18 +267,47 @@
def _abort(self):
self._do(self._doabort, self._serial)
- def close(self):
- self._serials.close()
- self._pickles.close()
- self._refcounts.close()
- self._oids.close()
- self._pending.close()
- BerkeleyBase.close(self)
-
#
- # Public storage interface
+ # Accessor interface
#
+ def _getCurrentSerial(self, oid):
+ # BAW: We must have the application level lock here.
+ c = self._serials.cursor()
+ try:
+ # There can be zero, one, or two entries in the serials table for
+ # this oid. If there are no entries, raise a KeyError (we know
+ # nothing about this object).
+ #
+ # If there is exactly one entry then this has to be the entry for
+ # the object, regardless of the pending flag.
+ #
+ # If there are two entries, then we need to look at the pending
+ # flag to decide which to return (there /better/ be a pending flag
+ # set!). If the pending flag is COMMIT then we've already voted
+ # so the second one is the good one. If the pending flag is ABORT
+ # then we haven't yet committed to this transaction so the first
+ # one is the good one.
+ serials = []
+ try:
+ rec = c.set(oid)
+ except db.DBNotFoundError:
+ rec = None
+ while rec:
+ serials.append(rec[1])
+ rec = c.next_dup()
+ if not serials:
+ return None
+ if len(serials) == 1:
+ return serials[0]
+ pending = self._pending.get(self._serial)
+ assert pending in (ABORT, COMMIT)
+ if pending == ABORT:
+ return serials[0]
+ return serials[1]
+ finally:
+ c.close()
+
def load(self, oid, version):
if version <> '':
raise POSException.Unsupported, 'versions are not supported'
@@ -326,19 +323,6 @@
self._lock_release()
def modifiedInVersion(self, oid):
- # So BaseStorage.getSerial just works. Note that this storage doesn't
- # support versions.
+ # So BaseStorage.getSerial() just works. Note that this storage
+ # doesn't support versions.
return ''
-
-
-
-def _update(deltas, data, incdec):
- refdoids = []
- referencesf(data, refdoids)
- for oid in refdoids:
- rc = deltas.get(oid, 0) + incdec
- if rc == 0:
- # Save space in the dict by zapping zeroes
- del deltas[oid]
- else:
- deltas[oid] = rc