[Zope3-checkins] CVS: ZODB4/src/zodb/storage - bdbminimal.py:1.10

Barry Warsaw barry@wooz.org
Thu, 30 Jan 2003 18:17:45 -0500


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

Modified Files:
	bdbminimal.py 
Log Message:
Close an autopack race, where if a store was done after a sweep, but
before the collect_objs, the stored object would stay in packmark
until the next pack, preventing any objects it references from being
counted in the root-reachable test.

I don't have time to write a test case for this. :(

pack(): After we acquire the packlock, but before we set the packing
flag to True, we clear the packmark table.

_dopack(): Use the convenience wrapper _withlock method.


=== ZODB4/src/zodb/storage/bdbminimal.py 1.9 => 1.10 ===
--- ZODB4/src/zodb/storage/bdbminimal.py:1.9	Mon Jan 27 11:26:00 2003
+++ ZODB4/src/zodb/storage/bdbminimal.py	Thu Jan 30 18:17:43 2003
@@ -370,6 +370,12 @@
         # A simple wrapper around the bulk of packing, but which acquires a
         # lock that prevents multiple packs from running at the same time.
         self._packlock.acquire()
+        # Before setting the packing flag to true, acquire the storage lock
+        # and clear out the packmark table, in case there's any cruft left
+        # over from the previous pack.
+        def clear_packmark(txn):
+            self._packmark.truncate(txn=txn)
+        self._withlock(self._withtxn, clear_packmark)
         self._packing = True
         try:
             # We don't wrap this in _withtxn() because we're going to do the
@@ -390,25 +396,13 @@
         # objects reachable from the root.  Anything else is a candidate for
         # having all their revisions packed away.  The set of reachable
         # objects lives in the _packmark table.
-        self._lock_acquire()
-        try:
-            self._withtxn(self._mark)
-        finally:
-            self._lock_release()
+        self._withlock(self._withtxn, self._mark)
         # Now perform a sweep, using oidqueue to hold all object ids for
         # objects which are not root reachable as of the pack time.
-        self._lock_acquire()
-        try:
-            self._withtxn(self._sweep)
-        finally:
-            self._lock_release()
+        self._withlock(self._withtxn, self._sweep)
         # Once again, collect any objects with refcount zero due to the mark
         # and sweep garbage collection pass.
-        self._lock_acquire()
-        try:
-            self._withtxn(self._collect_objs)
-        finally:
-            self._lock_release()
+        self._withlock(self._withtxn, self._collect_objs)
 
     def _mark(self, txn):
         # Find the oids for all the objects reachable from the root.  To
@@ -462,7 +456,6 @@
         finally:
             c.close()
         # We're done with the mark table
-        self._packmark.truncate(txn)
 
     def _collect_objs(self, txn):
         orec = self._oidqueue.consume(txn)