[Zope3-checkins] CVS: Zope3/src/zodb/storage - bdbfull.py:1.19

Barry Warsaw barry@wooz.org
Mon, 17 Mar 2003 15:22:40 -0500


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

Modified Files:
	bdbfull.py 
Log Message:
pack(), autopack(): Simplify the api since these are essentially the
same method with just the gc flag argument difference.

_dopack(): gc flag isn't optinal

"classicpack" -> "gcpack"


=== Zope3/src/zodb/storage/bdbfull.py 1.18 => 1.19 ===
--- Zope3/src/zodb/storage/bdbfull.py:1.18	Fri Mar 14 15:44:50 2003
+++ Zope3/src/zodb/storage/bdbfull.py	Mon Mar 17 15:22:39 2003
@@ -297,7 +297,7 @@
         lastpacktime = u64(self._last_packtime())
         return _Autopack(
             self, event,
-            config.frequency, config.packtime, config.classicpack,
+            config.frequency, config.packtime, config.gcpack,
             lastpacktime)
 
     def _doabort(self, txn, tid):
@@ -1293,36 +1293,27 @@
             last = abs(last)
         return self._withlock(self._doundolog, first, last, filter)
 
-    # Packing
-    #
-    # There are two types of pack operations, the classic pack and the
-    # autopack.  Autopack's primary job is to periodically delete non-current
-    # object revisions.  It runs in a thread and has an `autopack time' which
-    # is essentially just a time in the past at which to autopack to.  For
-    # example, you might set up autopack to run once per hour, packing away
-    # all revisions that are older than 4 hours.  Autopack can also be
-    # configured to periodically do a classic pack.
     #
-    # Classic pack is like autopack -- it packs away old revisions -- but it
-    # also does a mark and sweep through all the known objects, looking for
-    # those that are not root reachable as of the pack time.  Such objects are
-    # also packed away even if they have current revisions in the packable
-    # transactions, because it means that there is no undo operation that can
-    # restore the object's reachability.  Remember that you cannot undo
-    # previous to the latest pack time.
-    #
-    # Both packing strategies do reference counting, and the refcounts are
-    # sums of the refcounts of all revisions, so if an object's refcount goes
-    # to zero, all its object revisions can safely be packed away.
+    # Packing
     #
-    # We try to interleave BerkeleyDB transactions and non-pack-lock
-    # acquisition as granularly as possible so that packing doesn't block
-    # other operations for too long.  But remember we don't use Berkeley locks
-    # so we have to be careful about our application level locks.
-
-    # First, the public API for classic pack
-    def pack(self, t):
-        self.log('classic pack started')
+
+    def pack(self, t, gc=True):
+        """Perform a pack on the storage.
+
+        There are two forms of packing: incremental and full gc.  In an
+        incremental pack, only old object revisions are removed.  In a full gc
+        pack, cyclic garbage detection and removal is also performed.
+
+        t is the pack time.  All non-current object revisions older than t
+        will be removed in an incremental pack.
+
+        pack() always performs an incremental pack.  If the gc flag is True,
+        then pack() will also perform a garbage collection.  Some storages
+        (e.g. FileStorage) always do both phases in a pack() call.  Such
+        storages should simply ignore the gc flag.
+        """
+        self.log('pack started (packtime: %s, gc? %s)', t,
+                 (gc and 'yes' or 'no'))
         # 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()
@@ -1332,13 +1323,13 @@
             # operation across several Berkeley transactions, which allows
             # other work to happen (stores and reads) while packing is being
             # done.
-            self._dopack(t)
+            self._dopack(t, gc)
         finally:
             self._packing = False
             self._packlock.release()
-        self.log('classic pack finished')
+        self.log('pack finished')
 
-    def _dopack(self, t, gc=True):
+    def _dopack(self, t, gc):
         # t is a TimeTime, or time float, convert this to a TimeStamp object,
         # using an algorithm similar to what's used in FileStorage.  We know
         # that our transaction ids, a.k.a. revision ids, are timestamps.
@@ -1388,29 +1379,6 @@
         finally:
             self._lock_release()
 
-    def autopack(self, t, gc=False):
-        """Perform an autopack pass.
-
-        Autopacking is different than classic pack() in that it doesn't do
-        cyclic garbage detection unless the gc flag is True.
-        """
-        self.log('autopack started (packtime: %s, gc? %s)', t,
-                 (gc and 'yes' or 'no'))
-        # 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()
-        self._packing = True
-        try:
-            # We don't wrap this in _withtxn() because we're going to do the
-            # operation across several Berkeley transactions, which allows
-            # other work to happen (stores and reads) while packing is being
-            # done.
-            self._dopack(t, gc)
-        finally:
-            self._packing = False
-            self._packlock.release()
-        self.log('autopack finished')
-
     def _collect_revs(self, txn, packtid):
         ct = co = None
         try:
@@ -1870,21 +1838,21 @@
     NAME = 'autopacking'
 
     def __init__(self, storage, event,
-                 frequency, packtime, classicpack,
+                 frequency, packtime, gcpack,
                  lastpacktime):
         _WorkThread.__init__(self, storage, event, frequency)
         self._packtime = packtime
-        self._classicpack = classicpack
+        self._gcpack = gcpack
         # Bookkeeping
-        self._lastclassic = 0
+        self._lastgc = 0
 
     def _dowork(self):
-        # Should we do a classic pack this time?
-        if self._classicpack <= 0:
-            classicp = False
+        # Should we do a full gc pack this time?
+        if self._gcpack <= 0:
+            dofullgc = False
         else:
-            v = (self._lastclassic + 1) % self._classicpack
-            self._lastclassic = v
-            classicp = not v
-        # Run the autopack phase
-        self._storage.autopack(time.time() - self._packtime, classicp)
+            v = (self._lastgc + 1) % self._gcpack
+            self._lastgc = v
+            dofullgc = not v
+        # Run the full gc phase
+        self._storage.pack(time.time() - self._packtime, dofullgc)