Commit 4babe9e1 authored by Jim Fulton's avatar Jim Fulton

Reverted changes in rev r24514 that broke mount points.

Made a small fix to _setDB in Mount.py to pass 
through new args passed to it.

With these changes, Zope now runs again.
parent 7f8def24
...@@ -75,16 +75,12 @@ def autoClassFactory(jar, module, name): ...@@ -75,16 +75,12 @@ def autoClassFactory(jar, module, name):
""" """
# If not the root connection, use the class factory from # If not the root connection, use the class factory from
# the root database, otherwise use the Zope class factory. # the root database, otherwise use the Zope class factory.
# The default Zope configuration installs this function as the DB
# class's classFactory() method.
root_conn = getattr(jar, '_root_connection', None) root_conn = getattr(jar, '_root_connection', None)
if root_conn is not jar: root_db = getattr(root_conn, '_db', None)
root_db = getattr(root_conn, '_db', None) if root_db is not None:
if root_db is not None: return root_db.classFactory(root_conn, module, name)
return root_db.classFactory(root_conn, module, name) else:
return zopeClassFactory(jar, module, name) return zopeClassFactory(jar, module, name)
class_factories['auto'] = autoClassFactory class_factories['auto'] = autoClassFactory
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
$Id$ $Id$
""" """
import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_ import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_
import time, traceback, os, Products import time, traceback, os, Products
from DateTime import DateTime from DateTime import DateTime
...@@ -323,10 +324,10 @@ class AppInitializer: ...@@ -323,10 +324,10 @@ class AppInitializer:
def install_tempfolder_and_sdc(self): def install_tempfolder_and_sdc(self):
app = self.getApp() app = self.getApp()
from Products.ZODBMountPoint.MountedObject \ from Products.ZODBMountPoint.MountedObject import manage_addMounts,\
import manage_addMounts, MountedObject MountedObject
from Products.ZODBMountPoint.MountedObject \ from Products.ZODBMountPoint.MountedObject import getConfiguration as \
import getConfiguration as getDBTabConfiguration getDBTabConfiguration
dbtab_config = getDBTabConfiguration() dbtab_config = getDBTabConfiguration()
......
...@@ -28,16 +28,13 @@ import Persistence, Acquisition ...@@ -28,16 +28,13 @@ import Persistence, Acquisition
from Acquisition import aq_base from Acquisition import aq_base
from ZODB.POSException import MountedStorageError from ZODB.POSException import MountedStorageError
from ZODB.DB import DB
from ZODB.Connection import Connection
LOG = getLogger('Zope.ZODBMountPoint') LOG = getLogger('Zope.ZODBMountPoint')
class MountPoint(Persistence.Persistent, Acquisition.Implicit): class MountPoint(Persistence.Persistent, Acquisition.Implicit):
"""An object that accesses a different database when traversed. '''The base class for a Zope object which, when traversed,
accesses a different database.
This class is intended to be used as a base class. '''
"""
# Default values for non-persistent variables. # Default values for non-persistent variables.
_v_data = None # An object in an open connection _v_data = None # An object in an open connection
...@@ -47,19 +44,23 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit): ...@@ -47,19 +44,23 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit):
self.id = id self.id = id
def _getDB(self): def _getDB(self):
"""Hook for getting the DB object for this mount point.""" """Hook for getting the DB object for this mount point.
"""
raise NotImplementedError raise NotImplementedError
def _getDBName(self): def _getDBName(self):
"""Hook for getting the name of the database for this mount point.""" """Hook for getting the name of the database for this mount point.
"""
raise NotImplementedError raise NotImplementedError
def _getRootDBName(self): def _getRootDBName(self):
"""Hook for getting the name of the root database.""" """Hook for getting the name of the root database.
"""
raise NotImplementedError raise NotImplementedError
def _traverseToMountedRoot(self, root, mount_parent): def _traverseToMountedRoot(self, root, mount_parent):
"""Hook for getting the object to be mounted.""" """Hook for getting the object to be mounted.
"""
raise NotImplementedError raise NotImplementedError
def __repr__(self): def __repr__(self):
...@@ -122,13 +123,20 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit): ...@@ -122,13 +123,20 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit):
def _test(self, parent): def _test(self, parent):
"""Tests the database connection.""" '''Tests the database connection.
'''
self._getOrOpenObject(parent) self._getOrOpenObject(parent)
return 1 return 1
def _logConnectException(self): def _logConnectException(self):
"""Records info about the exception that just occurred.""" '''Records info about the exception that just occurred.
'''
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
import traceback
exc = sys.exc_info() exc = sys.exc_info()
LOG.error('Failed to mount database. %s (%s)' % exc[:2], exc_info=exc) LOG.error('Failed to mount database. %s (%s)' % exc[:2], exc_info=exc)
f=StringIO() f=StringIO()
...@@ -136,73 +144,85 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit): ...@@ -136,73 +144,85 @@ class MountPoint(Persistence.Persistent, Acquisition.Implicit):
self._v_connect_error = (exc[0], exc[1], f.getvalue()) self._v_connect_error = (exc[0], exc[1], f.getvalue())
exc = None exc = None
class MountConnection(Connection):
"""Subclass of Connection that supports mounts."""
# XXX perhaps the code in this subclass should be folded into
# ZODB proper.
def __init__(self, **kwargs): class ConnectionPatches:
Connection.__init__(self, **kwargs) # Changes to Connection.py that might fold into ZODB
# The _root_connection of the actual root points to self. All
# other connections will have _root_connection over-ridden in _root_connection = None
# _addMountedConnection(). _mounted_connections = None
self._root_connection = self
self._mounted_connections = {}
def _getRootConnection(self): def _getRootConnection(self):
return self._root_connection root_conn = self._root_connection
if root_conn is None:
return self
else:
return root_conn
def _getMountedConnection(self, name): def _getMountedConnection(self, name):
return self._root_connection._mounted_connections.get(name) conns = self._getRootConnection()._mounted_connections
if conns is None:
return None
else:
return conns.get(name)
def _addMountedConnection(self, name, conn): def _addMountedConnection(self, name, conn):
if conn._root_connection is not conn: if conn._root_connection is not None:
raise ValueError("Connection %s is already mounted" % repr(conn)) raise ValueError, 'Connection %s is already mounted' % repr(conn)
conns = self._root_connection._mounted_connections root_conn = self._getRootConnection()
if name in conns: conns = root_conn._mounted_connections
raise KeyError("A connection named %s already exists" % repr(name)) if conns is None:
conn._root_connection = self._root_connection 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 conns[name] = conn
def _setDB(self, odb, **kwargs): def _setDB(self, odb, *args, **kw):
Connection._setDB(self, odb, **kwargs) self._real_setDB(odb, *args, **kw)
for conn in self._mounted_connections.values(): conns = self._mounted_connections
conn._setDB(odb, **kwargs) if conns:
for conn in conns.values():
conn._setDB(conn._db, *args, **kw)
def close(self): def close(self):
if self._root_connection is not self: if self._root_connection is not None:
raise RuntimeError("Should not close mounted connections directly") raise RuntimeError("Should not close mounted connections directly")
conns = self._mounted_connections
# The code here duplicates much of the code in if conns:
# DB._closeConnection and Connection.close. A mounted for conn in conns.values():
# connection can't operate independently, so we don't call # Notify the activity monitor
# DB._closeConnection(), which would return it to the db = conn.db()
# connection pool; only the root connection should be f = getattr(db, 'getActivityMonitor', None)
# returned. if f is not None:
am = f()
for conn in self._mounted_connections.values(): if am is not None:
# DB._closeConnection calls the activity monitor am.closedConnection(conn)
am = conn._db.getActivityMonitor() conn.cacheGC() # This is a good time to do some GC
am.closedConnection(conn) # XXX maybe we ought to call the close callbacks.
# Connection.close does GC conn._storage = conn._tmp = conn.new_oid = conn._opened = None
conn._cache.incrgc() conn._debug_info = ()
conn._storage = conn._tmp = conn.new_oid = conn._opened = None # The mounted connection keeps a reference to
conn._debug_info = () # its database, but nothing else.
# The mounted connection keeps a reference to # Note that mounted connections can not operate
# its database, but nothing else. # 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 # Close this connection only after the mounted connections
# have been closed. Otherwise, this connection gets returned # have been closed. Otherwise, this connection gets returned
# to the pool too early and another thread might use this # to the pool too early and another thread might use this
# connection before the mounted connections have all been # connection before the mounted connections have all been
# closed. # closed.
Connection.close(self) self._real_close()
# Replace the default database Connection if 1:
def install(): # patch Connection.py.
DB.klass = MountConnection from ZODB.Connection import Connection
Connection._real_setDB = Connection._setDB
# XXX This shouldn't be done as a side-effect of import, but it's not Connection._real_close = Connection.close
# clear where in the Zope initialization code it should be done.
install() for k, v in ConnectionPatches.__dict__.items():
if not k.startswith('__'):
setattr(Connection, k, v)
...@@ -22,9 +22,7 @@ import ZODB ...@@ -22,9 +22,7 @@ import ZODB
from OFS.Application import Application from OFS.Application import Application
from OFS.Folder import Folder from OFS.Folder import Folder
import App.config import App.config
from Products.ZODBMountPoint.MountedObject \ from Products.ZODBMountPoint.MountedObject import manage_addMounts, getMountPoint
import manage_addMounts, getMountPoint
from Products.ZODBMountPoint.Mount import MountConnection
from DBTab.DBTab import DBTab from DBTab.DBTab import DBTab
try: try:
...@@ -38,7 +36,7 @@ class TestDBConfig: ...@@ -38,7 +36,7 @@ class TestDBConfig:
self.mpoints = mpoints self.mpoints = mpoints
def getDB(self): def getDB(self):
from ZODB.config import MappingStorage from ZODB.config import DemoStorage
from ZODB.Connection import Connection from ZODB.Connection import Connection
from Zope.Startup.datatypes import ZopeDatabase from Zope.Startup.datatypes import ZopeDatabase
self.name = self.fname self.name = self.fname
...@@ -52,9 +50,9 @@ class TestDBConfig: ...@@ -52,9 +50,9 @@ class TestDBConfig:
self.version_pool_size = 3 self.version_pool_size = 3
self.version_cache_size = 100 self.version_cache_size = 100
self.mount_points = self.mpoints self.mount_points = self.mpoints
self.connection_class = MountConnection self.connection_class = Connection
self.class_factory = None self.class_factory = None
self.storage = MappingStorage(self) self.storage = DemoStorage(self)
self.container_class = None self.container_class = None
return ZopeDatabase(self) return ZopeDatabase(self)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment