[Zodb-checkins] CVS: Zope/lib/python/BTrees - BucketTemplate.c:1.47 SetOpTemplate.c:1.28
Tim Peters
tim.one@comcast.net
Thu, 27 Jun 2002 18:09:33 -0400
Update of /cvs-repository/Zope/lib/python/BTrees
In directory cvs.zope.org:/tmp/cvs-serv4634
Modified Files:
BucketTemplate.c SetOpTemplate.c
Log Message:
New bucket_append() utility function. Redid part of multiunion() to
use it, but this is really a step on the way to speeding "lopsided
merges".
=== Zope/lib/python/BTrees/BucketTemplate.c 1.46 => 1.47 ===
/*
+ * Append a slice of the "from" bucket to self.
+ *
+ * self Append (at least keys) to this bucket. self must be activated
+ * upon entry, and remains activated at exit. If copyValues
+ * is true, self must be empty or already have a non-NULL values
+ * pointer. self's access and modification times aren't updated.
+ * from The bucket from which to take keys, and possibly values. from
+ * must be activated upon entry, and remains activated at exit.
+ * If copyValues is true, from must have a non-NULL values
+ * pointer. self and from must not be the same. from's access
+ * time isn't updated.
+ * i, n The slice from[i : i+n] is appended to self. Must have
+ * i >= 0, n > 0 and i+n <= from->len.
+ * copyValues Boolean. If true, copy values from the slice as well as keys.
+ * In this case, from must have a non-NULL values pointer, and
+ * self must too (unless self is empty, in which case a values
+ * vector will be allocated for it).
+ * overallocate Boolean. If self doesn't have enough room upon entry to hold
+ * all the appended stuff, then if overallocate is false exactly
+ * enough room will be allocated to hold the new stuff, else if
+ * overallocate is true an excess will be allocated. overallocate
+ * may be a good idea if you expect to append more stuff to self
+ * later; else overallocate should be false.
+ *
+ * CAUTION: If self is empty upon entry (self->size == 0), and copyValues is
+ * false, then no space for values will get allocated. This can be a trap if
+ * the caller intends to copy values itself.
+ *
+ * Return
+ * -1 Error.
+ * 0 OK.
+ */
+static int
+bucket_append(Bucket *self, Bucket *from, int i, int n,
+ int copyValues, int overallocate)
+{
+ int newlen;
+
+ assert(self && from && self != from);
+ assert(i >= 0);
+ assert(n > 0);
+ assert(i+n <= from->len);
+
+ /* Make room. */
+ newlen = self->len + n;
+ if (newlen > self->size) {
+ int newsize = newlen;
+ if (overallocate) /* boost by 25% -- pretty arbitrary */
+ newsize += newsize >> 2;
+ if (Bucket_grow(self, newsize, ! copyValues) < 0)
+ return -1;
+ }
+ assert(newlen <= self->size);
+
+ /* Copy stuff. */
+ memcpy(self->keys + self->len, from->keys + i, n * sizeof(KEY_TYPE));
+ if (copyValues) {
+ assert(self->values);
+ assert(from->values);
+ memcpy(self->values + self->len, from->values + i,
+ n * sizeof(VALUE_TYPE));
+ }
+ self->len = newlen;
+
+ /* Bump refcounts. */
+#ifdef KEY_TYPE_IS_PYOBJECT
+ {
+ int j;
+ PyObject **p = from->keys + i;
+ for (j = 0; j < n; ++j, ++p) {
+ Py_INCREF(*p);
+ }
+ }
+#endif
+#ifdef VALUE_TYPE_IS_PYOBJECT
+ if (copyValues) {
+ int j;
+ PyObject **p = from->values + i;
+ for (j = 0; j < n; ++j, ++p) {
+ Py_INCREF(*p);
+ }
+ }
+#endif
+ return 0;
+}
+
+
+/*
** _bucket_set: Assign a value to a key in a bucket, delete a key+value
** pair, or just insert a key.
**
=== Zope/lib/python/BTrees/SetOpTemplate.c 1.27 => 1.28 ===
/* If set is a bucket, do a straight resize + memcpy. */
if (set->ob_type == (PyTypeObject*)&SetType ||
- set->ob_type == (PyTypeObject*)&BucketType) {
- Sized *theset = SIZED(set);
- int setsize;
- int size_desired;
+ set->ob_type == (PyTypeObject*)&BucketType)
+ {
+ Bucket *b = BUCKET(set);
+ int status;
- UNLESS (PER_USE(theset)) goto Error;
- setsize = theset->len;
- size_desired = result->len + setsize;
- /* If there are more to come, overallocate by 25% (arbitrary). */
- if (i < n-1)
- size_desired += size_desired >> 2;
- if (size_desired && size_desired > result->size) {
- if (Bucket_grow(result, size_desired, 1) < 0) {
- PER_ALLOW_DEACTIVATION(theset);
- PER_ACCESSED(theset);
- goto Error;
- }
- }
- memcpy(result->keys + result->len,
- BUCKET(theset)->keys,
- setsize * sizeof(KEY_TYPE));
- result->len += setsize;
- PER_ALLOW_DEACTIVATION(theset);
- PER_ACCESSED(theset);
+ UNLESS (PER_USE(b)) goto Error;
+ status = bucket_append(result, b, 0, b->len, 0, i < n-1);
+ PER_UNUSE(b);
+ if (status < 0) goto Error;
}
else {
/* No cheap way: iterate over set's elements one at a time. */