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

Jeremy Hylton jeremy@zope.com
Wed, 12 Jun 2002 19:48:33 -0400


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

Modified Files:
	BTreeModuleTemplate.c BTreeTemplate.c 
Log Message:
Define _bucket_type on BTree and TreeSet objects and use it to make buckets.

The class attribute is initialized to point to BucketType or SetType
as appropriate, but a subclass could override it to define a custom
bucket type.

XXX Should we check that the factory actually returns something of the
appropriate type? How?  The C code here is going to depend on any
custom bucket type having the same layout at the C level.

Add BTree_newBucket() that constructs a bucket by looking up the class
attribute.


=== Zope3/lib/python/Persistence/BTrees/BTreeModuleTemplate.c 1.2 => 1.3 ===
 #define MODULE_NAME "Persistence.BTrees." MOD_NAME_PREFIX "BTree."
 
-static PyObject *sort_str, *reverse_str, *__setstate___str;
+static PyObject *sort_str, *reverse_str, *__setstate___str,
+    *_bucket_type_str;
 static PyObject *ConflictError = NULL;
 
 static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
@@ -444,86 +445,92 @@
     type->tp_base = PyPersist_BASE_TYPE;
 
     if (PyType_Ready(type) < 0)
-	return -1;
+	return 0;
 
-    /* PyPersist_Type defines a tp_dictoffset so that classes that
-       mixin Persistent can have an __dict__.  But this messes up the
-       goal to share the type between C objects using PyPersist_HEAD
-       and PyPersist_INSTANCE_HEAD.
-
-       A type like a BTree should not have an __dict__, so
-       tp_dictoffset should be zero.  The tp_dictoffset gets inherited
-       from tp_base == PyPersist_Type.
-
-       XXX is this kosher?
-    */
-    type->tp_dictoffset = 0;
-    return 0;
+    return 1;
 }
 
 void
 INITMODULE (void)
 {
-  PyObject *m, *d, *c;
+    PyObject *m, *d, *c;
 
-  sort_str = PyString_InternFromString("sort");
-  if (!sort_str)
-      return;
-  reverse_str = PyString_InternFromString("reverse");
-  if (!reverse_str)
-      return;
-  __setstate___str = PyString_InternFromString("__setstate__");
-  if (!__setstate___str)
-      return;
-
-  /* Grab the ConflictError class */
-  m = PyImport_ImportModule("Persistence.BTrees.Exception");
-  if (m != NULL) {
+    sort_str = PyString_InternFromString("sort");
+    if (!sort_str)
+	return;
+    reverse_str = PyString_InternFromString("reverse");
+    if (!reverse_str)
+	return;
+    __setstate___str = PyString_InternFromString("__setstate__");
+    if (!__setstate___str)
+	return;
+    _bucket_type_str = PyString_InternFromString("_bucket_type");
+    if (!_bucket_type_str)
+	return;
+
+    /* Grab the ConflictError class */
+    m = PyImport_ImportModule("Persistence.BTrees.Exception");
+    if (m != NULL) {
   	c = PyObject_GetAttrString(m, "BTreesConflictError");
   	if (c != NULL)
-  		ConflictError = c;
+	    ConflictError = c;
 	Py_DECREF(m);
-  }
+    }
 
-  if (ConflictError == NULL) {
+    if (ConflictError == NULL) {
   	Py_INCREF(PyExc_ValueError);
 	ConflictError=PyExc_ValueError;
-  }
+    }
 
 #ifdef INTSET_H
-  UNLESS(d = PyImport_ImportModule("intSet")) return;
-  UNLESS(intSetType = PyObject_GetAttrString (d, "intSet")) return;
-  Py_DECREF (d);
+    UNLESS(d = PyImport_ImportModule("intSet")) return;
+    UNLESS(intSetType = PyObject_GetAttrString (d, "intSet")) return;
+    Py_DECREF (d);
 #endif
 
-  /* Initialize the PyPersist_C_API and the type objects. */
-  PyPersist_C_API = PyCObject_Import("Persistence.cPersistence", "C_API");
-  if (PyPersist_C_API == NULL)
-      return;
-
-  BTreeItemsType.ob_type = &PyType_Type;
-  init_persist_type(&BucketType);
-  init_persist_type(&BTreeType);
-  init_persist_type(&SetType);
-  init_persist_type(&TreeSetType);
-
-  /* Create the module and add the functions */
-  m = Py_InitModule4("_" MOD_NAME_PREFIX "BTree",
-		     module_methods, BTree_module_documentation,
-		     (PyObject *)NULL, PYTHON_API_VERSION);
-
-  /* Add some symbolic constants to the module */
-  d = PyModule_GetDict(m);
-  if (PyDict_SetItemString(d, MOD_NAME_PREFIX "Bucket",
-			   (PyObject *)&BucketType) < 0)
-      return;
-  if (PyDict_SetItemString(d, MOD_NAME_PREFIX "BTree",
-			   (PyObject *)&BTreeType) < 0)
-      return;
-  if (PyDict_SetItemString(d, MOD_NAME_PREFIX "Set",
-			   (PyObject *)&SetType) < 0)
-      return;
-  if (PyDict_SetItemString(d, MOD_NAME_PREFIX "TreeSet",
-			   (PyObject *)&TreeSetType) < 0)
-      return;
+    /* Initialize the PyPersist_C_API and the type objects. */
+    PyPersist_C_API = PyCObject_Import("Persistence.cPersistence", "C_API");
+    if (PyPersist_C_API == NULL)
+	return;
+
+    BTreeItemsType.ob_type = &PyType_Type;
+    if (!init_persist_type(&BucketType))
+	return;
+    if (!init_persist_type(&BTreeType))
+	return;
+    if (!init_persist_type(&SetType))
+	return;
+    if (!init_persist_type(&TreeSetType))
+	return;
+
+    if (PyDict_SetItem(BTreeType.tp_dict, _bucket_type_str,
+		       (PyObject *)&BucketType) < 0) {
+	fprintf(stderr, "btree failed\n");
+	return;
+    }
+    if (PyDict_SetItem(TreeSetType.tp_dict, _bucket_type_str,
+		       (PyObject *)&SetType) < 0) {
+	fprintf(stderr, "bucket failed\n");
+	return;
+    }
+
+    /* Create the module and add the functions */
+    m = Py_InitModule4("_" MOD_NAME_PREFIX "BTree",
+		       module_methods, BTree_module_documentation,
+		       (PyObject *)NULL, PYTHON_API_VERSION);
+
+    /* Add some symbolic constants to the module */
+    d = PyModule_GetDict(m);
+    if (PyDict_SetItemString(d, MOD_NAME_PREFIX "Bucket",
+			     (PyObject *)&BucketType) < 0)
+	return;
+    if (PyDict_SetItemString(d, MOD_NAME_PREFIX "BTree",
+			     (PyObject *)&BTreeType) < 0)
+	return;
+    if (PyDict_SetItemString(d, MOD_NAME_PREFIX "Set",
+			     (PyObject *)&SetType) < 0)
+	return;
+    if (PyDict_SetItemString(d, MOD_NAME_PREFIX "TreeSet",
+			     (PyObject *)&TreeSetType) < 0)
+	return;
 }


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.9 => 1.10 ===
 }
 
+/* Create a new bucket for the BTree or TreeSet using the class attribute
+   _bucket_type, which is normally initialized to BucketType or SetType
+   as appropriate.
+*/
+static Sized *
+BTree_newBucket(BTree *self)
+{
+    PyObject *factory;
+    /* _bucket_type_str defined in BTreeModuleTemplate.c */
+
+    factory = PyObject_GetAttr((PyObject *)self->ob_type, _bucket_type_str);
+    if (factory == NULL)
+	return NULL;
+    /* XXX Should we check that the factory actually returns something
+       of the appropriate type? How?  The C code here is going to
+       depend on any custom bucket type having the same layout at the
+       C level.
+    */
+    return (Sized *)PyObject_CallObject(factory, NULL);
+}
+
 /*
   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.
@@ -261,10 +282,7 @@
       if (self->len >= MAX_BTREE_SIZE(self) * 2)
 	  return BTree_clone(self);
   } else {
-      if (noval)
-          d->child = (Sized *)PyObject_CallObject((PyObject *)&SetType, NULL);
-      else
-          d->child = (Sized *)PyObject_CallObject((PyObject *)&BucketType, NULL);
+      d->child = BTree_newBucket(self);
       if (d->child == NULL)
 	  return -1;
       self->len = 1;
@@ -736,23 +754,17 @@
             }
 	    d->child = (Sized *)PyTuple_GET_ITEM(items, l);
 	    if (PyTuple_Check(d->child)) {
+		d->child = BTree_newBucket(self);
+		UNLESS (d->child)
+		    return -1;
 		if (noval) {
-                    d->child = (Sized *)PyObject_CallObject(OBJECT(&SetType),
-                                                            NULL);
-
-		    UNLESS (d->child)
-		        return -1;
 		    if (_set_setstate(BUCKET(d->child),
-				      PyTuple_GET_ITEM(items,l))
-			< 0) return -1;
-                } else {
-                    d->child = (Sized *)PyObject_CallObject(OBJECT(&BucketType),
-                                                            NULL);
-		    UNLESS (d->child)
+				      PyTuple_GET_ITEM(items,l)) < 0)
 			return -1;
+                } else {
 		    if (_bucket_setstate(BUCKET(d->child),
-					 PyTuple_GET_ITEM(items,l))
-			< 0) return -1;
+					 PyTuple_GET_ITEM(items,l)) < 0)
+			return -1;
                 }
 	    } else {
 		Py_INCREF(d->child);