[Zope-Checkins] CVS: Zope3/lib/python/ZODB - BaseStorage.py:1.15.10.1 ConflictResolution.py:1.7.30.1 Connection.py:1.60.6.1 DB.py:1.34.4.1 FileStorage.py:1.75.10.1 POSException.py:1.7.86.1 TimeStamp.c:1.8.4.1 __init__.py:1.10.60.1 DemoStorage.py:NONE PersistentMapping.py:NONE Setup:NONE Transaction.py:NONE bpthread.py:NONE cPersistence.c:NONE cPersistence.h:NONE cPickleCache.c:NONE conversionhack.py:NONE coptimizations.c:NONE

Jim Fulton jim@zope.com
Sun, 25 Nov 2001 19:39:42 -0500


Update of /cvs-repository/Zope3/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv18399

Modified Files:
      Tag: Zope-3x-branch
	BaseStorage.py ConflictResolution.py Connection.py DB.py 
	FileStorage.py POSException.py TimeStamp.c __init__.py 
Removed Files:
      Tag: Zope-3x-branch
	DemoStorage.py PersistentMapping.py Setup Transaction.py 
	bpthread.py cPersistence.c cPersistence.h cPickleCache.c 
	conversionhack.py coptimizations.c 
Log Message:
Refactored persistence and transactions out of ZODB.

Changed to use threading locks. 

Removed temporarily:

  - C optimizations

  - DemoStorage, because it depends on not-yet-ported BTrees.


=== Zope3/lib/python/ZODB/BaseStorage.py 1.15 => 1.15.10.1 ===
 __version__ = string.split('$Revision$')[-2:][0]
 
-import ThreadLock, bpthread
+import threading
 import time, UndoLogCompatible
 import POSException
 from TimeStamp import TimeStamp
@@ -104,10 +104,10 @@
         self.__name__=name
 
         # Allocate locks:
-        l=ThreadLock.allocate_lock()
+        l=threading.RLock()
         self._lock_acquire=l.acquire
         self._lock_release=l.release
-        l=bpthread.allocate_lock()
+        l=threading.Lock()
         self._commit_lock_acquire=l.acquire
         self._commit_lock_release=l.release
 


=== Zope3/lib/python/ZODB/ConflictResolution.py 1.7 => 1.7.30.1 ===
 from ZODB.POSException import ConflictError
 
+__new__=object.__new__
+
 #import traceback
 
 bad_classes={}
@@ -163,7 +165,11 @@
 
         newstate=unpickler.load()
         klass=_classFactory(class_tuple[0], class_tuple[1])
-        inst=klass.__basicnew__()
+        
+        #??? inst=klass.__basicnew__()
+        # CXX This isn't quite right, but I'm not sure what is.
+        # The contacts are a bit unclear.
+        inst=__new__(klass)
 
         try:
             resolve=inst._p_resolveConflict


=== Zope3/lib/python/ZODB/Connection.py 1.60 => 1.60.6.1 ===
+# Copyright (c) 2001 Zope Corporation and Contributors.  All Rights Reserved.
 # 
-# Zope Public License (ZPL) Version 1.0
-# -------------------------------------
-# 
-# Copyright (c) Digital Creations.  All rights reserved.
-# 
-# This license has been certified as Open Source(tm).
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-# 
-# 1. Redistributions in source code must retain the above copyright
-#    notice, this list of conditions, and the following disclaimer.
-# 
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions, and the following disclaimer in
-#    the documentation and/or other materials provided with the
-#    distribution.
-# 
-# 3. Digital Creations requests that attribution be given to Zope
-#    in any manner possible. Zope includes a "Powered by Zope"
-#    button that is installed by default. While it is not a license
-#    violation to remove this button, it is requested that the
-#    attribution remain. A significant investment has been put
-#    into Zope, and this effort will continue if the Zope community
-#    continues to grow. This is one way to assure that growth.
-# 
-# 4. All advertising materials and documentation mentioning
-#    features derived from or use of this software must display
-#    the following acknowledgement:
-# 
-#      "This product includes software developed by Digital Creations
-#      for use in the Z Object Publishing Environment
-#      (http://www.zope.org/)."
-# 
-#    In the event that the product being advertised includes an
-#    intact Zope distribution (with copyright and license included)
-#    then this clause is waived.
-# 
-# 5. Names associated with Zope or Digital Creations must not be used to
-#    endorse or promote products derived from this software without
-#    prior written permission from Digital Creations.
-# 
-# 6. Modified redistributions of any form whatsoever must retain
-#    the following acknowledgment:
-# 
-#      "This product includes software developed by Digital Creations
-#      for use in the Z Object Publishing Environment
-#      (http://www.zope.org/)."
-# 
-#    Intact (re-)distributions of any official Zope release do not
-#    require an external acknowledgement.
-# 
-# 7. Modifications are encouraged but must be packaged separately as
-#    patches to official Zope releases.  Distributions that do not
-#    clearly separate the patches from the original work must be clearly
-#    labeled as unofficial distributions.  Modifications which do not
-#    carry the name Zope may be packaged in any form, as long as they
-#    conform to all of the clauses above.
-# 
-# 
-# Disclaimer
-# 
-#   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
-#   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-#   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
-#   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-#   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-#   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-#   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-#   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-#   SUCH DAMAGE.
-# 
-# 
-# This software consists of contributions made by Digital Creations and
-# many individuals on behalf of Digital Creations.  Specific
-# attributions are listed in the accompanying credits file.
-# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
+# FOR A PARTICULAR PURPOSE.
 ##############################################################################
 """Database connection support
 
 $Id$"""
 __version__='$Revision$'[11:-2]
 
-from cPickleCache import PickleCache
+from Persistence.Cache import Cache
 from POSException import ConflictError
-from ExtensionClass import Base
 import ExportImport, TmpStore
 from zLOG import LOG, ERROR, BLATHER
-from coptimizations import new_persistent_id
 from ConflictResolution import ResolvedSerial
 
 from cPickle import Unpickler, Pickler
@@ -101,6 +25,10 @@
 from time import time
 from types import StringType, ClassType
 
+from Transaction import get_transaction
+
+__new__=object.__new__
+
 global_code_timestamp = 0
 
 def updateCodeTimestamp():
@@ -112,7 +40,7 @@
     global global_code_timestamp
     global_code_timestamp = time()
 
-ExtensionKlass=Base.__class__
+ExtensionKlass=object.__class__
 
 class Connection(ExportImport.ExportImport):
     """Object managers for individual object space.
@@ -135,7 +63,7 @@
                  cache_deactivate_after=60):
         """Create a new Connection"""
         self._version=version
-        self._cache=cache=PickleCache(self, cache_size, cache_deactivate_after)
+        self._cache=cache=Cache(cache_size, cache_deactivate_after)
         self._incrgc=self.cacheGC=cache.incrgc
         self._invalidated=d={}
         self._invalid=d.has_key
@@ -153,7 +81,8 @@
     def __getitem__(self, oid,
                     tt=type(())):
         cache=self._cache
-        if cache.has_key(oid): return cache[oid]
+        object=cache.get(oid, self)
+        if object is not self: return object
 
         __traceback_info__ = (oid)
         p, serial = self._storage.load(oid, self._version)
@@ -176,7 +105,10 @@
         
         if (args is None or
             not args and not hasattr(klass,'__getinitargs__')):
-            object=klass.__basicnew__()
+            #??? object=klass.__basicnew__()
+            # CXX This isn't quite right, but I'm not sure what is.
+            # The contacts are a bit unclear.
+            object=__new__(klass)
         else:
             object=apply(klass,args)
             if klass is not ExtensionKlass:
@@ -191,8 +123,79 @@
         if oid=='\0\0\0\0\0\0\0\0': self._root_=object # keep a ref
         return object
 
-    def _persistent_load(self,oid,
-                        tt=type(())):
+    ######################################################################
+    # IPersistentDataManager
+
+    def setstate(self, object):
+        try:
+            oid=object._p_oid
+             
+            p, serial = self._storage.load(oid, self._version)
+
+            # XXX this is quite conservative!
+            # We need, however, to avoid reading data from a transaction
+            # that committed after the current "session" started, as
+            # that might lead to mixing of cached data from earlier
+            # transactions and new inconsistent data.
+            #
+            # Note that we (carefully) wait until after we call the
+            # storage to make sure that we don't miss an invaildation
+            # notifications between the time we check and the time we
+            # read.
+            invalid=self._invalid
+            if invalid(oid) or invalid(None):
+                if not hasattr(object.__class__, '_p_independent'):
+                    get_transaction().register(self)
+                    raise ConflictError(`oid`, `object.__class__`)
+                invalid=1
+            else:
+                invalid=0
+
+            file=StringIO(p)
+            unpickler=Unpickler(file)
+            unpickler.persistent_load=self._persistent_load
+            unpickler.load()
+            state = unpickler.load()
+
+            if hasattr(object, '__setstate__'):
+                object.__setstate__(state)
+            else:
+                d=object.__dict__
+                for k,v in state.items(): d[k]=v
+
+            object._p_serial=serial
+
+            if invalid:
+                if object._p_independent():
+                    try: del self._invalidated[oid]
+                    except KeyError: pass
+                else:
+                    get_transaction().register(self)
+                    raise ConflictError(`oid`, `object.__class__`)
+
+        except ConflictError:
+            raise
+        except:
+            LOG('ZODB',ERROR, "Couldn't load state for %s" % `oid`,
+                error=sys.exc_info())
+            raise
+
+        # Add the object to the cache active list:
+        self._cache.setstate(oid, object)
+
+    def register(self, object):
+        get_transaction().register(object)
+
+    def mtime(self, object):
+        try: mtime=self._storage.mtime
+        except AttributeError: return None
+        return mtime(object._p_oid, object._p_serial)
+
+    ######################################################################
+
+
+    def _persistent_load(self, oid,
+                         tt=type(())):
 
         __traceback_info__=oid
 
@@ -202,7 +205,8 @@
             # Quick instance reference.  We know all we need to know
             # to create the instance wo hitting the db, so go for it!
             oid, klass = oid
-            if cache.has_key(oid): return cache[oid]
+            object=cache.get(oid, self)
+            if object is not self: return object
 
             if type(klass) is tt:
                 module, name = klass
@@ -213,7 +217,10 @@
                     # object's actual record!
                     return self[oid]
             
-            object=klass.__basicnew__()
+            # CXX This isn't quite right, but I'm not sure what is.
+            # The contacts are a bit unclear.
+            object=__new__(klass)
+            
             object._p_oid=oid
             object._p_jar=self
             object._p_changed=None
@@ -222,7 +229,8 @@
 
             return object
 
-        if cache.has_key(oid): return cache[oid]
+        object=cache.get(oid, self)
+        if object is not self: return object
         return self[oid]
 
     def _setDB(self, odb):
@@ -237,7 +245,7 @@
             # New code is in place.  Start a new cache.
             self._resetCache()
         else:
-            self._cache.invalidate(self._invalidated)
+            self._cache.invalidateMany(self._invalidated)
         self._opened=time()
 
         return self
@@ -258,7 +266,7 @@
         This just deactivates the thing.
         """
         if object is self:
-            self._cache.invalidate(self._invalidated)
+            self._cache.invalidateMany(self._invalidated)
         else:
             self._cache.invalidate(object._p_oid)
 
@@ -328,34 +336,6 @@
             return
 
         stack=[object]
-
-        # Create a special persistent_id that passes T and the subobject
-        # stack along:
-        #
-        # def persistent_id(object,
-        #                   self=self,
-        #                   stackup=stackup, new_oid=self.new_oid):
-        #     if (not hasattr(object, '_p_oid') or
-        #         type(object) is ClassType): return None
-        # 
-        #     oid=object._p_oid
-        # 
-        #     if oid is None or object._p_jar is not self:
-        #         oid = self.new_oid()
-        #         object._p_jar=self
-        #         object._p_oid=oid
-        #         stackup(object)
-        # 
-        #     klass=object.__class__
-        # 
-        #     if klass is ExtensionKlass: return oid
-        #     
-        #     if hasattr(klass, '__getinitargs__'): return oid
-        # 
-        #     module=getattr(klass,'__module__','')
-        #     if module: klass=module, klass.__name__
-        #     
-        #     return oid, klass
         
         file=StringIO()
         seek=file.seek
@@ -470,7 +450,7 @@
         self._storage=tmp
 
         
-        self._cache.invalidate(src._index.keys())
+        self._cache.invalidateMany(src._index.keys())
         self._invalidate_creating(src._creating)
 
     def _invalidate_creating(self, creating=None):
@@ -489,8 +469,6 @@
                 del o._p_oid
                 del cache[oid]
 
-    #XXX
-
     def db(self): return self._db
 
     def getVersion(self): return self._version
@@ -511,61 +489,14 @@
 
     def root(self): return self['\0\0\0\0\0\0\0\0']
 
-    def setstate(self, object):
-        try:
-            oid=object._p_oid
-             
-            p, serial = self._storage.load(oid, self._version)
-
-            # XXX this is quite conservative!
-            # We need, however, to avoid reading data from a transaction
-            # that committed after the current "session" started, as
-            # that might lead to mixing of cached data from earlier
-            # transactions and new inconsistent data.
-            #
-            # Note that we (carefully) wait until after we call the
-            # storage to make sure that we don't miss an invaildation
-            # notifications between the time we check and the time we
-            # read.
-            invalid=self._invalid
-            if invalid(oid) or invalid(None):
-                if not hasattr(object.__class__, '_p_independent'):
-                    get_transaction().register(self)
-                    raise ConflictError(`oid`, `object.__class__`)
-                invalid=1
-            else:
-                invalid=0
-
-            file=StringIO(p)
-            unpickler=Unpickler(file)
-            unpickler.persistent_load=self._persistent_load
-            unpickler.load()
-            state = unpickler.load()
-
-            if hasattr(object, '__setstate__'):
-                object.__setstate__(state)
-            else:
-                d=object.__dict__
-                for k,v in state.items(): d[k]=v
-
-            object._p_serial=serial
-
-            if invalid:
-                if object._p_independent():
-                    try: del self._invalidated[oid]
-                    except KeyError: pass
-                else:
-                    get_transaction().register(self)
-                    raise ConflictError(`oid`, `object.__class__`)
+    def oldstate(self, object, serial):
+        """Return the state of an object as it existed in some time in the past
 
-        except ConflictError:
-            raise
-        except:
-            LOG('ZODB',ERROR, "Couldn't load state for %s" % `oid`,
-                error=sys.exc_info())
-            raise
+        The time is specified via a serial number.
 
-    def oldstate(self, object, serial):
+        This routine is used by Zope's History facility.
+        """
+        
         oid=object._p_oid
         p = self._storage.loadSerial(oid, serial)
         file=StringIO(p)
@@ -610,8 +541,8 @@
             del self.__onCommitActions
         self._storage.tpc_abort(transaction)
         cache=self._cache
-        cache.invalidate(self._invalidated)
-        cache.invalidate(self._invalidating)
+        cache.invalidateMany(self._invalidated)
+        cache.invalidateMany(self._invalidating)
         self._invalidate_creating()
 
     def tpc_begin(self, transaction, sub=None):
@@ -703,7 +634,7 @@
             self._storage.tpc_finish(transaction,
                                      self._invalidate_invalidating)
 
-        self._cache.invalidate(self._invalidated)
+        self._cache.invalidateMany(self._invalidated)
         self._incrgc() # This is a good time to do some GC
 
     def _invalidate_invalidating(self):
@@ -716,7 +647,7 @@
         get_transaction().abort()
         sync=getattr(self._storage, 'sync', 0)
         if sync != 0: sync()
-        self._cache.invalidate(self._invalidated)
+        self._cache.invalidateMany(self._invalidated)
         self._incrgc() # This is a good time to do some GC
 
     def getDebugInfo(self): return self._debug_info
@@ -738,3 +669,35 @@
     def close(self):
         self._breakcr()
 
+def new_persistent_id(self, stackup):
+
+    # Create a special persistent_id that passes T and the subobject
+    # stack along:
+
+    def persistent_id(object, self=self, stackup=stackup):
+
+        new_oid = self.new_oid
+        
+        if (not hasattr(object, '_p_oid') or
+            type(object) is ClassType): return None
+
+        oid=object._p_oid
+
+        if oid is None or object._p_jar is not self:
+            oid = self.new_oid()
+            object._p_jar=self
+            object._p_oid=oid
+            stackup(object)
+
+        klass=object.__class__
+
+        if klass is ExtensionKlass: return oid
+
+        if hasattr(klass, '__getinitargs__'): return oid
+
+        module=getattr(klass,'__module__','')
+        if module: klass=module, klass.__name__
+
+        return oid, klass
+    
+    return persistent_id


=== Zope3/lib/python/ZODB/DB.py 1.34 => 1.34.4.1 ===
 import cPickle, cStringIO, sys, POSException, UndoLogCompatible
 from Connection import Connection
-from bpthread import allocate_lock
+from threading import Lock
 from Transaction import Transaction
 from referencesf import referencesf
 from time import time, ctime
@@ -124,7 +124,7 @@
         """
 
         # Allocate locks:
-        l=allocate_lock()
+        l=Lock()
         self._a=l.acquire
         self._r=l.release
 
@@ -146,10 +146,10 @@
         if not hasattr(storage,'tpc_vote'): storage.tpc_vote=lambda *args: None
         try: storage.load('\0\0\0\0\0\0\0\0','')
         except:
-            import PersistentMapping
+            from Persistence import PersistentMapping
             file=cStringIO.StringIO()
             p=cPickle.Pickler(file,1)
-            p.dump((PersistentMapping.PersistentMapping,None))
+            p.dump((PersistentMapping,None))
             p.dump({'_container': {}})
             t=Transaction()
             t.description='initial database creation'
@@ -453,7 +453,7 @@
                 pool, allocated, pool_lock = pools[version]
             else:
                 pool, allocated, pool_lock = pools[version] = (
-                    [], [], allocate_lock())
+                    [], [], Lock())
                 pooll.append((pool, allocated))
                 pool_lock.acquire()
 


=== Zope3/lib/python/ZODB/FileStorage.py 1.75 => 1.75.10.1 ===
 __version__='$Revision$'[11:-2]
 
-import struct, time, os, bpthread, string, base64, sys
+import struct, time, os, string, base64, sys
 from struct import pack, unpack
 from cPickle import loads
 import POSException


=== Zope3/lib/python/ZODB/POSException.py 1.7 => 1.7.86.1 ===
 __version__='$Revision$'[11:-2]
 
+from Transaction.Exceptions import TransactionError, ConflictError
+
 from string import join
 StringType=type('')
 DictType=type({})
 
 class POSError(Exception):
     """Persistent object system error
-    """
-
-class TransactionError(POSError):
-    """An error occured due to normal transaction processing
-    """
-
-class ConflictError(TransactionError):
-    """Two transactions tried to modify the same object at once
-
-    This transaction should be resubmitted.
     """
 
 class VersionError(POSError):


=== Zope3/lib/python/ZODB/TimeStamp.c 1.8 => 1.8.4.1 ===
 #include <stdlib.h>
 #include <time.h>
-#ifdef USE_EXTENSION_CLASS
-#include "ExtensionClass.h"
-#else
 #include "Python.h"
-#endif
 
 static PyObject *ErrorObject;
 
@@ -361,35 +357,12 @@
   {"seconds", (PyCFunction)TimeStamp_second, METH_VARARGS, ""},
   {"timeTime", (PyCFunction)TimeStamp_timeTime, METH_VARARGS, ""},
   {"laterThan", (PyCFunction)TimeStamp_laterThan, METH_VARARGS, ""},
-#ifdef USE_EXTENSION_CLASS
-  {"__init__", (PyCFunction)TimeStamp___init__, METH_VARARGS, 
-   ""},
-#endif  
   {NULL,		NULL}		/* sentinel */
 };
 
-#ifndef USE_EXTENSION_CLASS
-static TimeStampobject *
-newTimeStamp(PyObject *ignored, PyObject *args)
-{
-  TimeStamp *self;
-	
-  UNLESS(self = PyObject_NEW(TimeStamp, &TimeStampType)) return NULL;
-  
-  ignored=__init__(self, args);
-  if (! ignored) return NULL;
-    
-  Py_DECREF(ignored);
-  return self;
-}
-#endif
-
 static void
 TimeStamp_dealloc(TimeStamp *self)
 {
-#ifdef USE_EXTENSION_CLASS
-  Py_DECREF(self->ob_type);
-#endif  
   PyMem_DEL(self);
 }
 
@@ -429,21 +402,13 @@
 static PyObject *
 TimeStamp_getattro(TimeStamp *self, PyObject *name)
 {
-#ifndef USE_EXTENSION_CLASS
   char *s;
 
   if (! (s=PyString_AsString(name))) return NULL;
-  return Py_FindMethod(TimeStamp_methods, self, s); 
-#else
-  return Py_FindAttr(OBJECT(self), name);
-#endif
+  return Py_FindMethod(TimeStamp_methods, OBJECT(self), s); 
 }
 
-#ifdef USE_EXTENSION_CLASS
-static PyExtensionClass
-#else
 static PyTypeObject 
-#endif
 TimeStampType = {
   PyObject_HEAD_INIT(NULL)
   0,				/*ob_size*/
@@ -469,15 +434,24 @@
   /* Space for future expansion */
   0L,0L,
   "Simple time stamps"
-#ifdef USE_EXTENSION_CLASS
-  , METHOD_CHAIN(TimeStamp_methods),
-#endif
 };
 
+static TimeStamp *
+newTimeStamp(PyObject *ignored, PyObject *args)
+{
+  TimeStamp *self;
+	
+  UNLESS(self = PyObject_NEW(TimeStamp, &TimeStampType)) return NULL;
+  
+  ignored=TimeStamp___init__(self, args);
+  if (! ignored) return NULL;
+    
+  Py_DECREF(ignored);
+  return self;
+}
+
 static struct PyMethodDef Module_Level__methods[] = {
-#ifndef USE_EXTENSION_CLASS
   {"TimeStamp", (PyCFunction)newTimeStamp, METH_VARARGS, ""},
-#endif
   {NULL, (PyCFunction)NULL, 0, NULL}		/* sentinel */
 };
 
@@ -488,7 +462,6 @@
   char *rev="$Revision$";
 
   if (TimeStamp_init_gmoff() < 0) return;
-  if (! ExtensionClassImported) return;
 
   /* Create the module and add the functions */
   m = Py_InitModule4("TimeStamp", Module_Level__methods,
@@ -498,11 +471,7 @@
   /* Add some symbolic constants to the module */
   d = PyModule_GetDict(m);
 
-#ifndef USE_EXTENSION_CLASS
   TimeStampType.ob_type=&PyType_Type;
-#else
-  PyExtensionClass_Export(d, "TimeStamp", TimeStampType);
-#endif
 
   PyDict_SetItemString(d,"TimeStampType", OBJECT(&TimeStampType));
 


=== Zope3/lib/python/ZODB/__init__.py 1.10 => 1.10.60.1 ===
 # 
 ##############################################################################
-import sys, ExtensionClass, TimeStamp, cPersistence, Persistence
-import cStringIO, cPickle
 from zLOG import register_subsystem
 register_subsystem('ZODB')
-
-# This is lame. Don't look. :(
-sys.modules['cPersistence']=cPersistence
-
-Persistent=cPersistence.Persistent
-
-# Install Persistent and PersistentMapping in Persistence
-if not hasattr(Persistence, 'Persistent'):
-    Persistence.Persistent=Persistent
-    Persistent.__module__='Persistence'
-    Persistence.Overridable=cPersistence.Overridable
-    Persistence.Overridable.__module__='Persistence'
-    if not hasattr(Persistence, 'PersistentMapping'):
-        import PersistentMapping
-        sys.modules['PersistentMapping']=PersistentMapping
-        sys.modules['BoboPOS']=sys.modules['ZODB']
-        sys.modules['BoboPOS.PersistentMapping']=PersistentMapping
-        PersistentMapping=PersistentMapping.PersistentMapping
-        from PersistentMapping import PersistentMapping
-        Persistence.PersistentMapping=PersistentMapping
-        PersistentMapping.__module__='Persistence'
-        del PersistentMapping
-
-del cPersistence
+del register_subsystem
 
 from DB import DB
 
-import Transaction
+# The following provides some backward compat:
+from Transaction import get_transaction
+import __main__ 
+__main__.__builtins__.get_transaction=get_transaction
+del __main__
+del get_transaction

=== Removed File Zope3/lib/python/ZODB/DemoStorage.py ===

=== Removed File Zope3/lib/python/ZODB/PersistentMapping.py ===

=== Removed File Zope3/lib/python/ZODB/Setup ===

=== Removed File Zope3/lib/python/ZODB/Transaction.py ===

=== Removed File Zope3/lib/python/ZODB/bpthread.py ===

=== Removed File Zope3/lib/python/ZODB/cPersistence.c ===

=== Removed File Zope3/lib/python/ZODB/cPersistence.h ===

=== Removed File Zope3/lib/python/ZODB/cPickleCache.c ===

=== Removed File Zope3/lib/python/ZODB/conversionhack.py ===

=== Removed File Zope3/lib/python/ZODB/coptimizations.c ===