[Zodb-checkins] CVS: Zope3/lib/python/Persistence/BTrees - BTreeModuleTemplate.c:1.1.2.8 BTreeTemplate.c:1.1.2.7 BucketTemplate.c:1.1.2.8

Jeremy Hylton jeremy@zope.com
Sat, 2 Mar 2002 01:33:25 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	BTreeModuleTemplate.c BTreeTemplate.c BucketTemplate.c 
Log Message:
Use PyPersist_INCREF() and PyPersist_DECREF().



=== Zope3/lib/python/Persistence/BTrees/BTreeModuleTemplate.c 1.1.2.7 => 1.1.2.8 ===
     while (1) {
 	/* XXX Doesn't this leak a reference to first on error? */
-	PER_USE_OR_RETURN(first, NULL);
+	PyPersist_INCREF(first);
+	if (!PyPersist_IS_STICKY(first))
+	    return NULL;
 	if (first->next == current) {
 	    PER_ALLOW_DEACTIVATION(first);
 	    PER_ACCESSED(first);


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.1.2.6 => 1.1.2.7 ===
   UNLESS (copied) return NULL;
 
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   if (self->len)
     {
@@ -62,7 +64,7 @@
         r=PyInt_FromLong(0);
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 }    
@@ -98,17 +100,19 @@
     self->len = index;
 
     if (SameType_Check(self, next->data->value)) {
-	PER_USE_OR_RETURN(BTREE(next->data->value), -1);
+	PyPersist_INCREF((PyPersistObject *)next->data->value);
+	if (!PyPersist_IS_STICKY((PyPersistObject *)next->data->value))
+	    return -1;
 	next->firstbucket = BTREE(next->data->value)->firstbucket;
 	Py_XINCREF(next->firstbucket);
-	PER_ALLOW_DEACTIVATION(BTREE(next->data->value));
+	PyPersist_DECREF(BTREE(next->data->value));
 	PER_ACCESSED(BTREE(next->data->value));
     } else {
 	next->firstbucket = BUCKET(next->data->value);
 	Py_XINCREF(next->firstbucket);
     }
 
-    PER_CHANGED(self);
+    PyPersist_CHANGED(self);
     return 0;
 }
 
@@ -213,12 +217,14 @@
 	  return -1;
 
       /* Now split between the original (v) and the new (e) at the midpoint*/
-      PER_USE_OR_RETURN((Bucket *)v, -1);
+      PyPersist_INCREF((PyPersistObject *)v);
+      if (!PyPersist_IS_STICKY((PyPersistObject *)v))
+	  return -1;
       if (SameType_Check(self, v))
           i = BTree_split((BTree *)v, -1, (BTree *)e);
       else
           i = bucket_split((Bucket *)v, -1, (Bucket *)e);
-      PER_ALLOW_DEACTIVATION((Bucket *)v);
+      PyPersist_DECREF((Bucket *)v);
 
       if (i < 0)
           return -1;
@@ -283,9 +289,11 @@
 
     self = (BTree *)o;
 
-    PER_USE_OR_RETURN(self, NULL);
+    PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
     ASSIGN(o, OBJECT(BTree_lastBucket(self)));
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
 
     return (Bucket *)o;
@@ -296,7 +304,9 @@
 {
     Bucket *b;
 
-    PER_USE_OR_RETURN(self, -1);
+    PyPersist_INCREF(self);
+    if (!PyPersist_IS_STICKY(self))
+	return -1;
 
     b = BTree_lastBucket(self);
     if (b == NULL)
@@ -304,13 +314,13 @@
     if (Bucket_deleteNextBucket(b) < 0) 
 	goto err;
 
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
 
     return 0;
 
  err:
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     return -1;
 }
 
@@ -337,7 +347,9 @@
     if (!copied) 
 	return -1;
 
-    PER_USE_OR_RETURN(self, -1);
+    PyPersist_INCREF(self);
+    if (!PyPersist_IS_STICKY(self))
+	return -1;
 
     if (!self->len) {
 	if (value) {
@@ -434,7 +446,7 @@
 			    ASSIGNB(self->firstbucket, 
 				    BTREE(self->data->value)->firstbucket);
 			    Py_XINCREF(self->firstbucket);
-			    PER_ALLOW_DEACTIVATION(BTREE(self->data->value));
+			    PyPersist_DECREF(BTREE(self->data->value));
 			    PER_ACCESSED(BTREE(self->data->value));
                         } else {
 			    ASSIGNB(self->firstbucket, 
@@ -461,16 +473,16 @@
     && BUCKET(self->data->value)->po_oid == NULL /* It's in our record*/
 	    )
 	) 
-	if (PER_CHANGED(self) < 0) 
+	if (PyPersist_CHANGED(self) < 0) 
 	    goto err;
 #endif
   
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     return grew;
 
  err:
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     return -1;
 }
@@ -557,22 +569,26 @@
 static PyObject *
 BTree_clear(BTree *self)
 {
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   if (self->len)
     {
-      if (_BTree_clear(self) < 0) goto err;
-      if (PER_CHANGED(self) < 0) goto err;
+      if (_BTree_clear(self) < 0) 
+	  goto err;
+      if (PyPersist_CHANGED(self) < 0) 
+	  goto err;
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
 
   Py_INCREF(Py_None); 
   return Py_None;
 
 err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return NULL;
 }
@@ -583,7 +599,9 @@
     PyObject *r = NULL, *o;
     int i, l;
 
-    PER_USE_OR_RETURN(self, NULL);
+    PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
     if (self->len) {
 	r = PyTuple_New(self->len * 2 - 1);
@@ -622,13 +640,13 @@
 	Py_INCREF(r);
     }  
     
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     
     return r;
     
  err:
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     Py_XDECREF(r);
     return NULL;
@@ -722,7 +740,7 @@
 
     PER_PREVENT_DEACTIVATION(self); 
     r = _BTree_setstate(self, arg, 0);
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     
     if (r < 0) 
@@ -842,9 +860,11 @@
   if (SameType_Check(self, self->data[min].value)) 
     {
       self=BTREE(self->data[min].value);
-      PER_USE_OR_RETURN(self, -1);
+      PyPersist_INCREF(self);
+      if (!PyPersist_IS_STICKY(self))
+	  return -1;
       i = BTree_findRangeEnd(self, keyarg, low, bucket, offset);
-      PER_ALLOW_DEACTIVATION(self);
+      PyPersist_DECREF(self);
       PER_ACCESSED(self);
     }
   else
@@ -877,7 +897,9 @@
   
   UNLESS (PyArg_ParseTuple(args, "|O", &key)) return NULL;
   
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   UNLESS (self->data && self->len) goto empty;
   
@@ -890,7 +912,7 @@
           if (rc < 0) goto err;
           goto empty;
         } 
-      PER_ALLOW_DEACTIVATION(self);
+      PyPersist_DECREF(self);
       PER_ACCESSED(self);
       PER_USE_OR_RETURN(bucket, NULL);
     }
@@ -898,7 +920,7 @@
     {
       bucket = self->firstbucket;
       Py_INCREF(bucket);
-      PER_ALLOW_DEACTIVATION(self);
+      PyPersist_DECREF(self);
       PER_ACCESSED(self);
       PER_USE_OR_RETURN(bucket, NULL);
       offset = 0;
@@ -914,7 +936,7 @@
   else
     {
       bucket = BTree_lastBucket(self);
-      PER_ALLOW_DEACTIVATION(self);
+      PyPersist_DECREF(self);
       PER_ACCESSED(self);
       PER_USE_OR_RETURN(bucket, NULL);
       if (bucket->len)
@@ -930,7 +952,7 @@
     }
   
   COPY_KEY_TO_OBJECT(key, bucket->keys[offset]);
-  PER_ALLOW_DEACTIVATION(bucket);
+  PyPersist_DECREF(bucket);
   PER_ACCESSED(bucket);
   Py_DECREF(bucket);
 
@@ -940,11 +962,11 @@
   PyErr_SetString(PyExc_ValueError, "empty tree");
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   if (bucket)  
     {
-      PER_ALLOW_DEACTIVATION(bucket);
+      PyPersist_DECREF(bucket);
       PER_ACCESSED(bucket);
       Py_DECREF(bucket);
     }
@@ -982,7 +1004,9 @@
   
   UNLESS (! args || PyArg_ParseTuple(args,"|OO",&f, &l)) return NULL;
   
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   UNLESS (self->data && self->len) goto empty;
 
@@ -1019,11 +1043,11 @@
       highbucket = BTree_lastBucket(self);
       UNLESS (PER_USE(highbucket)) goto err;
       highoffset = highbucket->len - 1; 
-      PER_ALLOW_DEACTIVATION(highbucket);      
+      PyPersist_DECREF(highbucket);      
       PER_ACCESSED(highbucket);
     }
   
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   
   f=newBTreeItems(type, lowbucket, lowoffset, highbucket, highoffset);
@@ -1032,12 +1056,12 @@
   return f;
   
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return NULL;
 
  empty:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return newBTreeItems(type, 0, 0, 0, 0);
 }
@@ -1078,7 +1102,9 @@
   int copied=1;
   SetIteration it={0,0};
 
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   COPY_VALUE_FROM_ARG(min, omin, copied);
   UNLESS(copied) return NULL;
@@ -1124,12 +1150,12 @@
   UNLESS (item) goto err;
   Py_DECREF(item);
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_XDECREF(r);
   Py_XDECREF(it.set);
@@ -1299,7 +1325,7 @@
   PER_USE_OR_RETURN(self, -1); 
   b = self->firstbucket;
   Py_XINCREF(b);
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
 
   while (b != NULL) 
@@ -1309,14 +1335,14 @@
       if (nonzero && c)
         {
           /* Short-circuit if all we care about is nonempty */
-          PER_ALLOW_DEACTIVATION(b);
+          PyPersist_DECREF(b);
           PER_ACCESSED(b);
           Py_DECREF(b);
           return 1;
         }
       n = b->next;
       Py_XINCREF(n);
-      PER_ALLOW_DEACTIVATION(b);
+      PyPersist_DECREF(b);
       PER_ACCESSED(b);
       ASSIGNB(b, n);
     }


=== Zope3/lib/python/Persistence/BTrees/BucketTemplate.c 1.1.2.7 => 1.1.2.8 ===
   UNLESS (copied) return NULL;
 
-  PER_USE_OR_RETURN(self, NULL);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return NULL;
 
   for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2)
     {
@@ -52,14 +54,14 @@
 	    {
               COPY_VALUE_TO_OBJECT(r, self->values[i]);
 	    }
-	  PER_ALLOW_DEACTIVATION(self);
+	  PyPersist_DECREF(self);
           PER_ACCESSED(self);
 	  return r;
 	}
       else max=i;
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   if (has_key) return PyInt_FromLong(0);
   PyErr_SetObject(PyExc_KeyError, keyarg);
@@ -132,7 +134,9 @@
   COPY_KEY_FROM_ARG(key, keyarg, copied);
   UNLESS(copied) return -1;
 
-  PER_USE_OR_RETURN(self, -1);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return -1;
 
   for (min=0, max=l=self->len, i=max/2; i != l; l=i, i=(min+max)/2)
     {
@@ -151,7 +155,7 @@
 #ifdef VALUE_SAME
                   if (VALUE_SAME(self->values[i], value))
                     { /* short-circuit if no change */
-                      PER_ALLOW_DEACTIVATION(self);
+                      PyPersist_DECREF(self);
                       PER_ACCESSED(self);
                       return 0;
                     }
@@ -162,7 +166,7 @@
                   INCREF_VALUE(self->values[i]);
                   if (PER_CHANGED(self) < 0) goto err;
                 }
-	      PER_ALLOW_DEACTIVATION(self);
+	      PyPersist_DECREF(self);
               PER_ACCESSED(self);
 	      return 0;
 	    }
@@ -197,7 +201,7 @@
 		}
 
 	      if (PER_CHANGED(self) < 0) goto err;
-	      PER_ALLOW_DEACTIVATION(self);
+	      PyPersist_DECREF(self);
               PER_ACCESSED(self);
 	      return 1;
 	    }
@@ -238,12 +242,12 @@
   self->len++;
 
   if (PER_CHANGED(self) < 0) goto err;
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return 1;
 
 err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return -1;
 }
@@ -398,10 +402,12 @@
 static int
 Bucket_nextBucket(Bucket *self, Bucket **r)
 {
-    PER_USE_OR_RETURN(self, -1);
+    PyPersist_INCREF(self);
+    if (!PyPersist_IS_STICKY(self))
+	return -1;
     *r = self->next;
     Py_XINCREF(*r);
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     return 0;
 }
@@ -409,21 +415,22 @@
 static int 
 Bucket_deleteNextBucket(Bucket *self)
 {
-    PER_USE_OR_RETURN(self, -1);
+    PyPersist_INCREF(self);
+    if (!PyPersist_IS_STICKY(self))
+	return -1;
     if (self->next) {
 	Bucket *n;
 	if (Bucket_nextBucket(self->next, &n) < 0) 
 	    goto err;
-/*	fprintf(stderr, "delete %d\n", self->next->ob_refcnt); */
 	Py_DECREF(self->next);
 	self->next = n;
 	PER_CHANGED(self);
     }
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     return 0;
  err:
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     return -1;
 }
@@ -451,7 +458,9 @@
   COPY_KEY_FROM_ARG(key, keyarg, copied);
   UNLESS (copied) return -1;
 
-  PER_USE_OR_RETURN(self, -1);
+  PyPersist_INCREF(self);
+  if (!PyPersist_IS_STICKY(self))
+      return -1;
 
   for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2) 
     {
@@ -460,7 +469,7 @@
 	min=i;
       else if (cmp == 0)
         {
-          PER_ALLOW_DEACTIVATION(self);
+          PyPersist_DECREF(self);
           PER_ACCESSED(self);
           *offset=i;
           return 1;
@@ -491,7 +500,7 @@
         }
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
 
   return i;
@@ -522,14 +531,14 @@
   else offset = self->len -1;
 
   COPY_KEY_TO_OBJECT(key, self->keys[offset]);
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
 
   return key;
   
  empty:
   PyErr_SetString(PyExc_ValueError, "empty bucket");
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return NULL;
 }
@@ -617,12 +626,12 @@
 	  goto err;
   }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_XDECREF(r);
   return NULL;
@@ -657,12 +666,12 @@
       if (PyList_SetItem(r, i-low, v) < 0) goto err;
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_XDECREF(r);
   return NULL;
@@ -707,12 +716,12 @@
       item = 0;
     }
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_XDECREF(r);
   Py_XDECREF(item);
@@ -771,12 +780,12 @@
   UNLESS (item) goto err;
   Py_DECREF(item);
 
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return r;
 
  err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_XDECREF(r);
   Py_XDECREF(item);
@@ -839,13 +848,13 @@
       if (PER_CHANGED(self) < 0) 
 	  goto err;
   }
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   Py_INCREF(Py_None); 
   return Py_None;
 
 err:
-  PER_ALLOW_DEACTIVATION(self);
+  PyPersist_DECREF(self);
   PER_ACCESSED(self);
   return NULL;
 }
@@ -895,13 +904,13 @@
 	state = Py_BuildValue("(O)", items);
     Py_DECREF(items);
     
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     
     return state;
     
  err:
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     Py_XDECREF(items);
     return NULL;
@@ -980,7 +989,7 @@
 
     PER_PREVENT_DEACTIVATION(self); 
     r = _bucket_setstate(self, state);
-    PER_ALLOW_DEACTIVATION(self);
+    PyPersist_DECREF(self);
     PER_ACCESSED(self);
     
     if (r < 0) 
@@ -1027,53 +1036,49 @@
 static PyObject *
 _bucket__p_resolveConflict(PyObject *ob_type, PyObject *s[3])
 {
-  PyObject *r=0, *a;
-  Bucket *b[3];
-  int i;
+    PyObject *r = NULL, *meth = NULL, *a = NULL;
+    Bucket *b[3];
+    int i;
   
-  for (i=0; i < 3; i++)
-    {
-      if ((b[i]=(Bucket*)PyObject_CallObject(OBJECT(ob_type), NULL)))
-        {
-          if ((s[i] == Py_None))  /* None is equivalent to empty, for BTrees */
-            continue;
-          ASSIGN(r, PyObject_GetAttr(OBJECT(b[i]), __setstate___str));
-          if ((a=PyTuple_New(1)))
-            {
-              if (r)
-                {
-                  PyTuple_SET_ITEM(a, 0, s[i]);
-                  Py_INCREF(s[i]);
-                  ASSIGN(r, PyObject_CallObject(r, a));
-                }
-              Py_DECREF(a);
-              if (r) continue;
-            }
-        }
-      Py_XDECREF(r);
-      while (--i >= 0)
-        {
-          Py_DECREF(b[i]);
-        }
-      return NULL;
-    }
-  Py_DECREF(r);
-  r=NULL;
-
-  if (b[0]->next != b[1]->next || b[0]->next != b[2]->next)
-    {
-      merge_error(-1, -1, -1, 0);
-      goto err;
+    for (i=0; i < 3; i++) {
+	b[i] = (Bucket*)PyObject_CallObject((PyObject *)ob_type, NULL);
+	if (b[i]) {
+	    if (s[i] == Py_None) /* None is equivalent to empty, for BTrees */
+		continue;
+	    meth = PyObject_GetAttr((PyObject *)b[i], __setstate___str);
+	    if (meth == NULL)
+		goto loop_err;
+	    a = PyTuple_New(1);
+	    if (a == NULL)
+		goto loop_err;
+	    PyTuple_SET_ITEM(a, 0, s[i]);
+	    Py_INCREF(s[i]);
+	    r = PyObject_CallObject(meth, a);
+	    Py_DECREF(a);
+	    Py_DECREF(meth);
+	    if (r) {
+		Py_DECREF(r);
+		continue;
+	    }
+	loop_err:
+	    while (--i >= 0)
+		Py_DECREF(b[i]);
+	    Py_XDECREF(a);
+	    Py_XDECREF(meth);
+	    return NULL;
+	}
     }
-
-  r=bucket_merge(b[0], b[1], b[2]);
-
- err:
-  Py_DECREF(b[0]);
-  Py_DECREF(b[1]);
-  Py_DECREF(b[2]);
-
-  return r;
+    
+    if (b[0]->next != b[1]->next || b[0]->next != b[2]->next)
+	merge_error(-1, -1, -1, 0);
+    else
+	r = bucket_merge(b[0], b[1], b[2]);
+    
+    Py_DECREF(b[0]);
+    Py_DECREF(b[1]);
+    Py_DECREF(b[2]);
+    
+    return r;
 }
 
 static PyObject *
@@ -1198,12 +1203,14 @@
 static int
 Bucket_length( Bucket *self)
 {
-  int r;
-  PER_USE_OR_RETURN(self, -1);
-  r=self->len;
-  PER_ALLOW_DEACTIVATION(self);
-  PER_ACCESSED(self);
-  return r;
+    int r;
+    PyPersist_INCREF(self);
+    if (!PyPersist_IS_STICKY(self))
+	return -1;
+    r = self->len;
+    PyPersist_DECREF(self);
+    PER_ACCESSED(self);
+    return r;
 }
 
 static PyMappingMethods Bucket_as_mapping = {
@@ -1304,7 +1311,7 @@
           PER_ACCESSED(BUCKET(i->set));
         }
 
-      PER_ALLOW_DEACTIVATION(BUCKET(i->set));
+      PyPersist_DECREF(BUCKET(i->set));
     }