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

Tim Peters tim.one@comcast.net
Fri, 28 Jun 2002 15:58:38 -0400


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

Modified Files:
	BTreeTemplate.c 
Log Message:
BTree_split():  Beefed up docs; simplified code; added comments;
rearranged so that damaged info isn't left behind in case of a
persistence error; added another assert for "the other way" an empty
BTree may get created.


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.38 => 1.39 ===
 
 /*
-  Copy data from the current BTree to the newly created BTree, next.
-  Reset length to reflect the fact that we've given up some data.
-*/
+ * Move data from the current BTree, from index onward, to the newly created
+ * BTree 'next'.  self and next must both be activated.  If index is OOB (< 0
+ * or >= self->len), use self->len / 2 as the index (i.e., split at the
+ * midpoint).  self must have at least 2 children on entry, and index must
+ * be such that self and next each have at least one child at exit.  self's
+ * accessed time is updated.
+ *
+ * Return:
+ *    -1    error
+ *     0    OK
+ */
 static int
 BTree_split(BTree *self, int index, BTree *next)
 {
     int next_size;
-    ASSERT(self->len > 1, "split of empty tree", -1);
+    Sized *child;
 
     if (index < 0 || index >= self->len)
-	index = self->len/2;
+	index = self->len / 2;
 
     next_size = self->len - index;
+    ASSERT(index > 0, "split creates empty tree", -1);
     ASSERT(next_size > 0, "split creates empty tree", -1);
 
     next->data = BTree_Malloc(sizeof(BTreeItem) * next_size);
     if (!next->data)
 	return -1;
-    memcpy(next->data, self->data+index, sizeof(BTreeItem) * next_size);
-    next->size = next->len = next_size;
+    memcpy(next->data, self->data + index, sizeof(BTreeItem) * next_size);
+    next->size = next_size;  /* but don't set len until we succeed */
 
-    self->len = index;
-
-    if (SameType_Check(self, next->data->child)) {
-	PyPersist_INCREF((PyPersistObject *)next->data->child);
-	if (!PyPersist_IS_STICKY((PyPersistObject *)next->data->child))
-	    return -1;
-	next->firstbucket = BTREE(next->data->child)->firstbucket;
-	Py_XINCREF(next->firstbucket);
-	PyPersist_DECREF(BTREE(next->data->child));
-	PyPersist_SetATime(BTREE(next->data->child));
-    }
-    else {
-	next->firstbucket = BUCKET(next->data->child);
-	Py_XINCREF(next->firstbucket);
+    /* Set next's firstbucket.  self->firstbucket is still correct. */
+    child = next->data[0].child;
+    if (SameType_Check(self, child)) {
+        PER_USE_OR_RETURN(child, -1);
+	next->firstbucket = BTREE(child)->firstbucket;
+	PER_UNUSE(child);
     }
+    else
+	next->firstbucket = BUCKET(child);
+    Py_INCREF(next->firstbucket);
 
-    if (PER_CHANGED(self) < 0)
-      return -1;
-    return 0;
+    next->len = next_size;
+    self->len = index;
+    return PER_CHANGED(self) < 0 ? -1 : 0;
 }