[Zodb-checkins] SVN: ZODB/trunk/src/ZODB/ Fixed a pack bug (or possibly a missfeature). POSKeyErrors were
Jim Fulton
jim at zope.com
Tue Dec 16 11:23:51 EST 2008
Log message for revision 94128:
Fixed a pack bug (or possibly a missfeature). POSKeyErrors were
ignored when doing GC. That is, when traversing from the root, if a
reference object wasn't found, it was simply ignored, covering up a
potential problem. Now raise a key error, which stops packing.
Changed:
U ZODB/trunk/src/ZODB/FileStorage/fspack.py
U ZODB/trunk/src/ZODB/tests/TransactionalUndoStorage.py
-=-
Modified: ZODB/trunk/src/ZODB/FileStorage/fspack.py
===================================================================
--- ZODB/trunk/src/ZODB/FileStorage/fspack.py 2008-12-16 15:24:08 UTC (rev 94127)
+++ ZODB/trunk/src/ZODB/FileStorage/fspack.py 2008-12-16 16:23:50 UTC (rev 94128)
@@ -248,27 +248,28 @@
def findReachableAtPacktime(self, roots):
"""Mark all objects reachable from the oids in roots as reachable."""
+ reachable = self.reachable
+ oid2curpos = self.oid2curpos
+
todo = list(roots)
while todo:
oid = todo.pop()
- if self.reachable.has_key(oid):
+ if oid in reachable:
continue
- L = []
+ try:
+ pos = oid2curpos[oid]
+ except KeyError:
+ if oid == z64 and len(oid2curpos) == 0:
+ # special case, pack to before creation time
+ continue
+ raise
+
+ reachable[oid] = pos
+ for oid in self.findrefs(pos):
+ if oid not in reachable:
+ todo.append(oid)
- pos = self.oid2curpos.get(oid)
- if pos is not None:
- L.append(pos)
- todo.extend(self.findrefs(pos))
-
- if not L:
- continue
-
- pos = L.pop()
- self.reachable[oid] = pos
- if L:
- self.reach_ex[oid] = L
-
def findReachableFromFuture(self):
# In this pass, the roots are positions of object revisions.
# We add a pos to extra_roots when there is a backpointer to a
Modified: ZODB/trunk/src/ZODB/tests/TransactionalUndoStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/TransactionalUndoStorage.py 2008-12-16 15:24:08 UTC (rev 94127)
+++ ZODB/trunk/src/ZODB/tests/TransactionalUndoStorage.py 2008-12-16 16:23:50 UTC (rev 94128)
@@ -427,10 +427,23 @@
self._iterate()
def checkTransactionalUndoAfterPack(self):
- eq = self.assertEqual
+ # bwarsaw Date: Thu Mar 28 21:04:43 2002 UTC
+ # This is a test which should provoke the underlying bug in
+ # transactionalUndo() on a standby storage. If our hypothesis
+ # is correct, the bug is in FileStorage, and is caused by
+ # encoding the file position in the `id' field of the undoLog
+ # information. Note that Full just encodes the tid, but this
+ # is a problem for FileStorage (we have a strategy for fixing
+ # this).
+
+ # So, basically, this makes sure that undo info doesn't depend
+ # on file positions. We change the file positions in an undo
+ # record by packing.
+
# Add a few object revisions
- oid = self._storage.new_oid()
- revid1 = self._dostore(oid, data=MinPO(51))
+ oid = '\0'*8
+ revid0 = self._dostore(oid, data=MinPO(50))
+ revid1 = self._dostore(oid, revid=revid0, data=MinPO(51))
snooze()
packtime = time.time()
snooze() # time.time() now distinct from packtime
@@ -438,7 +451,7 @@
self._dostore(oid, revid=revid2, data=MinPO(53))
# Now get the undo log
info = self._storage.undoInfo()
- eq(len(info), 3)
+ self.assertEqual(len(info), 4)
tid = info[0]['id']
# Now pack just the initial revision of the object. We need the
# second revision otherwise we won't be able to undo the third
@@ -446,18 +459,18 @@
self._storage.pack(packtime, referencesf)
# Make some basic assertions about the undo information now
info2 = self._storage.undoInfo()
- eq(len(info2), 2)
+ self.assertEqual(len(info2), 2)
# And now attempt to undo the last transaction
t = Transaction()
self._storage.tpc_begin(t)
tid, oids = self._storage.undo(tid, t)
self._storage.tpc_vote(t)
self._storage.tpc_finish(t)
- eq(len(oids), 1)
- eq(oids[0], oid)
+ self.assertEqual(len(oids), 1)
+ self.assertEqual(oids[0], oid)
data, revid = self._storage.load(oid, '')
# The object must now be at the second state
- eq(zodb_unpickle(data), MinPO(52))
+ self.assertEqual(zodb_unpickle(data), MinPO(52))
self._iterate()
def checkTransactionalUndoAfterPackWithObjectUnlinkFromRoot(self):
More information about the Zodb-checkins
mailing list