[Zodb-checkins] CVS: Packages/StorageGC - CyclicGC.py:1.14
tim@digicool.com
tim@digicool.com
Tue, 24 Apr 2001 17:21:08 -0400 (EDT)
Update of /cvs-repository/Packages/StorageGC
In directory korak:/tmp/cvs-serv4802
Modified Files:
CyclicGC.py
Log Message:
Much simpler proof that it's safe to skip TopologyError() when gcReferences(x)
returns new stuff across calls. But reused the "extra" <wink> doc space to
given an example of when it's *not* safe to ignore new refs.
Added a cheap assert of a key invariant.
--- Updated File CyclicGC.py in package Packages/StorageGC --
--- CyclicGC.py 2001/04/23 20:50:08 1.13
+++ CyclicGC.py 2001/04/24 21:21:08 1.14
@@ -322,6 +322,7 @@
for d in self._allobjds:
adjrc = d[ADJRC]
+ assert adjrc != ADJRC_ISFREE
if adjrc > 0:
# This is externally reachable, so must reincrement the
@@ -443,7 +444,7 @@
# Else this reference popped into existence after we captured
# the initial refcount info. So why don't we raise
# _TopologyError? I don't think it can hurt! The ultimate
- # result is the transitive closure of the root set, less
+ # result is the transitive closure of the start set, less
# everything reachable starting from outside the TC. Since
# we didn't know about this node before, obj is pointing to a
# child *outside* the TC. That *can* make something we're
@@ -463,19 +464,22 @@
# new reference popped up. But this new pointer goes from
# inside the TC (obj) to outside the TC (child): it's going
# "in the wrong direction" to hurt.
- # Detail: A path from something outside the TC to something
- # inside the TC that contains this new pointer has to get
- # inside the TC *before* reaching this pointer (because this
- # pointer *starts* in the TC). So the endpoint of that pointer
- # was already reachable from outside the TC, and therefore also
- # everything in the TC along the path from that endpoint to
- # obj. So if such a new path exists, there are no *newly*
- # reachable objects in the TC from the start of the path up
- # through and including obj.
- # What about the path after obj? Since obj ends in child, if
- # there's a path from child to something in the TC, that path
- # still goes from child to something in the TC without the
- # obj->child pointer, so again the object was reachable before.
+ # Detail: For something outside the TC to reach something
+ # inside the TC, there must be a pointer P starting outside
+ # and ending inside. But since the new obj->child pointer
+ # goes the other direction, it's irrelevant to the existence
+ # of any such pointer (P exists whether or not obj->child does).
+ # If the ignored obj->child pointer were *within* the TC, then
+ # we'd be vulnerable; e.g.,
+ # A <-> B -> C <- D
+ # If the start set is {A}, the TC is {A, B, C}, and of those
+ # only C is reachable from outside, so A<->B is trash. But if
+ # a new pointer B <- C popped into existence, A<->B would no
+ # longer be trash. We can't detect that here; we detect that
+ # later, in _extract_garbage(), by ensuring that the refcounts
+ # on trash objects haven't changed since we captured them (in
+ # this specific example, we'll eventually discover that B's
+ # refcount has changed).
return result
def _get_storage_rc(self, obj):