[Zope-Checkins] CVS: Zope3/lib/python/ZODB - Connection.py:1.60.6.9 DB.py:1.34.4.5 ExportImport.py:1.11.86.4 ZApplication.py:1.8.60.2

Jeremy Hylton jeremy@zope.com
Sun, 10 Mar 2002 16:26:14 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	Connection.py DB.py ExportImport.py ZApplication.py 
Log Message:
Refactor Connection object.

Rename updateCodeTimeStamp() to resetPersistentCaches().  The old name
    described an implementation strategy.  The new name describes the
    interface.  Updated two uses in ZopeLegacy.

Remove getDebugInfo() and setDebugInfo().  It was used in ZApplication
    and in ZopePublication.  I could only find calls to set the debug
    info, none to read it.  So I've removed this on YAGNI grounds.  It
    should be easy to restore if it's actually used somewhere.

Removed tConnection() subclass that was unused and _breakcr() method
    in Connection base that was only called by tConnection().  The
    Python GC should break cycles for us anyway.

Removed self._incrgc alias for self.cacheGC, which is in turn an alias
    for Cache().incrgc.  The cacheGC attribute seems to be used by
    ZopeLegacy code, although it only seems to happen through DTML; so
    I'm not really sure.

Remove try/except around unpickler.load() in __getitem__ of
    Connection.  It was a blind try/except that hid whatever the real
    exception was.  It raised a long string that was basically
    impossible to catch, because it was formatted to contain the oid
    of the object.  It seems more helpful to have a traceback with the
    real exception.

Add some helper methods that handle unpickling of objects and their
    states.   Used by __getitem__() and setstate().

Replace mtime() implementation with an even simpler stub.  This method
    is required by the interface, but there is no real implementation
    or user yet.

Deleted setklassstate() method, which was not documented or called by
    any code in Zope or ZODB.


=== Zope3/lib/python/ZODB/Connection.py 1.60.6.8 => 1.60.6.9 === (729/829 lines abridged)
 """Database connection support
 
+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.
+
+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$
 """
 
@@ -23,24 +50,27 @@
 
 from Persistence.Cache import Cache
 from Transaction import get_transaction
-from zLOG import LOG, ERROR, BLATHER
+from zLOG import LOG, ERROR, BLATHER, INFO
 
 from cPickle import Unpickler, Pickler
 from cStringIO import StringIO
 import sys
-from time import time
+import time
 from types import StringType, ClassType, TupleType
 
-global_code_timestamp = 0
+# XXX Does this need to be an actual timestamp or would a counter be
+# sufficient? 
+_cache_timestamp = 0

[-=- -=- -=- 729 lines omitted -=- -=- -=-]

+        self.cacheGC() # This is a good time to do some GC
 
     def _invalidate_invalidating(self):
-        invalidate=self._db.invalidate
         for oid in self._invalidating:
-            invalidate(oid, self)
+            self._db.invalidate(oid, self)
         self._db.finish_invalidation()
 
     def sync(self):
         get_transaction().abort()
-        sync=getattr(self._storage, 'sync', 0)
-        if sync != 0: sync()
+        sync = getattr(self._storage, 'sync', None)
+        if sync is not None:
+            sync()
         self._cache.invalidateMany(self._invalidated.iterkeys())
         self._invalidated.clear()
-        self._incrgc() # This is a good time to do some GC
-
-    def getDebugInfo(self): return self._debug_info
-    def setDebugInfo(self, *args): self._debug_info=self._debug_info+args
+        self.cacheGC() # This is a good time to do some GC
 
-
-    ######################################################################
-    # 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
+        # XXX This seems to exist only to support ZClasses.
+        # replace old's cache entry with 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
+        self._cache[oid] = new
         
-class tConnection(Connection):
-
-    def close(self):
-        self._breakcr()
-
 def new_persistent_id(self, stack):
     # XXX need a doc string.  not sure if the one for persistent_id()
     # below is correct.


=== Zope3/lib/python/ZODB/DB.py 1.34.4.4 => 1.34.4.5 ===
                     cache_deactivate_after=
                     self._version_cache_deactivate_after)
-                c._setDB(self)
+                c.registerDB(self)
                 self._temps.append(c)
                 if transaction is not None: transaction[id(c)]=c
                 return c
@@ -442,7 +442,7 @@
 
             c=pool[-1]
             del pool[-1]
-            c._setDB(self)
+            c.registerDB(self)
             for pool, allocated in pooll:
                 for cc in pool:
                     cc._incrgc()


=== Zope3/lib/python/ZODB/ExportImport.py 1.11.86.3 => 1.11.86.4 ===
 """
 
-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,20 +47,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=open(file,'rb')
-        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):
@@ -68,7 +69,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)
@@ -80,11 +82,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
@@ -93,14 +96,15 @@
 
         def persistent_load(ooid,
                             Ghost=Ghost, 
-                            TupleType=type(()),
                             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:
@@ -127,7 +131,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,8 +152,6 @@
             store(oid, None, p, version, transaction)
 
 
-StringType=type('')
-
 def TemporaryFile():
     # This is sneaky suicide
     global TemporaryFile
@@ -158,7 +161,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/ZApplication.py 1.8.60.1 => 1.8.60.2 ===
         REQUEST._hold(cleanup)
 
-        conn.setDebugInfo(REQUEST.environ, REQUEST.other)
+##        conn.setDebugInfo(REQUEST.environ, REQUEST.other)
         
         v=conn.root()[aname]