[Zope3-checkins] CVS: ZODB/src/ZODB - DB.py:1.79

Tim Peters tim.one at comcast.net
Fri May 7 15:11:30 EDT 2004


Update of /cvs-repository/ZODB/src/ZODB
In directory cvs.zope.org:/tmp/cvs-serv21371/src/ZODB

Modified Files:
	DB.py 
Log Message:
Collector 1309: ZODB.DB.DB.cacheExtremeDetail reports wrong reference count

The refcount reported for a ghost was one too small, because the code for
ghosts and non-ghosts was the same, and presumably "it's a feature" that
the code for non-ghosts deliberately lies about the true Python refcount,
in order (guessing here) to report what the count would have been if the
cPickleCache didn't exist.  But while the cPickleCache holds on to a real
reference to non-ghost objects, it does not hold a real reference to ghost
objects, so subtracting "an extra" count for all objects made it appear
that non-referenced ghosts exist in the cache (which doesn't actually
happen).

What a tangled web we weave ...


=== ZODB/src/ZODB/DB.py 1.78 => 1.79 ===
--- ZODB/src/ZODB/DB.py:1.78	Fri Apr 23 13:26:37 2004
+++ ZODB/src/ZODB/DB.py	Fri May  7 15:10:59 2004
@@ -243,29 +243,39 @@
         return detail
 
     def cacheExtremeDetail(self):
-        detail=[]
+        detail = []
         conn_no = [0]  # A mutable reference to a counter
         def f(con, detail=detail, rc=sys.getrefcount, conn_no=conn_no):
-            conn_no[0] = conn_no[0] + 1
+            conn_no[0] += 1
             cn = conn_no[0]
             for oid, ob in con._cache_items():
-                id=''
-                if hasattr(ob,'__dict__'):
-                    d=ob.__dict__
+                id = ''
+                if hasattr(ob, '__dict__'):
+                    d = ob.__dict__
                     if d.has_key('id'):
-                        id=d['id']
+                        id = d['id']
                     elif d.has_key('__name__'):
-                        id=d['__name__']
+                        id = d['__name__']
 
                 module = getattr(ob.__class__, '__module__', '')
-                module = module and '%s.' % module or ''
+                module = module and ('%s.' % module) or ''
 
+                # What refcount ('rc') should we return?  The intent is
+                # that we return the true Python refcount, but as if the
+                # cache didn't exist.  This routine adds 3 to the true
+                # refcount:  1 for binding to name 'ob', another because
+                # ob lives in the con._cache_items() list we're iterating
+                # over, and calling sys.getrefcount(ob) boosts ob's
+                # count by 1 too.  So the true refcount is 3 less than
+                # sys.getrefcount(ob) returns.  But, in addition to that,
+                # the cache holds an extra reference on non-ghost objects,
+                # and we also want to pretend that doesn't exist.
                 detail.append({
                     'conn_no': cn,
                     'oid': oid,
                     'id': id,
                     'klass': "%s%s" % (module, ob.__class__.__name__),
-                    'rc': rc(ob)-4,
+                    'rc': rc(ob) - 3 - (ob._p_changed is not None),
                     'state': ob._p_changed,
                     #'references': con.references(oid),
                     })




More information about the Zope3-Checkins mailing list