[Zodb-checkins] CVS: Zope/lib/python/BTrees - BTreeTemplate.c:1.68
Tim Peters
tim.one@comcast.net
Tue, 25 Jun 2002 12:23:26 -0400
Update of /cvs-repository/Zope/lib/python/BTrees
In directory cvs.zope.org:/tmp/cvs-serv16279
Modified Files:
BTreeTemplate.c
Log Message:
BTree_clone(): Renamed to BTree_split_root(), and greatly simplified
the algorithm in a way I believe Jim suggested a few weeks ago (but that
I didn't understand then).
=== Zope/lib/python/BTrees/BTreeTemplate.c 1.67 => 1.68 ===
}
-/* Split out data among two newly created BTrees, which become
- out children.
-*/
+
+/* Fwd decl -- BTree_grow and BTree_split_root reference each other. */
+static int BTree_grow(BTree *self, int index, int noval);
+
+/* Split the root. This is a little special because the root isn't a child
+ * of anything else, and the root needs to retain its object identity. So
+ * this routine moves the root's data into a new child, and splits the
+ * latter. This leaves the root with two children.
+ *
+ * Return:
+ * 0 OK
+ * -1 error
+ *
+ * CAUTION: The caller must call PER_CHANGED on self.
+ */
static int
-BTree_clone(BTree *self)
+BTree_split_root(BTree *self, int noval)
{
- /* We've grown really big without anybody splitting us.
- We should split ourselves.
- */
- BTree *n1=0, *n2=0;
- BTreeItem *d=0;
-
- /* Create two BTrees to hold ourselves after split */
- UNLESS (n1=BTREE(PyObject_CallObject(OBJECT(self->ob_type), NULL)))
- return -1;
- UNLESS (n2=BTREE(PyObject_CallObject(OBJECT(self->ob_type), NULL)))
- goto err;
-
- /* Create a new data buffer to hold two BTrees */
- UNLESS (d=PyMalloc(sizeof(BTreeItem)*2)) goto err;
-
- /* Split ourself */
- if (BTree_split(self,-1,n2) < 0) goto err;
-
- /* Move our data to new BTree */
- n1->size=self->size;
- n1->len=self->len;
- n1->data=self->data;
- n1->firstbucket = self->firstbucket;
- Py_XINCREF(n1->firstbucket);
-
- /* Initialize our data to hold split data */
- self->data = d;
- self->len = 2;
- self->size = 2;
- self->data->child = SIZED(n1);
- COPY_KEY(self->data[1].key, n2->data->key);
-
- /* We take the unused reference from n2, so there's no reason to INCREF! */
- /* INCREF_KEY(self->data[1].key); */
-
- self->data[1].child = SIZED(n2);
-
- return 0;
-
-err:
- Py_XDECREF(n1);
- Py_XDECREF(n2);
- if (d) free(d);
- return -1;
+ BTree *child;
+ BTreeItem *d;
+
+ /* Create a child BTree, and a new data vector for self. */
+ child = BTREE(PyObject_CallObject(OBJECT(self->ob_type), NULL));
+ if (!child) return -1;
+
+ d = PyMalloc(sizeof(BTreeItem) * 2);
+ if (!d) {
+ Py_DECREF(child);
+ return -1;
+ }
+
+ /* Move our data to new BTree. */
+ child->size = self->size;
+ child->len = self->len;
+ child->data = self->data;
+ child->firstbucket = self->firstbucket;
+ Py_INCREF(child->firstbucket);
+
+ /* Point self to child and split the child. */
+ self->data = d;
+ self->len = 1;
+ self->size = 2;
+ self->data[0].child = SIZED(child); /* transfers reference ownership */
+ return BTree_grow(self, 0, noval);
}
/*
@@ -417,7 +411,8 @@
self->len++;
- if (self->len >= MAX_BTREE_SIZE(self) * 2) return BTree_clone(self);
+ if (self->len >= MAX_BTREE_SIZE(self) * 2) /* the root is huge */
+ return BTree_split_root(self, noval);
}
else
{