[Zodb-checkins] CVS: Zope3/lib/python/Persistence/BTrees - BTreeModuleTemplate.c:1.1.2.4 BTreeTemplate.c:1.1.2.4 BucketTemplate.c:1.1.2.5 IIBTree.py:1.1.2.2 IOBTree.py:1.1.2.2 OIBTree.py:1.1.2.2 OOBTree.py:1.1.2.2 SetTemplate.c:1.1.2.4 TreeSetTemplate.c:1.1.2.3

Jeremy Hylton jeremy@zope.com
Thu, 28 Feb 2002 01:38:08 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	BTreeModuleTemplate.c BTreeTemplate.c BucketTemplate.c 
	IIBTree.py IOBTree.py OIBTree.py OOBTree.py SetTemplate.c 
	TreeSetTemplate.c 
Log Message:
Potential fix for various crashes in BTrees code.

XXX I thought I had checked this change in early in the afternoon on
Wed.  No idea why the commit didn't happen :-(.

The key change was to remove HEAPTYPE flag from tp_flags slot and put
a full path name for the module in the tp_name slot.  Guido suggested
this on the way to lunch.  The old code was misusing HEAPTYPE, which
should only be defined for type objects actually allocated on the
heap, i.e. with malloc.

The actual names in tp_name are not for the _OOBTree module but for
the OOBTree module that does an import * from _OOBTree.

XXX Jim pointed out that the approach of using a static string for
tp_name is not flexible.  It means the location of the BTrees modules
in the package hierarchy is fixed at compile time.  It would be more
flexible to assign to tp_name dynamically, inside the module init
function where the module's path is known.  Then the type's path would
depend on where it is loaded from.  The current scheme will always
have the same __module__ for a type, even if the .so is placed inside
a different package.  But YAGNI to the dynamic tp_name assignment.

Since the immediate core dumps were fixed, it is now possible to
remove the unused __init__ functions from the various PyMethodDefs.


=== Zope3/lib/python/Persistence/BTrees/BTreeModuleTemplate.c 1.1.2.3 => 1.1.2.4 ===
 #endif
 
+/*
+  The tp_name slots of the various BTree types contain the fully
+  qualified names of the types, e.g. Persistence.BTrees.OOBTree.OOBTree.
+  The full name is usd to support pickling and because it is not
+  possible to modify the __module__ slot of a type dynamically.  (This
+  may be a bug in Python 2.2). 
+*/
+
+#define MODULE_NAME "Persistence.BTrees." MOD_NAME_PREFIX "BTree."
 
 static PyObject *sort_str, *reverse_str, *__setstate___str;
 static PyObject *ConflictError = NULL;
@@ -295,15 +304,6 @@
 
     if (PyType_Ready(type) < 0)
 	return -1;
-    /* The INCREF below is based on superstition.  I suspect that by
-       marking an object as Py_TPFLAGS_HEAPTYPE, it is possible for
-       the type to be collected by the GC.  This doesn't make any
-       sense for a statically allocated type in an extension module,
-       but HEAPTYPE is necessary for other reasons.  If this guess is
-       right, then the INCREF below, which has no corresponding
-       DECREF, will prevent collection.
-     */
-    Py_INCREF(type);
 
     /* PyPersist_Type defines a tp_dictoffset so that classes that
        mixin Persistent can have an __dict__.  But this messes up the


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.1.2.3 => 1.1.2.4 ===
   {"update",	(PyCFunction) Mapping_update,	METH_VARARGS,
    "update(collection) -- Add the items from the given collection"},
-  {"__init__",	(PyCFunction) Mapping_update,	METH_VARARGS,
-   "__init__(collection) -- Initialize with items from the given collection"},
 #ifdef PERSISTENT
   {"_p_resolveConflict", (PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
    "_p_resolveConflict() -- Reinitialize from a newly created copy"},
@@ -1323,10 +1321,7 @@
 static PyTypeObject BTreeType = {
     PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
     0,					/* ob_size */
-/*
-  "Persistence.BTrees." MOD_NAME_PREFIX "BTree." MOD_NAME_PREFIX "BTree",
-*/
-    MOD_NAME_PREFIX "BTree",		/* tp_name */
+    MODULE_NAME MOD_NAME_PREFIX "BTree",/* tp_name */
     sizeof(BTree),			/* tp_basicsize */
     0,					/* tp_itemsize */
     (destructor)BTree_dealloc,		/* tp_dealloc */
@@ -1344,7 +1339,7 @@
     0,					/* tp_getattro */
     0,					/* tp_setattro */
     0,					/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HEAPTYPE |
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 
 	    Py_TPFLAGS_BASETYPE, 	/* tp_flags */
     0,					/* tp_doc */
     (traverseproc)BTree_traverse,	/* tp_traverse */


=== Zope3/lib/python/Persistence/BTrees/BucketTemplate.c 1.1.2.4 => 1.1.2.5 ===
     PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
     0,					/* ob_size */
-    MODULE_NAME MOD_NAME_PREFIX "Bucket",
+    MODULE_NAME MOD_NAME_PREFIX "Bucket",/* tp_name */
     sizeof(Bucket),			/* tp_basicsize */
     0,					/* tp_itemsize */
     (destructor)bucket_dealloc,		/* tp_dealloc */


=== Zope3/lib/python/Persistence/BTrees/IIBTree.py 1.1.2.1 => 1.1.2.2 ===
 # hack to overcome dynamic-linking headache.
 from _IIBTree import *
-
-# We don't really want _ names in pickles, so update all of the __module__
-# references.
-##for o in globals().values():
-##    if hasattr(o, '__module__'):
-##        o.__module__=__name__


=== Zope3/lib/python/Persistence/BTrees/IOBTree.py 1.1.2.1 => 1.1.2.2 ===
 # hack to overcome dynamic-linking headache.
 from _IOBTree import *
-
-# We don't really want _ names in pickles, so update all of the __module__
-# references.
-##for o in globals().values():
-##    if hasattr(o, '__module__'):
-##        o.__module__=__name__


=== Zope3/lib/python/Persistence/BTrees/OIBTree.py 1.1.2.1 => 1.1.2.2 ===
 # hack to overcome dynamic-linking headache.
 from _OIBTree import *
-
-# We don't really want _ names in pickles, so update all of the __module__
-# references.
-##for o in globals().values():
-##    if hasattr(o, '__module__'):
-##        o.__module__=__name__


=== Zope3/lib/python/Persistence/BTrees/OOBTree.py 1.1.2.1 => 1.1.2.2 ===
 # hack to overcome dynamic-linking headache.
 from _OOBTree import *
-
-# We don't really want _ names in pickles, so update all of the __module__
-# references.
-##for o in globals().values():
-##    print o
-##    if hasattr(o, '__module__'):
-##        o.__module__=__name__
-
-# XXX can't figure out why _reduce() won't call our __getstate__.
-
-import copy_reg
-
-def pickle_OOBTree(t):
-    return t.__class__, t.__getstate__()
-
-def unpickle_OOBTree(state):
-    obj = OOBTree.__new__(OOBTree, None)
-    obj.__setstate__(state)
-    return obj
-
-copy_reg.pickle(OOBTree, pickle_OOBTree)


=== Zope3/lib/python/Persistence/BTrees/SetTemplate.c 1.1.2.3 => 1.1.2.4 ===
   {"update",	(PyCFunction)Set_update,	METH_VARARGS,
    "update(seq) -- Add the items from the given sequence to the set"},
-  {"__init__",	(PyCFunction)Set_update,	METH_VARARGS,
-   "__init__(seq) -- Initialize with  the items from the given sequence"},
   {"remove",	(PyCFunction)Set_remove,	METH_VARARGS,
    "remove(id) -- Remove an id from the set"},
 
@@ -273,7 +271,7 @@
 static PyTypeObject SetType = {
     PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
     0,					/* ob_size */
-    MOD_NAME_PREFIX "Set",		/* tp_name */
+    MODULE_NAME MOD_NAME_PREFIX "Set",	/* tp_name */
     sizeof(Bucket),			/* tp_basicsize */
     0,					/* tp_itemsize */
     (destructor)bucket_dealloc,		/* tp_dealloc */
@@ -292,7 +290,7 @@
     0,					/* tp_setattro */
     0,					/* tp_as_buffer */
 /* XXX need to define traverse and clear functions */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HEAPTYPE |
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
 	    Py_TPFLAGS_BASETYPE, 	/* tp_flags */
     0,					/* tp_doc */
     0,	/* tp_traverse */


=== Zope3/lib/python/Persistence/BTrees/TreeSetTemplate.c 1.1.2.2 => 1.1.2.3 ===
   {"update",	(PyCFunction)TreeSet_update,	METH_VARARGS,
    "update(seq) -- Add the items from the given sequence to the set"},
-  {"__init__",	(PyCFunction)TreeSet_update,	METH_VARARGS,
-   "__init__(seq) -- Initialize with  the items from the given sequence"},
   {"remove",	(PyCFunction)TreeSet_remove,	METH_VARARGS,
    "remove(id) -- Remove a key from the set"},
 #ifdef PERSISTENT
@@ -162,7 +160,7 @@
 static PyTypeObject TreeSetType = {
     PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
     0,					/* ob_size */
-    MOD_NAME_PREFIX "TreeSet",		/* tp_name */
+    MODULE_NAME MOD_NAME_PREFIX "TreeSet",/* tp_name */
     sizeof(BTree),			/* tp_basicsize */
     0,					/* tp_itemsize */
     (destructor)BTree_dealloc,		/* tp_dealloc */
@@ -180,7 +178,7 @@
     0,					/* tp_getattro */
     0,					/* tp_setattro */
     0,					/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HEAPTYPE |
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 
 	    Py_TPFLAGS_BASETYPE, 	/* tp_flags */
     0,					/* tp_doc */
     (traverseproc)BTree_traverse,	/* tp_traverse */