[Zodb-checkins] CVS: StandaloneZODB/bsddb3Storage/bsddb3Storage - Full.py:1.40.2.1
Jim Fulton
jim@zope.com
Wed, 27 Mar 2002 13:53:33 -0500
Update of /cvs-repository/StandaloneZODB/bsddb3Storage/bsddb3Storage
In directory cvs.zope.org:/tmp/cvs-serv24317
Modified Files:
Tag: bsddb3Storage-picklelog-branch
Full.py
Log Message:
Begun work on adding a pickle log. The idea is as follows:
In each stpre call (or other call that writes pickles), execute a
BDB transaction that writes the pickle to the pickle table and
writes the pickle key to the pickle log.
On ZODB transaction tpc_finish, remove the keys from the pickle log.
On ZODB tpc_abort or on startup, remove the pickles for the keys in
the pickle log and clear the pickle log.
This should pretty reasonably limit the size of a BDB transaction.
It may make things go faster. It should make tpc_finish go much
faster. By doing many more smaller BDB transactions, we shouldn't
block for really long times.
The work isn't done, but is being checked in so Barry can hack on it.
=== StandaloneZODB/bsddb3Storage/bsddb3Storage/Full.py 1.40 => 1.40.2.1 ===
import time
+from cPickle import loads, Pickler
+Pickler = Pickler()
+Pickler.fast = 1 # Don't use a memo
+fast_pickle_dumps = Pickler.dump
+del Pickler
+
# This uses the Dunn/Kuchling PyBSDDB v3 extension module available from
# http://pybsddb.sourceforge.net
from bsddb3 import db
@@ -97,7 +103,15 @@
# pickles -- {oid+revid -> pickle}
# Maps the concrete object referenced by oid+revid to that
# object's data pickle.
+
+ # Jim
#
+ # picklelog -- {oid+revid}
+ # Keeps a log of pickles that haven't been committed yet.
+ # This allows us to write pickles as we get them in the
+ # in separate BDB transactions.
+
+
# These are used only by the Full implementation.
#
# vids -- {version_string -> vid}
@@ -167,6 +181,8 @@
# Tables common to the base framework
self._serials = self._setupDB('serials')
self._pickles = self._setupDB('pickles')
+ self._picklelog = self._setupDB('picklelog')
+
# These are specific to the full implementation
self._vids = self._setupDB('vids')
self._versions = self._setupDB('versions')
@@ -176,6 +192,7 @@
self._txnoids = self._setupDB('txnoids', db.DB_DUP)
self._refcounts = self._setupDB('refcounts')
self._pickleRefcounts = self._setupDB('pickleRefcounts')
+
# Initialize our cache of the next available version id.
record = self._versions.cursor().last()
if record:
@@ -191,6 +208,7 @@
def close(self):
self._serials.close()
self._pickles.close()
+ self._picklelog.close()
self._vids.close()
self._versions.close()
self._currentVersions.close()
@@ -643,8 +661,10 @@
tuple(map(U64, (oid, ovid, vid))))
else:
nvrevid = onvrevid
- # Record the update to this object in the commit log.
- self._commitlog.write_object(oid, vid, nvrevid, data, oserial)
+
+ self._log_object(oid, vid, nvrevid, data, oserial)
+
+
finally:
self._lock_release()
# Return our cached serial number for the object. If conflict
@@ -653,6 +673,33 @@
return ResolvedSerial
return self._serial
+ def _log_object(self, oid, vid, nvrevid, data, oserial):
+
+ # Save data for later commit. We do this by writing the pickle
+ # directly to BDB and saving the pickle key in the pickle log.
+ # We extract the references and save them in the transaction log.
+
+ # Get the references
+ refdoids = []
+ referencesf(pickle, refdoids)
+ refdoids = fast_pickle_dumps(refdoids)
+
+ # Record the update to this object in the commit log.
+ self._commitlog.write_object(oid, vid, nvrevid, refdoids, oserial)
+
+ # Save the pickle in the database:
+ txn = self._env.txn_begin()
+ try:
+ key = oid + self._serial
+ self._pickles.put(key, data, txn=txn)
+ self._picklelog.put(key, '', txn=txn)
+ except:
+ txn.abort()
+ raise
+ else:
+ txn.commit()
+
+
def transactionalUndo(self, tid, transaction):
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
@@ -776,8 +823,7 @@
# see duplicate oids in this iteration.
oids[oid] = 1
for oid, vid, nvrevid, data, prevrevid in newstates:
- self._commitlog.write_object(oid, vid, nvrevid, data,
- prevrevid)
+ self._log_object(oid, vid, nvrevid, data, prevrevid)
oids[oid] = 1
return oids.keys()
finally: