[Zope-Checkins] CVS: ZODB3/ZODB - fspack.py:1.8.8.5

Tim Peters tim.one at comcast.net
Fri Jan 16 14:18:21 EST 2004


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv25285/ZODB

Modified Files:
      Tag: Zope-2_7-branch
	fspack.py 
Log Message:
Backport "redundant pack" fix from the HEAD:  if you try to pack to a time
earlier than a .fs was previously packed to, the attempt shouldn't do
anything (except raise an exception).  It was trying to pack to the
earlier time anyway, but pack's reachability traversal can't work
correctly then due to the "missing" revisions in the gap between the
pack times, and the packed .fs could lose live data as a result.


=== ZODB3/ZODB/fspack.py 1.8.8.4 => 1.8.8.5 ===
--- ZODB3/ZODB/fspack.py:1.8.8.4	Mon Sep 15 17:26:56 2003
+++ ZODB3/ZODB/fspack.py	Fri Jan 16 14:17:51 2004
@@ -24,17 +24,11 @@
 a backpointer after that time.
 """
 
-# This module contains code backported from ZODB4 from the
-# zodb.storage.file package.  It's been edited heavily to work with
-# ZODB3 code and storage layout.
-
 import os
-import struct
 from types import StringType
 
 from ZODB.referencesf import referencesf
-from ZODB.utils import p64, u64, z64, oid_repr
-from zLOG import LOG, BLATHER, WARNING, ERROR, PANIC
+from ZODB.utils import p64, u64, z64
 
 try:
     from ZODB.fsIndex import fsIndex
@@ -69,6 +63,7 @@
 TRANS_HDR_LEN = 23
 DATA_HDR_LEN = 42
 DATA_VERSION_HDR_LEN = 58
+import struct
 assert struct.calcsize(TRANS_HDR) == TRANS_HDR_LEN
 assert struct.calcsize(DATA_HDR) == DATA_HDR_LEN
 
@@ -465,11 +460,19 @@
 
     def buildPackIndex(self):
         pos = 4L
+        # We make the initial assumption that the database has been
+        # packed before and set unpacked to True only after seeing the
+        # first record with a status == " ".  If we get to the packtime
+        # and unpacked is still False, we need to watch for a redundant
+        # pack.
+        unpacked = False
         while pos < self.eof:
             th = self._read_txn_header(pos)
             if th.tid > self.packtime:
                 break
             self.checkTxn(th, pos)
+            if th.status != "p":
+                unpacked = True
 
             tpos = pos
             end = pos + th.tlen
@@ -493,6 +496,24 @@
 
         self.packpos = pos
 
+        if unpacked:
+            return
+        # check for a redundant pack.  If the first record following
+        # the newly computed packpos has status 'p', then it was
+        # packed earlier and the current pack is redudant.
+        try:
+            th = self._read_txn_header(pos)
+        except CorruptedDataError, err:
+            if err.buf != "":
+                raise
+        if th.status == 'p':
+            # Delay import to code with circular imports.
+            # XXX put exceptions in a separate module
+            from ZODB.FileStorage import FileStorageError
+            raise FileStorageError(
+                "The database has already been packed to a later time"
+                " or no changes have been made since the last pack")
+
     def findReachableAtPacktime(self, roots):
         """Mark all objects reachable from the oids in roots as reachable."""
         todo = list(roots)
@@ -878,3 +899,4 @@
         if self._lock_counter % 20 == 0:
             self._commit_lock_acquire()
         return ipos
+




More information about the Zope-Checkins mailing list