Commit ce3c542c authored by Tim Peters's avatar Tim Peters

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).
parent c22307fb
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.67 2002/06/21 18:06:26 tim_one Exp $\n" #define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.68 2002/06/25 16:23:26 tim_one Exp $\n"
/* Sanity-check a BTree. This is a private helper for BTree_check. Return: /* Sanity-check a BTree. This is a private helper for BTree_check. Return:
* -1 Error. If it's an internal inconsistency in the BTree, * -1 Error. If it's an internal inconsistency in the BTree,
...@@ -265,56 +265,50 @@ BTree_split(BTree *self, int index, BTree *next) ...@@ -265,56 +265,50 @@ BTree_split(BTree *self, int index, BTree *next)
return 0; return 0;
} }
/* Split out data among two newly created BTrees, which become
out children.
*/
static int
BTree_clone(BTree *self)
{
/* 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 */ /* Fwd decl -- BTree_grow and BTree_split_root reference each other. */
UNLESS (d=PyMalloc(sizeof(BTreeItem)*2)) goto err; static int BTree_grow(BTree *self, int index, int noval);
/* Split ourself */ /* Split the root. This is a little special because the root isn't a child
if (BTree_split(self,-1,n2) < 0) goto err; * 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
/* Move our data to new BTree */ * latter. This leaves the root with two children.
n1->size=self->size; *
n1->len=self->len; * Return:
n1->data=self->data; * 0 OK
n1->firstbucket = self->firstbucket; * -1 error
Py_XINCREF(n1->firstbucket); *
* CAUTION: The caller must call PER_CHANGED on self.
/* Initialize our data to hold split data */ */
self->data = d; static int
self->len = 2; BTree_split_root(BTree *self, int noval)
self->size = 2; {
self->data->child = SIZED(n1); BTree *child;
COPY_KEY(self->data[1].key, n2->data->key); BTreeItem *d;
/* 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); /* Create a child BTree, and a new data vector for self. */
child = BTREE(PyObject_CallObject(OBJECT(self->ob_type), NULL));
if (!child) return -1;
return 0; d = PyMalloc(sizeof(BTreeItem) * 2);
if (!d) {
Py_DECREF(child);
return -1;
}
err: /* Move our data to new BTree. */
Py_XDECREF(n1); child->size = self->size;
Py_XDECREF(n2); child->len = self->len;
if (d) free(d); child->data = self->data;
return -1; 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 @@ BTree_grow(BTree *self, int index, int noval) ...@@ -417,7 +411,8 @@ BTree_grow(BTree *self, int index, int noval)
self->len++; 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 else
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment