[Zope-Checkins] CVS: Zope3/lib/python/Persistence/BTrees - BTreeTemplate.c:1.33

Tim Peters tim.one@comcast.net
Fri, 21 Jun 2002 01:44:21 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence/BTrees
In directory cvs.zope.org:/tmp/cvs-serv13468

Modified Files:
	BTreeTemplate.c 
Log Message:
All internal consistency checks based on refcounts, in both old and new
code, are bogus when PERSISTENCE is #define'd.  Repair them.


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.32 => 1.33 ===
     /* Non-empty BTree. */
     CHECK(self->firstbucket != NULL, "Non-empty BTree has NULL firstbucket");
+
+    /* Obscure:  The first bucket is pointed to at least by self->firstbucket
+     * and data[0].child of whichever BTree node it's a child of.  However,
+     * if persistence is enabled then the latter BTree node may be a ghost
+     * at this point, and so its pointers "don't count":  we can only rely
+     * on self's pointers being intact.
+     */
+#ifdef PERSISTENT
+    CHECK(self->firstbucket->ob_refcnt >= 1,
+          "Non-empty BTree firstbucket has refcount < 1");
+#else
     CHECK(self->firstbucket->ob_refcnt >= 2,
           "Non-empty BTree firstbucket has refcount < 2");
+#endif
+
     for (i = 0; i < self->len; ++i) {
         CHECK(self->data[i].child != NULL, "BTree has NULL child");
     }
+
     if (SameType_Check(self, self->data[0].child)) {
         /* Our children are also BTrees. */
         child = self->data[0].child;
@@ -93,7 +107,11 @@
                   "BTree children have different types");
             CHECK(child->len >= 1, "Bucket length < 1"); /* no empty buckets! */
             CHECK(child->len <= child->size, "Bucket len > size");
+#ifdef PERSISTENT
+            CHECK(child->ob_refcnt >= 1, "Bucket has refcount < 1");
+#else
             CHECK(child->ob_refcnt >= 2, "Bucket has refcount < 2");
+#endif
             if (i == self->len - 1)
                 bucketafter = nextbucket;
             else
@@ -259,7 +277,8 @@
 	Py_XINCREF(next->firstbucket);
 	PyPersist_DECREF(BTREE(next->data->child));
 	PyPersist_SetATime(BTREE(next->data->child));
-    } else {
+    }
+    else {
 	next->firstbucket = BUCKET(next->data->child);
 	Py_XINCREF(next->firstbucket);
     }
@@ -524,8 +543,19 @@
     const int len = self->len;
 
     if (self->firstbucket) {
+        /* Obscure:  The first bucket is pointed to at least by
+         * self->firstbucket and data[0].child of whichever BTree node it's
+         * a child of.  However, if persistence is enabled then the latter
+         * BTree node may be a ghost at this point, and so its pointers "don't
+         * count":  we can only rely on self's pointers being intact.
+         */
+#ifdef PERSISTENT
+	ASSERT(self->firstbucket->ob_refcnt > 0,
+	       "Invalid firstbucket pointer", -1);
+#else
 	ASSERT(self->firstbucket->ob_refcnt > 1,
 	       "Invalid firstbucket pointer", -1);
+#endif
 	Py_DECREF(self->firstbucket);
 	self->firstbucket = NULL;
     }
@@ -896,7 +926,8 @@
 	    ASSIGN(r, Py_BuildValue("OO", r, self->firstbucket));
         }
 
-    } else {
+    }
+    else {
 	r = Py_None;
 	Py_INCREF(r);
     }
@@ -968,11 +999,13 @@
 	    if (noval) {
 		if (_set_setstate(BUCKET(d->child), v) < 0)
 		    return -1;
-	    } else {
+	    }
+	    else {
 		if (_bucket_setstate(BUCKET(d->child), v) < 0)
 		    return -1;
 	    }
-	} else {
+	}
+	else {
 	    d->child = (Sized *)v;
 	    Py_INCREF(v);
 	}
@@ -990,8 +1023,12 @@
     }
     self->firstbucket = BUCKET(firstbucket);
     Py_INCREF(firstbucket);
+#ifndef PERSISTENT
+    /* firstbucket is also the child of some BTree node, but that node may
+     * be a ghost if persistence is enabled.
+     */
     assert(self->firstbucket->ob_refcnt > 1);
-
+#endif
     self->len = len;
 
     return 0;