[Zope-Checkins] CVS: Zope3/lib/python/ZODB - IConnection.py:1.2 setup.py:1.2 .cvsignore:1.2 BaseStorage.py:1.20 ConflictResolution.py:1.10 Connection.py:1.68 DB.py:1.43 ExportImport.py:1.14 FileStorage.py:1.92 MappingStorage.py:1.7 POSException.py:1.12 TimeStamp.c:1.16 TmpStore.py:1.7 ZApplication.py:1.11 __init__.py:1.13 dbmStorage.py:1.4 fsIndex.py:1.3 fsdump.py:1.4 fsrecover.py:1.5 lock_file.py:1.6 referencesf.py:1.6 utils.py:1.12 winlock.c:1.9 ActivityMonitor.py:NONE DemoStorage.py:NONE Mount.py:NONE PersistentList.py:NONE PersistentMapping.py:NONE Setup:NONE Transaction.py:NONE UndoLogCompatible.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
Mon, 10 Jun 2002 19:28:50 -0400


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

Modified Files:
	.cvsignore BaseStorage.py ConflictResolution.py Connection.py 
	DB.py ExportImport.py FileStorage.py MappingStorage.py 
	POSException.py TimeStamp.c TmpStore.py ZApplication.py 
	__init__.py dbmStorage.py fsIndex.py fsdump.py fsrecover.py 
	lock_file.py referencesf.py utils.py winlock.c 
Added Files:
	IConnection.py setup.py 
Removed Files:
	ActivityMonitor.py DemoStorage.py Mount.py PersistentList.py 
	PersistentMapping.py Setup Transaction.py UndoLogCompatible.py 
	bpthread.py cPersistence.c cPersistence.h cPickleCache.c 
	conversionhack.py coptimizations.c 
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.


=== Zope3/lib/python/ZODB/IConnection.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+# 
+##############################################################################
+try:
+    from Interface import Interface
+except ImportError:
+    class Interface:
+        pass
+
+class IConnection(Interface):
+    """Interface required of Connection by ZODB DB.
+
+    The Connection also implements IPersistentDataManager.
+    """
+
+    def reset():
+        """Reset the Connection."""
+
+    def getVersion():
+        """Return the version that connection is using."""
+
+    def invalidate(oid):
+        """Invalidate a particular oid
+
+        This marks the oid as invalid, but doesn't actually invalidate
+        it.  The object data will be actually invalidated at certain
+        transaction boundaries.
+
+        XXX The code suggests that invalidate() may sometimes be
+        called with None as the oid, which would mean the "entire
+        transaction" is invalidated.
+        """
+        
+    def close():
+        # XXX
+


=== Zope3/lib/python/ZODB/setup.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+# 
+##############################################################################
+from distutils.core import setup, Extension
+setup(
+    name="ZODB",
+    version="4.0x",
+    ext_modules=[Extension("TimeStamp", ["TimeStamp.c"])]
+    )


=== Zope3/lib/python/ZODB/.cvsignore 1.1 => 1.2 ===
-Makefile.pre
-Makefile
-sedscript
-config.c
+build


=== Zope3/lib/python/ZODB/BaseStorage.py 1.19 => 1.20 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Handy standard storage machinery
+
+$Id$
 """
-# Do this portably in the face of checking out with -kv
-import string
-__version__ = string.split('$Revision$')[-2:][0]
 
-import ThreadLock, bpthread
-import time, UndoLogCompatible
+import threading
+import time
 import POSException
 from TimeStamp import TimeStamp
 z64='\0'*8
 
-class BaseStorage(UndoLogCompatible.UndoLogCompatible):
+class BaseStorage:
     _transaction=None # Transaction that is being committed
     _serial=z64       # Transaction serial number
     _tstatus=' '      # Transaction status, used for copying data
@@ -34,16 +33,16 @@
         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
 
         t=time.time()
         t=self._ts=apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,)))
-        self._serial=`t`
+        self._serial=t.raw()
         if base is None:
             self._oid='\0\0\0\0\0\0\0\0'
         else:
@@ -98,9 +97,6 @@
     def isReadOnly(self):
         return self._is_read_only
     
-    def supportsUndo(self):
-        return 0
-    
     def supportsVersions(self):
         return 0
         
@@ -121,7 +117,8 @@
     def tpc_begin(self, transaction, tid=None, status=' '):
         self._lock_acquire()
         try:
-            if self._transaction is transaction: return
+            if self._transaction is transaction:
+                return
             self._lock_release()
             self._commit_lock_acquire()
             self._lock_acquire()
@@ -131,15 +128,18 @@
             user=transaction.user
             desc=transaction.description
             ext=transaction._extension
-            if ext: ext=dumps(ext,1)
-            else: ext=""
+            if ext:
+                import cPickle
+                ext = cPickle.dumps(ext, 1)
+            else:
+                ext = ""
             self._ude=user, desc, ext
 
             if tid is None:
                 t=time.time()
                 t=apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,)))
                 self._ts=t=t.laterThan(self._ts)
-                self._serial=`t`
+                self._serial=t.raw()
             else:
                 self._ts=TimeStamp(tid)
                 self._serial=tid
@@ -148,7 +148,8 @@
 
             self._begin(self._serial, user, desc, ext)
             
-        finally: self._lock_release()
+        finally:
+            self._lock_release()
 
     def _begin(self, tid, u, d, e):
         """Subclasses should redefine this to supply transaction start actions.
@@ -171,16 +172,18 @@
     def tpc_finish(self, transaction, f=None):
         self._lock_acquire()
         try:
-            if transaction is not self._transaction: return
+            if transaction is not self._transaction:
+                return
             try:
-                if f is not None: f()
+                if f is not None:
+                    f()
 
-                u,d,e=self._ude
+                u, d, e = self._ude
                 self._finish(self._serial, u, d, e)
                 self._clear_temp()
             finally:
-                self._ude=None
-                self._transaction=None
+                self._ude = None
+                self._transaction = None
                 self._commit_lock_release()
         finally:
             self._lock_release()
@@ -190,10 +193,38 @@
         """
         pass
 
-    def undo(self, transaction_id):
-        if self._is_read_only:
-            raise POSException.ReadOnlyError()
-        raise POSException.UndoError, 'non-undoable transaction'
+    def undoInfo(self, first=0, last=-20, specification=None):
+        """Return a list of transaction descriptions for use with undo.
+
+        The first and last argument specify how many transactions to
+        return and where in the transaction history they should come
+        from.  The specification argument is a mapping that specifies
+        a filter on transaction metadata.
+
+        undoInfo() scans the transaction history from most recent
+        transaction to oldest transaction.  It skips the 'first' most
+        recent transactions; i.e. if first is N, then the first
+        transaction returned will be the Nth transaction.
+
+        If last is less than zero, then its absolute value is the
+        maximum number of transactions to return.  Otherwise if last
+        is N, then only the N most recent transactions following start
+        are considered.
+
+        If specification is not None, then it must be a mapping that
+        is compared to the transaction description.  Each key-value
+        pair in the specification must also be present in the
+        description.
+        """
+        if specification:
+            def filter(desc, spec=specification.items()):
+                for k, v in spec:
+                    if desc.get(k) != v:
+                        return 0
+                return 1
+        else:
+            filter = None
+        return self.undoLog(first, last, filter)
 
     def undoLog(self, first, last, filter=None):
         return ()
@@ -257,7 +288,7 @@
                     if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
                     ok=0
                     _ts=t.laterThan(_ts)
-                    tid=`_ts`
+                    tid=_ts.raw()
                 else:
                     _ts = t
                     if not ok:


=== Zope3/lib/python/ZODB/ConflictResolution.py 1.9 => 1.10 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 from cStringIO import StringIO
 from cPickle import Unpickler, Pickler
-import sys
 
 from ZODB.POSException import ConflictError
 
-#import traceback
-
 bad_classes={}
 def bad_class(class_tuple):
-    if bad_classes.has_key(class_tuple) or class_tuple[0][0] == '*':
+    if (class_tuple in bad_classes) or class_tuple[0][0] == '*':
         # if we've seen the class before or if it's a ZClass, we know that
         # we can't resolve the conflict
         return 1
@@ -53,19 +50,18 @@
 
 class PersistentReferenceFactory:
 
-    data=None
+    data = None
     
-    def __call__(self, oid,
-                 getattr=getattr, None=None):
-
-        data=self.data
-        if not data: data=self.data={}
+    def __call__(self, oid):
+        data = self.data
+        if not data:
+            data = self.data = {}
 
-        r=data.get(oid, None)
+        r = data.get(oid, None)
         if r is None:
-            r=PersistentReference()
-            r.data=oid
-            data[oid]=r
+            r = PersistentReference()
+            r.data = oid
+            data[oid] = r
 
         return r
 
@@ -79,7 +75,6 @@
 
 def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
                          committedData=''):
-    #class_tuple, old, committed, newstate = ('',''), 0, 0, 0
     try:
         file=StringIO(newpickle)
         unpickler=Unpickler(file)
@@ -87,19 +82,16 @@
         unpickler.persistent_load=prfactory
         class_tuple=unpickler.load()[0]
         if bad_class(class_tuple):
-            #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
             return 0
 
-        newstate=unpickler.load()
-        klass=_classFactory(class_tuple[0], class_tuple[1])
-        inst=klass.__basicnew__()
+        newstate = unpickler.load()
+        klass = _classFactory(class_tuple[0], class_tuple[1])
+        inst = klass.__new__(klass)
 
         try:
-            resolve=inst._p_resolveConflict
+            resolve = inst._p_resolveConflict
         except AttributeError:
             bad_classes[class_tuple]=1
-            #traceback.print_exc()
-            #sys.stderr.write(' b%s ' % class_tuple[1]); sys.stderr.flush()
             return 0
 
         old=state(self, oid, oldSerial, prfactory)
@@ -112,7 +104,6 @@
         pickler.persistent_id=persistent_id
         pickler.dump(class_tuple)
         pickler.dump(resolved)
-        #sys.stderr.write(' r%s ' % class_tuple[1]); sys.stderr.flush()
         return file.getvalue(1)
     except ConflictError:
         return 0


=== Zope3/lib/python/ZODB/Connection.py 1.67 => 1.68 === (1057/1157 lines abridged)
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Database connection support
 
-$Id$"""
-__version__='$Revision$'[11:-2]
+The Connection object serves as a data manager.  ZODB is organized so
+that each thread should have its own Connection.  A thread acquires a
+Connection by calling the open() method on a database object.
 
-from cPickleCache import PickleCache, MUCH_RING_CHECKING
-from POSException import ConflictError, ReadConflictError
-from ExtensionClass import Base
-import ExportImport, TmpStore
-from zLOG import LOG, ERROR, BLATHER, WARNING
-from coptimizations import new_persistent_id
-from ConflictResolution import ResolvedSerial
+A Connection can be associated with a single version when it is
+created.  By default, a Connection is not associated with a version.
+It uses non-version data.
+
+The root() method on a Connection returns the root object for the
+database.  This object and all objects reachable from it are
+associated with the Connection that loaded them.  When the objects are
+modified, the Connection is registered with the current transaction.
+
+XXX multi-threaded issues
+
+One or more application threads could call methods on a Connection or
+interact with it indirectly via objects that the Connection loaded.
+The intent is for a single thread to use a Connection, but this is not
+enforced.
+
+Not sure if its possible for other threads to interact with Connection
+in other ways.
+
+XXX undocumented issues
+
+The Connection supports callbacks on close and commit.
+
+$Id$
+"""
+
+from ZODB import ExportImport, TmpStore
+from ZODB.ConflictResolution import ResolvedSerial
+from ZODB.POSException import ConflictError

[-=- -=- -=- 1057 lines omitted -=- -=- -=-]

 
-    ######################################################################
-    # Just plain weird. Don't try this at home kids.
-    def exchange(self, old, new):
-        oid=old._p_oid
-        new._p_oid=oid
-        new._p_jar=self
-        new._p_changed=1
-        get_transaction().register(new)
-        self._cache[oid]=new
+        If it is persistent, it returns the oid and sometimes a tuple
+        with other stuff.
+        """
         
-class tConnection(Connection):
-
-    def close(self):
-        self._breakcr()
+        if (not hasattr(object, '_p_oid') or
+            isinstance(object, ClassType)):
+            return None
+        
+        oid = object._p_oid
+
+        # I'd like to write something like this --
+        # if isinstance(oid, types.MemberDescriptor):
+        # -- but I can't because the type doesn't have a canonical name.
+        # Instead, we'll assert that an oid must always be a string
+        if not (isinstance(oid, StringType) or oid is None):
+            return None
+        
+        if oid is None or object._p_jar is not self:
+            oid = self.new_oid()
+            object._p_jar = self
+            object._p_oid = oid
+            stack.append(object)
+
+        klass = object.__class__
+
+        if klass is type:
+            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.42 => 1.43 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Database objects
 
-$Id$"""
-__version__='$Revision$'[11:-2]
+$Id$
+"""
 
-import cPickle, cStringIO, sys, POSException, UndoLogCompatible
+import cPickle, cStringIO, sys
+import POSException
 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
@@ -26,16 +27,13 @@
 
 from types import StringType
 
-class DB(UndoLogCompatible.UndoLogCompatible):
+class DB:
     """The Object Database
 
     The Object database coordinates access to and interaction of one
     or more connections, which manage object spaces.  Most of the actual work
     of managing objects is done by the connections.
     """
-    klass = Connection  # Class to use for connections
-    _activity_monitor = None
-
     def __init__(self, storage,
                  pool_size=7,
                  cache_size=400,
@@ -54,7 +52,7 @@
         """
 
         # Allocate locks:
-        l=allocate_lock()
+        l=Lock()
         self._a=l.acquire
         self._r=l.release
 
@@ -63,23 +61,22 @@
         self._temps=[]
         self._pool_size=pool_size
         self._cache_size=cache_size
-        self._cache_deactivate_after = cache_deactivate_after
+        self._cache_deactivate_after=cache_deactivate_after
         self._version_pool_size=version_pool_size
         self._version_cache_size=version_cache_size
-        self._version_cache_deactivate_after = version_cache_deactivate_after
+        self._version_cache_deactivate_after=version_cache_deactivate_after
 
         self._miv_cache={}
 
         # Setup storage
-        self._storage=storage
+        self._storage = storage
         storage.registerDB(self, None)
-        if not hasattr(storage,'tpc_vote'): storage.tpc_vote=lambda *args: None
         try:
-            storage.load('\0\0\0\0\0\0\0\0','')
+            storage.load('\0\0\0\0\0\0\0\0', '')
         except KeyError:
             # Create the database's root in the storage if it doesn't exist
-            import PersistentMapping
-            root = PersistentMapping.PersistentMapping()
+            from Persistence import PersistentMapping
+            root = PersistentMapping()
             # Manually create a pickle for the root to put in the storage.
             # The pickle must be in the special ZODB format.
             file = cStringIO.StringIO()
@@ -94,15 +91,10 @@
             storage.tpc_finish(t)
 
         # Pass through methods:
-        for m in ('history',
-                  'supportsUndo', 'supportsVersions', 'undoLog',
-                  'versionEmpty', 'versions'):
+        for m in ('history', 'supportsVersions', 'undoInfo', 'versionEmpty',
+                  'versions'):
             setattr(self, m, getattr(storage, m))
 
-        if hasattr(storage, 'undoInfo'):
-            self.undoInfo=storage.undoInfo
-            
-
     def _cacheMean(self, attr):
         # XXX this method doesn't work
         m=[0,0]
@@ -125,9 +117,6 @@
         """Return a connection to the pool"""
         self._a()
         try:
-            am = self._activity_monitor
-            if am is not None:
-                am.closedConnection(connection)
             version=connection._version
             pools,pooll=self._pools
             pool, allocated, pool_lock = pools[version]
@@ -161,19 +150,17 @@
 
         Organized by class."""
 
-        detail = {}
-        def f(con, detail=detail, have_detail=detail.has_key):
+        detail={}
+        def f(con,detail=detail,have_detail=detail.has_key):
             for oid, ob in con._cache.items():
                 module = getattr(ob.__class__, '__module__', '')
                 module = module and '%s.' % module or ''
-                c = "%s%s" % (module, ob.__class__.__name__)
-                if have_detail(c):
-                    detail[c] = detail[c] + 1
-                else:
-                    detail[c] = 1
+                c="%s%s" % (module, ob.__class__.__name__)
+                if have_detail(c): detail[c]=detail[c]+1
+                else: detail[c]=1
         
         self._connectionMap(f)
-        detail = detail.items()
+        detail=detail.items()
         detail.sort()
         return detail
 
@@ -183,7 +170,7 @@
         def f(con, detail=detail, rc=sys.getrefcount, conn_no=conn_no):
             conn_no[0] = conn_no[0] + 1
             cn = conn_no[0]
-            for oid, ob in con._cache_items():
+            for oid, ob in con._cache.items():
                 id=''
                 if hasattr(ob,'__dict__'):
                     d=ob.__dict__
@@ -230,21 +217,11 @@
     def cacheSize(self):
         m=[0]
         def f(con, m=m):
-            m[0] = m[0] + con._cache.cache_non_ghost_count
+            m[0]=m[0]+len(con._cache)
 
         self._connectionMap(f)
         return m[0]
 
-    def cacheDetailSize(self):
-        m=[]
-        def f(con, m=m):
-            m.append({'connection':repr(con),
-                      'ngsize':con._cache.cache_non_ghost_count,
-                      'size':len(con._cache)})
-        self._connectionMap(f)
-        m.sort()
-        return m
-
     def close(self): self._storage.close()
 
     def commitVersion(self, source, destination=''):
@@ -253,11 +230,8 @@
     def exportFile(self, oid, file=None):
         raise 'Not yet implemented'
                            
-    def getCacheDeactivateAfter(self):
-        return self._cache_deactivate_after
-    
-    def getCacheSize(self):
-        return self._cache_size
+    def getCacheDeactivateAfter(self): return self._cache_deactivate_after
+    def getCacheSize(self): return self._cache_size
 
     def getName(self): return self._storage.getName()
 
@@ -267,12 +241,9 @@
 
     def getVersionCacheDeactivateAfter(self):
         return self._version_cache_deactivate_after
-    
-    def getVersionCacheSize(self):
-        return self._version_cache_size
+    def getVersionCacheSize(self): return self._version_cache_size
 
-    def getVersionPoolSize(self):
-        return self._version_pool_size
+    def getVersionPoolSize(self): return self._version_pool_size
 
     def importFile(self, file):
         raise 'Not yet implemented'
@@ -287,8 +258,7 @@
         # invalidate() call.
         self._r()
 
-    def invalidate(self, oid, connection=None, version='',
-                   rc=sys.getrefcount):
+    def invalidate(self, oid, connection=None, version=''):
         """Invalidate references to a given oid.
 
         This is used to indicate that one of the connections has committed a
@@ -297,32 +267,53 @@
         connection.
         """
         if connection is not None:
-            version=connection._version
-        # Update modified in version cache
-        h=hash(oid)%131
-        o=self._miv_cache.get(h, None)
-        if o is not None and o[0]==oid: del self._miv_cache[h]
+            version = connection._version
+
+        assert oid is not None
+
+        self.updateMIVCache(oid)
 
         # Notify connections
         for pool, allocated in self._pools[1]:
             for cc in allocated:
-                if (cc is not connection and
-                    (not version or cc._version==version)):
-                    if rc(cc) <= 3:
-                        cc.close()
-                    cc.invalidate(oid)
-
-        temps=self._temps
-        if temps:
-            t=[]
-            for cc in temps:
-                if rc(cc) > 3:
-                    if (cc is not connection and
-                        (not version or cc._version==version)):
-                        cc.invalidate(oid)
-                    t.append(cc)
-                else: cc.close()
-            self._temps=t
+                if cc is not connection:
+                    self.invalidateConnection(cc, version, oid)
+
+        if self._temps:
+            # t accumulates all the connections that aren't closed.
+            t = []
+            for cc in self._temps:
+                if cc is not connection:
+                    self.invalidateConnection(cc, oid, version,
+                                              t.append)
+            self._temps = t
+
+    def invalidateConnection(self, conn, oid, version, alive=None):
+        """Send invalidation message to conn for oid on version.
+
+        If the modification occurred on a version, an invalidation is
+        sent only if the version of the mod matches the version of the
+        connection.
+
+        This function also handles garbage collection of connection's
+        that aren't used anymore.  If the optional argument alive is
+        defined, it is a function that is called for all connections
+        that aren't garbage collected.
+        """
+
+        if sys.getrefcount(conn) <= 3:
+            conn.close()
+        else:
+            if alive is not None:
+                alive(conn)
+        if not version or conn.getVersion() == version:
+            conn.invalidate(oid)
+
+    def updateMIVCache(self, oid):
+        h = hash(oid) % 131
+        o = self._miv_cache.get(h)
+        if o is not None and o[0]==oid:
+            del self._miv_cache[h]
 
     def modifiedInVersion(self, oid):
         h=hash(oid)%131
@@ -334,7 +325,7 @@
         cache[h]=oid, v
         return v
 
-    def objectCount(self):
+    def __len__(self):
         return len(self._storage)
         
     def open(self, version='', transaction=None, temporary=0, force=None,
@@ -372,15 +363,15 @@
                 # This is a temporary connection.
                 # We won't bother with the pools.  This will be
                 # a one-use connection.
-                c=self.klass(
-                    version=version,
-                    cache_size=self._version_cache_size)
-                c._setDB(self)
+                c = Connection(self, version,
+                               cache_size=self._version_cache_size,
+                               cache_deactivate_after=
+                               self._version_cache_deactivate_after)
                 self._temps.append(c)
-                if transaction is not None: transaction[id(c)]=c
+                if transaction is not None:
+                    transaction[id(c)] = c
                 return c
 
-
             pools,pooll=self._pools
 
             # pools is a mapping object:
@@ -412,7 +403,7 @@
                 pool, allocated, pool_lock = pools[version]
             else:
                 pool, allocated, pool_lock = pools[version] = (
-                    [], [], allocate_lock())
+                    [], [], Lock())
                 pooll.append((pool, allocated))
                 pool_lock.acquire()
 
@@ -421,15 +412,17 @@
                 c=None
                 if version:
                     if self._version_pool_size > len(allocated) or force:
-                        c=self.klass(
-                            version=version,
-                            cache_size=self._version_cache_size)
+                        c = Connection(self, version,
+                                       cache_size=self._version_cache_size,
+                                       cache_deactivate_after=
+                                       self._version_cache_deactivate_after)
                         allocated.append(c)
                         pool.append(c)
                 elif self._pool_size > len(allocated) or force:
-                    c=self.klass(
-                        version=version,
-                        cache_size=self._cache_size)
+                    c = Connection(self, version,
+                                   cache_size=self._cache_size,
+                                   cache_deactivate_after=
+                                   self._cache_deactivate_after)
                     allocated.append(c)
                     pool.append(c)
                     
@@ -460,10 +453,10 @@
 
             c=pool[-1]
             del pool[-1]
-            c._setDB(self)
+            c.reset()
             for pool, allocated in pooll:
                 for cc in pool:
-                    cc._incrgc()
+                    cc.cacheGC()
 
             if transaction is not None: transaction[version]=c
             return c
@@ -490,9 +483,6 @@
                     })
         return r
         
-    def getActivityMonitor(self):
-        return self._activity_monitor
-    
     def pack(self, t=None, days=0):
         if t is None: t=time()
         t=t-(days*86400)
@@ -502,30 +492,20 @@
             raise
                            
     def setCacheDeactivateAfter(self, v):
-        self._cache_deactivate_after = v
-        d = self._pools[0]
-        pool_info = d.get('')
-        if pool_info is not None:
-            for c in pool_info[1]:
-                c._cache.cache_age = v
+        self._cache_deactivate_after=v
+        for c in self._pools[0][''][1]:
+            c._cache.cache_age=v
 
     def setCacheSize(self, v):
-        self._cache_size = v
-        d = self._pools[0]
-        pool_info = d.get('')
-        if pool_info is not None:
-            for c in pool_info[1]:
-                c._cache.cache_size = v
+        self._cache_size=v
+        for c in self._pools[0][''][1]:
+            c._cache.cache_size=v
 
     def setClassFactory(self, factory):
-        self._classFactory = factory
-
-    def setPoolSize(self, v):
-        self._pool_size=v
-
-    def setActivityMonitor(self, am):
-        self._activity_monitor = am
+        self._classFactory=factory
 
+    def setPoolSize(self, v): self._pool_size=v
+    
     def setVersionCacheDeactivateAfter(self, v):
         self._version_cache_deactivate_after=v
         for ver in self._pools[0].keys():
@@ -545,20 +525,7 @@
     def cacheStatistics(self): return () # :(
 
     def undo(self, id):
-        storage=self._storage
-        try: supportsTransactionalUndo = storage.supportsTransactionalUndo
-        except AttributeError:
-            supportsTransactionalUndo=0
-        else:
-            supportsTransactionalUndo=supportsTransactionalUndo()
-
-        if supportsTransactionalUndo:
-            # new style undo
-            TransactionalUndo(self, id)
-        else:
-            # fall back to old undo
-            for oid in storage.undo(id):
-                self.invalidate(oid)
+        TransactionalUndo(self, id)
 
     def versionEmpty(self, version):
         return self._storage.versionEmpty(version)


=== Zope3/lib/python/ZODB/ExportImport.py 1.13 => 1.14 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-
 """Support for database export and import.
 """
 
-import POSException, string
+import POSException
 
 from utils import p64, u64
 from referencesf import referencesf
 from cStringIO import StringIO
 from cPickle import Pickler, Unpickler
-TupleType=type(())
+from types import StringType, TupleType
 
 class ExportImport:
 
     def exportFile(self, oid, file=None):
 
-        if file is None: file=TemporaryFile()
-        elif type(file) is StringType: file=open(file,'w+b')
-        write=file.write
-        write('ZEXP')
+        if file is None:
+            file = TemporaryFile()
+        elif isinstance(file, StringType):
+            file = open(file, 'w+b')
+        file.write('ZEXP')
         version=self._version
         ref=referencesf
         oids=[oid]
@@ -46,24 +46,20 @@
             except: pass # Ick, a broken reference
             else:
                 ref(p, oids)
-                write(oid)
-                write(p64(len(p)))
-                write(p)
-        write(export_end_marker)
+                file.write(oid)
+                file.write(p64(len(p)))
+                file.write(p)
+        file.write(export_end_marker)
         return file
 
     def importFile(self, file, clue='', customImporters=None):
         # This is tricky, because we need to work in a transaction!
 
-        if type(file) is StringType:
-            file_name=file
-            file=open(file,'rb')
-        else:
-            try: file_name=file.name
-            except: file_name='(unknown)'    
-        read=file.read
+        if isinstance(file, StringType):
+            file = open(file,'rb')
+        read = file.read
 
-        magic=read(4)
+        magic = read(4)
 
         if magic != 'ZEXP':
             if customImporters and customImporters.has_key(magic):
@@ -72,7 +68,8 @@
             raise POSException.ExportError, 'Invalid export header'
 
         t = get_transaction()
-        if clue: t.note(clue)
+        if clue:
+            t.note(clue)
 
         return_oid_list = []
         self.onCommitAction('_importDuringCommit', file, return_oid_list)
@@ -84,11 +81,12 @@
             return None
 
     def _importDuringCommit(self, transaction, file, return_oid_list):
-        '''
-        Invoked by the transaction manager mid commit.
+        """Invoked by the transaction manager mid commit.
+        
         Appends one item, the OID of the first object created,
         to return_oid_list.
-        '''
+        """
+
         oids = {}
         storage = self._storage
         new_oid = storage.new_oid
@@ -96,15 +94,16 @@
         read = file.read
 
         def persistent_load(ooid,
-                            Ghost=Ghost, StringType=StringType,
-                            atoi=string.atoi, TupleType=type(()),
+                            Ghost=Ghost, 
                             oids=oids, wrote_oid=oids.has_key,
                             new_oid=storage.new_oid):
         
             "Remap a persistent id to a new ID and create a ghost for it."
 
-            if type(ooid) is TupleType: ooid, klass = ooid
-            else: klass=None
+            if isinstance(ooid, TupleType):
+                ooid, klass = ooid
+            else:
+                klass = None
 
             if wrote_oid(ooid): oid=oids[ooid]
             else:
@@ -131,7 +130,8 @@
             ooid=h[:8]
             if oids:
                 oid=oids[ooid]
-                if type(oid) is TupleType: oid=oid[0]
+                if isinstance(oid, TupleType):
+                    oid = oid[0]
             else:
                 oids[ooid] = oid = storage.new_oid()
                 return_oid_list.append(oid)
@@ -147,13 +147,10 @@
             pickler.dump(unpickler.load())
             pickler.dump(unpickler.load())
             p=newp.getvalue()
-            plen=len(p)
 
             store(oid, None, p, version, transaction)
 
 
-StringType=type('')
-
 def TemporaryFile():
     # This is sneaky suicide
     global TemporaryFile
@@ -163,7 +160,8 @@
 
 export_end_marker='\377'*16
 
-class Ghost: pass
+class Ghost:
+    pass
 
 def persistent_id(object, Ghost=Ghost):
     if getattr(object, '__class__', None) is Ghost:


=== Zope3/lib/python/ZODB/FileStorage.py 1.91 => 1.92 === (743/843 lines abridged)
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-# 
-#  File-based ZODB storage
-# 
-# Files are arranged as follows.
-# 
-#   - The first 4 bytes are a file identifier.
-#   
-#   - The rest of the file consists of a sequence of transaction
-#     "records".
-# 
-# A transaction record consists of:
-# 
-#   - 8-byte transaction id, which is also a time stamp.
-#   
-#   - 8-byte transaction record length - 8.
-#   
-#   - 1-byte status code
-#   
-#   - 2-byte length of user name
-#   
-#   - 2-byte length of description 
-#   
-#   - 2-byte length of extension attributes 
-#   
-#   -   user name
-#   
-#   -   description
-#
-#   -   extension attributes
-# 
-#   * A sequence of data records
-#   
-#   - 8-byte redundant transaction length -8
-# 
-# A data record consists of
-# 
-#   - 8-byte oid.
-# 
-#   - 8-byte serial, which is a type stamp that matches the
-#     transaction timestamp.
-# 
-#   - 8-byte previous-record file-position.
-# 
-#   - 8-byte beginning of transaction record file position.

[-=- -=- -=- 743 lines omitted -=- -=- -=-]

+            unpack=struct.unpack
+            strip=string.strip
+            encode=base64.encodestring
+            r=[]
+            append=r.append
+            i=0
+            while i < last and pos > 39:
+                seek(pos-8)
+                pos=pos-U64(read(8))-8
+                seek(pos)
+                h=read(TRANS_HDR_LEN)
+                tid, tl, status, ul, dl, el = unpack(">8s8scHHH", h)
+                if tid < packt: break
+                if status != ' ': continue
+                u=ul and read(ul) or ''
+                d=dl and read(dl) or ''
+                d={'id': encode(tid+p64(pos))[:22],
+                   'time': TimeStamp(tid).timeTime(),
+                   'user_name': u, 'description': d}
+                if el:
+                    try: 
+                        e=loads(read(el))
+                        d.update(e)
+                    except: pass
+                if filter is None or filter(d):
+                    if i >= first: append(d)
+                    i=i+1
+                
+            return r
+        finally: self._lock_release()
 
     def versionEmpty(self, version):
         if not version:
@@ -2120,11 +1974,11 @@
                   name, pos)
         pos=pos+8
 
-        if tindex: # avoid the pathological empty transaction case
-            _maxoid = max(tindex.keys()) # in 2.2, just max(tindex)
-            maxoid = max(_maxoid, maxoid)
-            index.update(tindex)
-            tindex.clear()
+        _maxoid = max(tindex.keys()) # in 2.2, just max(tindex)
+        maxoid = max(_maxoid, maxoid)
+        index.update(tindex)
+
+        tindex.clear()
 
     return pos, maxoid, ltid
 


=== Zope3/lib/python/ZODB/MappingStorage.py 1.6 => 1.7 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Very Simple Mapping ZODB storage
@@ -86,8 +86,8 @@
 
 and call it to minotor the storage.
 
+$Id$
 """
-__version__='$Revision$'[11:-2]
 
 import POSException, BaseStorage, string, utils
 from TimeStamp import TimeStamp


=== Zope3/lib/python/ZODB/POSException.py 1.11 => 1.12 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-"""BoboPOS-defined exceptions
+"""ZODB-defined exceptions
 
-$Id$"""
-__version__ = '$Revision$'.split()[-2:][0]
+$Id$
+"""
+
+import Transaction.Exceptions
+from Transaction.Exceptions import TransactionError
 
 from string import join
 from types import StringType, DictType
@@ -35,7 +38,7 @@
     """An error occured due to normal transaction processing
     """
 
-class ConflictError(TransactionError):
+class ConflictError(Transaction.Exceptions.ConflictError):
     """Two transactions tried to modify the same object at once.  This
     transaction should be resubmitted.
 
@@ -117,13 +120,6 @@
             message = "database read conflict error"
         ConflictError.__init__(self, message=message, object=object,
                                serials=serials)
-
-class BTreesConflictError(ConflictError):
-    """A special subclass for BTrees conflict errors, which return
-    an undocumented four-tuple."""
-    def __init__(self, *btree_args):
-        ConflictError.__init__(self, message="BTrees conflict error")
-        self.btree = btree_args
 
 class VersionError(POSError):
     """An error in handling versions occurred


=== Zope3/lib/python/ZODB/TimeStamp.c 1.15 => 1.16 === (628/728 lines abridged)
 
-  Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-  All Rights Reserved.
+  Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
   
   This software is subject to the provisions of the Zope Public License,
   Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
@@ -12,52 +11,22 @@
   
  ****************************************************************************/
 
-static char TimeStamp_module_documentation[] = 
-"Defines 64-bit TimeStamp objects used as ZODB serial numbers.\n"
-"\n"
-"\n$Id$\n";
-
 #include <stdlib.h>
 #include <time.h>
-#ifdef USE_EXTENSION_CLASS
-#include "ExtensionClass.h"
-#else
 #include "Python.h"
-#endif
-
-
-/* ----------------------------------------------------- */
 
-#define UNLESS(E) if(!(E))
-#define OBJECT(O) ((PyObject*)(O))
+PyObject *TimeStamp_FromDate(int, int, int, int, int, double);
+PyObject *TimeStamp_FromString(const char *);
 
-/* Declarations for objects of type TimeStamp */
+static char TimeStampModule_doc[] = 
+"A 64-bit TimeStamp used as a ZODB serial number.\n";
 
 typedef struct {
-  PyObject_HEAD
-  unsigned char data[8];
+    PyObject_HEAD
+    unsigned char data[8];
 } TimeStamp;
 
-static double
-TimeStamp_yad(int y)
-{
-  double d, s;
-
-  y -= 1900;
-  

[-=- -=- -=- 628 lines omitted -=- -=- -=-]

-static struct PyMethodDef Module_Level__methods[] = {
-#ifndef USE_EXTENSION_CLASS
-  {"TimeStamp", (PyCFunction)newTimeStamp, METH_VARARGS, ""},
-#endif
-  {NULL, (PyCFunction)NULL, 0, NULL}		/* sentinel */
-};
 
 void
 initTimeStamp(void)
 {
-  PyObject *m, *d, *s;
+    PyObject *m;
+
+    if (TimeStamp_init_gmoff() < 0)
+	return;
 
-  if (TimeStamp_init_gmoff() < 0) return;
-  if (! ExtensionClassImported) return;
+    m = Py_InitModule4("TimeStamp", TimeStampModule_functions,
+		       TimeStampModule_doc, NULL, PYTHON_API_VERSION);
+    if (m == NULL)
+	return;
 
-  /* Create the module and add the functions */
-  m = Py_InitModule4("TimeStamp", Module_Level__methods,
-		     TimeStamp_module_documentation,
-		     (PyObject*)NULL,PYTHON_API_VERSION);
-
-  /* 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));
-
-  s = PyString_FromString("TimeStamp.error");
-  PyDict_SetItemString(d, "error", s);
-  Py_XDECREF(s);
-
-  /* Check for errors */
-  if (PyErr_Occurred())
-    Py_FatalError("can't initialize module TimeStamp");
+    TimeStamp_type.ob_type = &PyType_Type;
+    TimeStamp_type.tp_getattro = PyObject_GenericGetAttr;
 }
+ 


=== Zope3/lib/python/ZODB/TmpStore.py 1.6 => 1.7 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-
 import POSException
 from utils import p64, u64
 
@@ -23,15 +22,16 @@
             import tempfile
             file=tempfile.TemporaryFile()
 
-        self._file=file
-        self._index={}
-        self._pos=self._tpos=0
-        self._bver=base_version
-        self._tindex=[]
-        self._db=None
-        self._creating=[]
+        self._file = file
+        self._index = {}
+        self._pos = self._tpos = 0
+        self._bver = base_version
+        self._tindex = []
+        self._db = None
+        self._created = []
 
-    def __del__(self): self.close()
+    def __del__(self):
+        self.close()
 
     def close(self):
         self._file.close()
@@ -39,8 +39,11 @@
         del self._index
         del self._db
 
-    def getName(self): return self._db.getName()
-    def getSize(self): return self._pos
+    def getName(self):
+        return self._db.getName()
+    
+    def getSize(self):
+        return self._pos
 
     def load(self, oid, version):
         #if version is not self: raise KeyError, oid
@@ -55,14 +58,16 @@
         return file.read(u64(h[16:])), h[8:16]
         
     def modifiedInVersion(self, oid):
-        if self._index.has_key(oid): return 1
+        if self._index.has_key(oid):
+            return 1
         return self._db._storage.modifiedInVersion(oid)
 
-    def new_oid(self): return self._db._storage.new_oid()
+    def new_oid(self):
+        return self._db._storage.new_oid()
 
     def registerDB(self, db, limit):
-        self._db=db
-        self._storage=db._storage
+        self._db = db
+        self._storage = db._storage
 
     def store(self, oid, serial, data, version, transaction):
         if transaction is not self._transaction:


=== Zope3/lib/python/ZODB/ZApplication.py 1.10 => 1.11 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Implement an bobo_application object that is BoboPOS3 aware
 
 This module provides a wrapper that causes a database connection to be created
 and used when bobo publishes a bobo_application object.
+
+$Id$
 """
-__version__='$Revision$'[11:-2]
 
 StringType=type('')
 connection_open_hooks = []
@@ -54,9 +55,9 @@
         # arrange for the connection to be closed when the request goes away
         cleanup=Cleanup()
         cleanup.__del__=conn.close
-        REQUEST._hold(cleanup)
+        REQUEST.hold(cleanup)
 
-        conn.setDebugInfo(REQUEST.environ, REQUEST.other)
+##        conn.setDebugInfo(REQUEST.environ, REQUEST.other)
         
         v=conn.root()[aname]
 


=== Zope3/lib/python/ZODB/__init__.py 1.12 => 1.13 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-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
+import sys, Transaction
+sys.modules['ZODB.Transaction']=Transaction
+del sys
+del Transaction


=== Zope3/lib/python/ZODB/dbmStorage.py 1.3 => 1.4 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Very Simple dbm-based ZODB storage
@@ -17,8 +17,9 @@
 don't support versions or Undo.  This may be useful when implementing
 objects like hit counters that don't need or want to participate
 in undo or versions.
+
+$Id$
 """
-__version__='$Revision$'[11:-2]
 
 import base64, POSException, time, string, utils
 


=== Zope3/lib/python/ZODB/fsIndex.py 1.2 => 1.3 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Implement an OID to File-position (long integer) mapping
@@ -34,7 +34,7 @@
 # bytes back before using U64 to convert the data back to (long)
 # integers.
 
-from BTrees._fsBTree import fsBTree as _fsBTree
+from Persistence.BTrees._fsBTree import fsBTree as _fsBTree
 
 import struct
 


=== Zope3/lib/python/ZODB/fsdump.py 1.3 => 1.4 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+# 
+##############################################################################
 from ZODB.FileStorage import FileIterator
 from ZODB.TimeStamp import TimeStamp
 from ZODB.utils import U64


=== Zope3/lib/python/ZODB/fsrecover.py 1.4 => 1.5 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-
-
 """Simple script for repairing damaged FileStorage files.
 
 Usage: %s [-f] input output
@@ -259,7 +257,7 @@
                 if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
                 ok=0
                 _ts=t.laterThan(_ts)
-                tid=`_ts`
+                tid=_ts.raw()
             else:
                 _ts = t
                 if not ok:


=== Zope3/lib/python/ZODB/lock_file.py 1.5 => 1.6 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-
 import POSException
 
 # Try to create a function that creates Unix file locks.  On windows


=== Zope3/lib/python/ZODB/referencesf.py 1.5 => 1.6 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
 """Provide a function that can find object references in pickles


=== Zope3/lib/python/ZODB/utils.py 1.11 => 1.12 ===
 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-
-import sys
 import TimeStamp, time, struct
 
-if sys.version >= (2, 2):
+def p64(v, pack=struct.pack):
+    """Pack an integer or long into a 8-byte string"""
+    return pack(">Q", v)
+
+# Note that the distinction between ints and longs is blurred in
+# Python 2.2.  So make u64() and U64() the same.
+
+def u64(v, unpack=struct.unpack):
+    """Unpack an 8-byte string into a 64-bit long integer."""
+    return unpack(">Q", v)[0]
 
-    # Note that the distinction between ints and longs is blurred in
-    # Python 2.2.  So make u64() and U64() the same.
+U64 = u64
 
-    def p64(v, pack=struct.pack):
-        """Pack an integer or long into a 8-byte string"""
-        return pack(">Q", v)
-
-    def u64(v, unpack=struct.unpack):
-        """Unpack an 8-byte string into a 64-bit long integer."""
-        return unpack(">Q", v)[0]
-
-    U64 = u64
-
-else:
-
-    t32 = 1L << 32
-
-    def p64(v, pack=struct.pack):
-        """Pack an integer or long into a 8-byte string"""
-        if v < t32:
-            h = 0
-        else:
-            h, v = divmod(v, t32)
-        return pack(">II", h, v)
-
-    def u64(v, unpack=struct.unpack):
-        """Unpack an 8-byte string into a 64-bit (or long) integer."""
-        h, v = unpack(">ii", v)
-        if v < 0:
-            v = t32 + v
-        if h:
-            if h < 0:
-                h= t32 + h
-            v = (long(h) << 32) + v
-        return v
-
-    def U64(v, unpack=struct.unpack):
-        """Same as u64 but always returns a long."""
-        h, v = unpack(">II", v)
-        if h:
-            v = (long(h) << 32) + v
-        return v
+# clients use this module to get this contant
+t32 = 1L << 32
 
 def cp(f1, f2, l):
     read = f1.read
     write = f2.write
-    n = 8192
+    n =8192
     
     while l > 0:
         if n > l:


=== Zope3/lib/python/ZODB/winlock.c 1.8 => 1.9 ===

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

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

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

=== Removed File Zope3/lib/python/ZODB/PersistentList.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/UndoLogCompatible.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 ===