[Zope-Checkins] SVN: Zope/branches/zodb-blobs-branch/lib/python/ Initial changes to support the use of multidatabases instead of Mount.py's homegrown mounting support.

Chris McDonough chrism at plope.com
Sun Sep 25 13:16:00 EDT 2005


Log message for revision 38625:
  Initial changes to support the use of multidatabases instead of Mount.py's homegrown mounting support.
  

Changed:
  U   Zope/branches/zodb-blobs-branch/lib/python/DBTab/DBTab.py
  U   Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/Mount.py
  U   Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/MountedObject.py
  U   Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/tests/testMountPoint.py
  U   Zope/branches/zodb-blobs-branch/lib/python/Zope2/Startup/datatypes.py

-=-
Modified: Zope/branches/zodb-blobs-branch/lib/python/DBTab/DBTab.py
===================================================================
--- Zope/branches/zodb-blobs-branch/lib/python/DBTab/DBTab.py	2005-09-25 17:02:02 UTC (rev 38624)
+++ Zope/branches/zodb-blobs-branch/lib/python/DBTab/DBTab.py	2005-09-25 17:15:59 UTC (rev 38625)
@@ -17,7 +17,6 @@
 """
 
 import sys
-from thread import allocate_lock
 
 from ZODB.ActivityMonitor import ActivityMonitor
 import Globals
@@ -31,11 +30,10 @@
 
     def __init__(self, db_factories, mount_paths):
         self._started = 0
-        self.opened = {}            # { name -> Database instance }
-        self.lock = allocate_lock()
 
         self.db_factories = db_factories  # { name -> DatabaseFactory }
         self.mount_paths = mount_paths    # { virtual path -> name }
+        self.databases = {}
 
     def startup(self):
         """Opens the databases set to open_at_startup."""
@@ -76,45 +74,25 @@
     def getDatabase(self, mount_path=None, name=None, is_root=0):
         """Returns an opened database.  Requires either mount_path or name.
         """
-        self.startup()
+        self.startup() # XXX get rid of this
         if name is None:
-            if mount_path is None:
-                raise ValueError('Either mount_path or name is required')
-            name = self.mount_paths.get(mount_path)
-            if name is None:
-                self._mountPathError(mount_path)
-        db = self.opened.get(name)
+            name = self.getName(mount_path)
+        db = self.databases.get(name, None)
         if db is None:
-            if not self.db_factories.has_key(name):
-                raise KeyError('%s is not a configured database' % repr(name))
-            self.lock.acquire()
-            try:
-                # Check again, since the database may have been created
-                # by another thread before the lock was acquired.
-                db = self.opened.get(name)
-                if db is None:
-                    db = self._createDatabase(name, is_root)
-            finally:
-                self.lock.release()
+            factory = self.getDatabaseFactory(name=name)
+            db = factory.open(name, self.databases)
         return db
 
     def getDatabaseFactory(self, mount_path=None, name=None):
         if name is None:
-            if mount_path is None:
-                raise ValueError('Either mount_path or name is required')
-            name = self.mount_paths.get(mount_path)
-            if name is None:
-                self._mountPathError(mount_path)
+            name = self.getName(mount_path)
+        if not self.db_factories.has_key(name):
+            raise KeyError('%s is not a configured database' % repr(name))
         return self.db_factories[name]
 
+    def getName(self, mount_path):
+        name = self.mount_paths.get(mount_path)
+        if name is None:
+            self._mountPathError(mount_path)
+        return name
 
-    def _createDatabase(self, name, is_root):
-        factory = self.db_factories[name]
-        db = factory.open()
-        self.opened[name] = db
-        if not is_root:
-            Globals.opened.append(db)
-        # If it is the root database, Zope will add the database to
-        # Globals.opened.  A database should not be listed twice.
-        return db
-

Modified: Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/Mount.py
===================================================================
--- Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/Mount.py	2005-09-25 17:02:02 UTC (rev 38624)
+++ Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/Mount.py	2005-09-25 17:15:59 UTC (rev 38625)
@@ -69,17 +69,9 @@
 
     def _getMountedConnection(self, anyjar):
         db_name = self._getDBName()
-        conn = anyjar._getMountedConnection(db_name)
-        if conn is None:
-            root_conn = anyjar._getRootConnection()
-            if db_name == self._getRootDBName():
-                conn = root_conn
-            else:
-                conn = self._getDB().open(version=root_conn.getVersion())
-                root_conn._addMountedConnection(db_name, conn)
+        conn = anyjar.get_connection(db_name)
         return conn
 
-
     def _getOrOpenObject(self, parent):
         t = self._v_data
         if t is not None:
@@ -143,95 +135,3 @@
         traceback.print_tb(exc[2], 100, f)
         self._v_connect_error = (exc[0], exc[1], f.getvalue())
         exc = None
-
-
-
-class ConnectionPatches:
-    # Changes to Connection.py that might fold into ZODB
-
-    _root_connection = None
-    _mounted_connections = None
-
-    def _getRootConnection(self):
-        root_conn = self._root_connection
-        if root_conn is None:
-            return self
-        else:
-            return root_conn
-
-    def _getMountedConnection(self, name):
-        conns = self._getRootConnection()._mounted_connections
-        if conns is None:
-            return None
-        else:
-            return conns.get(name)
-
-    def _addMountedConnection(self, name, conn):
-        if conn._root_connection is not None:
-            raise ValueError, 'Connection %s is already mounted' % repr(conn)
-        root_conn = self._getRootConnection()
-        conns = root_conn._mounted_connections
-        if conns is None:
-            conns = {}
-            root_conn._mounted_connections = conns
-        if conns.has_key(name):
-            raise KeyError, 'A connection named %s already exists' % repr(name)
-        conn._root_connection = root_conn
-        conns[name] = conn
-
-    def _setDB(self, odb, *args, **kw):
-        self._real_setDB(odb, *args, **kw)
-        conns = self._mounted_connections
-        if conns:
-            for conn in conns.values():
-                conn._setDB(conn._db, *args, **kw)
-
-    def close(self):
-        if self._root_connection is not None:
-            raise RuntimeError("Should not close mounted connections directly")
-        conns = self._mounted_connections
-        if conns:
-            for conn in conns.values():
-                # Notify the activity monitor
-                db = conn.db()
-                f = getattr(db, 'getActivityMonitor', None)
-                if f is not None:
-                    am = f()
-                    if am is not None:
-                        am.closedConnection(conn)
-                conn.cacheGC() # This is a good time to do some GC
-                # XXX maybe we ought to call the close callbacks.
-                conn._storage = conn._normal_storage = None
-                conn._savepoint_storage = None
-                conn.new_oid = conn._opened = None
-                conn._debug_info = ()
-
-                # collector #1350: ensure that the connection is unregistered
-                # from the transaction manager (XXX API method?)
-                if conn._synch:
-                    conn.transaction_manager.unregisterSynch(conn)
-
-                # The mounted connection keeps a reference to
-                # its database, but nothing else.
-                # Note that mounted connections can not operate
-                # independently, so don't use _closeConnection() to
-                # return them to the pool.  Only the root connection
-                # should be returned.
-
-        # Close this connection only after the mounted connections
-        # have been closed.  Otherwise, this connection gets returned
-        # to the pool too early and another thread might use this
-        # connection before the mounted connections have all been
-        # closed.
-        self._real_close()
-
-if 1:
-    # patch Connection.py.
-    from ZODB.Connection import Connection
-    Connection._real_setDB = Connection._setDB
-    Connection._real_close = Connection.close
-
-    for k, v in ConnectionPatches.__dict__.items():
-        if not k.startswith('__'):
-            setattr(Connection, k, v)
-

Modified: Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/MountedObject.py
===================================================================
--- Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/MountedObject.py	2005-09-25 17:02:02 UTC (rev 38624)
+++ Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/MountedObject.py	2005-09-25 17:15:59 UTC (rev 38625)
@@ -107,7 +107,7 @@
         obj = context.unrestrictedTraverse(id)
         # Commit a subtransaction to assign the new object to
         # the correct database.
-        transaction.commit(1)
+        transaction.savepoint()
         return obj
 
 
@@ -133,6 +133,14 @@
         id = path.split('/')[-1]
         MountPoint.__init__(self, id)
 
+    def _getMountedConnection(self, anyjar):
+        db_name = self._getDBName()
+        try:
+            conn = anyjar.get_connection(db_name)
+        except KeyError:
+            conn = self._getDB().open()
+        return conn
+
     def mount_error_(self):
         return self._v_connect_error
 
@@ -177,7 +185,7 @@
                 obj = Application()
                 root[real_root] = obj
                 # Get it into the database
-                transaction.commit(1)
+                transaction.savepoint()
             else:
                 raise
 

Modified: Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/tests/testMountPoint.py
===================================================================
--- Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/tests/testMountPoint.py	2005-09-25 17:02:02 UTC (rev 38624)
+++ Zope/branches/zodb-blobs-branch/lib/python/Products/ZODBMountPoint/tests/testMountPoint.py	2005-09-25 17:15:59 UTC (rev 38625)
@@ -107,7 +107,7 @@
         self.app._p_jar.close()
         del self.app
         del self.db
-        for db in self.conf.opened.values():
+        for db in self.conf.databases.values():
             db.close()
         del self.conf
 

Modified: Zope/branches/zodb-blobs-branch/lib/python/Zope2/Startup/datatypes.py
===================================================================
--- Zope/branches/zodb-blobs-branch/lib/python/Zope2/Startup/datatypes.py	2005-09-25 17:02:02 UTC (rev 38624)
+++ Zope/branches/zodb-blobs-branch/lib/python/Zope2/Startup/datatypes.py	2005-09-25 17:15:59 UTC (rev 38625)
@@ -149,18 +149,18 @@
             mount_points[point] = name
     from DBTab.DBTab import DBTab
     section.dbtab = DBTab(mount_factories, mount_points)
-
+    
     return section
 
 class ZopeDatabase(ZODBDatabase):
     """ A ZODB database datatype that can handle an extended set of
     attributes for use by DBTab """
 
-    def createDB(self):
-        return ZODBDatabase.open(self)
+    def createDB(self, database_name, databases):
+        return ZODBDatabase.open(self, database_name, databases)
 
-    def open(self):
-        DB = self.createDB()
+    def open(self, database_name, databases):
+        DB = self.createDB(database_name, databases)
         if self.config.connection_class:
             # set the connection class
             DB.klass = self.config.connection_class



More information about the Zope-Checkins mailing list