[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;