[Zope-Checkins] CVS: ZODB3/ZODB - FileStorage.py:1.105.2.9

Jeremy Hylton jeremy@zope.com
Fri, 6 Dec 2002 17:59:31 -0500


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

Modified Files:
      Tag: ZODB3-3_1-branch
	FileStorage.py 
Log Message:
Fix subtle bug in restore().

The _txn_find() must not stop at the pack boundary when it is called
by restore().  It was originally written for _txn_undo() which isn't
supposed to undo to a transaction across a pack.  But it should be
legal to restore() a transaction with a reference to a data record in
a transaction that was packed.

Fix by adding stop_at_pack flag to _txn_find() and add tests of this
behavior for FileStorage.


=== ZODB3/ZODB/FileStorage.py 1.105.2.8 => 1.105.2.9 ===
--- ZODB3/ZODB/FileStorage.py:1.105.2.8	Tue Nov 26 18:03:23 2002
+++ ZODB3/ZODB/FileStorage.py	Fri Dec  6 17:59:31 2002
@@ -783,7 +783,7 @@
         try:
             prev_pos = 0
             if prev_txn is not None:
-                prev_txn_pos = self._txn_find(prev_txn)
+                prev_txn_pos = self._txn_find(prev_txn, 0)
                 if prev_txn_pos:
                     prev_pos = self._data_find(prev_txn_pos, oid, data)
             old = self._index_get(oid, 0)
@@ -1205,12 +1205,12 @@
         # Find the right transaction to undo and call _txn_undo_write().
         tid = base64.decodestring(transaction_id + '\n')
         assert len(tid) == 8
-        tpos = self._txn_find(tid)
+        tpos = self._txn_find(tid, 1)
         tindex = self._txn_undo_write(tpos, tid)
         self._tindex.update(tindex)
         return tindex.keys()
 
-    def _txn_find(self, tid):
+    def _txn_find(self, tid, stop_at_pack):
         pos = self._pos
         # XXX Why 39?  Only because undoLog() uses it as a boundary.
         while pos > 39:
@@ -1221,9 +1221,10 @@
             _tid = h[:8]
             if _tid == tid:
                 return pos
-            status = h[16] # get the c in 8s8sc
-            if status == 'p' or _tid < self._packt:
-                break
+            if stop_at_pack:
+                # If the status indicates the record is packed, stop.
+                if h[16] == 'p' or _tid < self._packt:
+                    break
         raise UndoError("Invalid transaction id")
 
     def _txn_undo_write(self, tpos, tid):