[Zope-Checkins] CVS: ZODB3/ZODB - cPersistence.c:1.68 cPickleCache.c:1.80

Jeremy Hylton jeremy@zope.com
Wed, 2 Apr 2003 11:50:50 -0500


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

Modified Files:
	cPersistence.c cPickleCache.c 
Log Message:
Restore cache behavior for unreferenced by recently used objects.

The implementation is to make the reference in the cache "ring" a new
reference rather than a borrowed reference.  It is the intent of the
cache to keep N recently used objects in memory, regardless of whether
they are currently referenced.  The goal is to avoid the cost of
recreating the objects, based on the assumption that they are likely
to be used again soon.


=== ZODB3/ZODB/cPersistence.c 1.67 => 1.68 ===
--- ZODB3/ZODB/cPersistence.c:1.67	Tue Apr  1 12:33:23 2003
+++ ZODB3/ZODB/cPersistence.c	Wed Apr  2 11:50:49 2003
@@ -131,6 +131,7 @@
             self->ring.prev = home->prev;
 	    home->prev->next = &self->ring;
 	    home->prev = &self->ring;
+	    Py_INCREF(self);
         }
         self->state = cPersistent_CHANGED_STATE;
         /* Call the object's __setstate__() */
@@ -184,6 +185,8 @@
     self->ring.prev = NULL;
     self->ring.next = NULL;
     self->state = cPersistent_GHOST_STATE;
+    /* self->ring held a reference to the object. */
+    Py_DECREF(self);
 }
 
 static void


=== ZODB3/ZODB/cPickleCache.c 1.79 => 1.80 ===
--- ZODB3/ZODB/cPickleCache.c:1.79	Tue Apr  1 13:49:43 2003
+++ ZODB3/ZODB/cPickleCache.c	Wed Apr  2 11:50:49 2003
@@ -53,10 +53,12 @@
 
 Regime 3: Non-Ghost Objects
 
-Non-ghost objects are stored in two data structures. Firstly, in the
-dictionary along with everything else, with a *strong* reference.
-Secondly, they are stored in a doubly-linked-list which encodes the
-order in which these objects have been most recently used.
+Non-ghost objects are stored in two data structures: the dictionary
+mapping oids to objects and a doubly-linked list that encodes the
+order in which the objects were accessed.  The dictionary reference is
+borrowed, as it is for ghosts.  The list reference is a new reference;
+the list stores recently used objects, even if they are otherwise
+unreferenced, to avoid loading the object from the database again.
 
 The doubly-link-list nodes contain next and previous pointers linking
 together the cache and all non-ghost persistent objects.
@@ -762,8 +764,7 @@
     
     if (PyDict_SetItem(self->data, key, v) < 0) 
 	return -1;
-    /* Remove the reference used by the dict.  The cache should only
-       have borrowed references to objects. */
+    /* the dict should have a borrowed reference */
     Py_DECREF(v);
     
     p = (cPersistentObject *)v;
@@ -771,12 +772,14 @@
     p->cache = (PerCache *)self;
     if (p->state >= 0) {
 	/* insert this non-ghost object into the ring just 
-	   behind the home position */
+	   behind the home position. */
 	self->non_ghost_count++;
 	p->ring.next = &self->ring_home;
 	p->ring.prev =  self->ring_home.prev;
 	self->ring_home.prev->next = &p->ring;
 	self->ring_home.prev = &p->ring;
+	/* this list should have a new reference to the object */
+	Py_INCREF(v);
     }
     return 0;
 }
@@ -802,6 +805,8 @@
 	    p->ring.prev->next = p->ring.next;
 	    p->ring.prev = NULL;
 	    p->ring.next = NULL;
+	    /* The DelItem below will account for the reference
+	       held by the list. */
 	} else {
 	    /* This is a ghost object, so we havent kept a reference
 	       count on it.  For it have stayed alive this long