[Zope-Checkins] CVS: Zope/lib/python/DBTab - CHANGES.txt:1.1 ClassFactories.py:1.1 DBTab.py:1.1 Exceptions.py:1.1 __init__.py:1.1

Chris McDonough chrism@zope.com
Sat, 19 Jul 2003 22:56:05 -0400


Update of /cvs-repository/Zope/lib/python/DBTab
In directory cvs.zope.org:/tmp/cvs-serv5583/lib/python/DBTab

Added Files:
	CHANGES.txt ClassFactories.py DBTab.py Exceptions.py 
	__init__.py 
Log Message:
Integrate DBTab into HEAD.

DBTab now obtains all values related to storages and databases from zope.conf.  It is also now just a package rather than a product.

A new product named ZODBMountPoint exposes the mount point functionality to the ZMI.


=== Added File Zope/lib/python/DBTab/CHANGES.txt ===
HEAD

  - Merged into Zope 2.7+.  Split into two pieces: the ZODBMountPoint
    Product and the DBTab package.  Neither custom_zodb.py nor dbtab.conf
    is now required (all configuration is performed via zope.conf).

Version 1.2.1

  - Began unit tests.

  - Fixed a race condition on connection close.  The symptom was
    spurious "Should not load state when connection closed" errors under
    high load.

  - DemoStorage configurations can now include a base_type option,
    taking advantage of DemoStorage's layering feature.

  - The mount status page (visible by selecting "Add DBTab Mount Point")
    sometimes indicated there were objects mounted that really were not.
    Fixed.


Version 1.2

  - Fixed activity monitoring for mounted databases.

  - Removed import of AdaptableStorage.  Argument converters now work
    when you specify the full module of a storage class.

  - You can now specify a container_class to generate folderish
    objects other than standard folders when mounting a new database.
    See dbtab.conf.in.


Version 1.1

  - Changed DBTab's mounting strategy so that mounted connections stay
    bound to a root connection.  This change is designed to:

    - eliminate issues with volatile attributes in application code
      that cross mount boundaries.  Now it's safe to use cross-database
      volatile attributes.

    - eliminate the global registry of open connections, which seemed
      to have a rare race condition (ugh!)

    - go faster. :-) The mount point traversal penalty is much lower
      now, since the mount point can keep a long-lived reference to the
      mounted object.


Version 1.0.2

- Updated to work with the latest BDBStorage and AdaptableStorage.


Version 1.0.1

- Deferred startup until after MainConfiguration has been imported.
  Needed for ZRS.

- Added AdaptableStorage and BerkeleyStorage to the list of
  easily-configured storage types.

- Fixed bug reported by Robert Boulanger:

    If the Storage/Databasename is the same like the mountpath it is
    not possible to access the database management screens in the
    Control Panel. Instead getting Admin screens for Cache and
    Activity you will be redirected to the manage workspace of the
    folder.

- Arranged for Zope to properly close open database connections on
  clean shutdown.



=== Added File Zope/lib/python/DBTab/ClassFactories.py ===
##############################################################################
#
# 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
#
##############################################################################
"""Available ZODB class factories.

$Id: ClassFactories.py,v 1.1 2003/07/20 02:55:58 chrism Exp $"""

import OFS.Uninstalled


class_factories = {}

def minimalClassFactory(jar, module, name,
                        _silly=('__doc__',), _globals={},
                        ):
    """Minimal class factory.

    If any class is not found, this class factory will propagate
    the exception to the application, unlike the other class factories.
    """
    m = __import__(module, _globals, _globals, _silly)
    return getattr(m, name)

class_factories['minimal'] = minimalClassFactory



def simpleClassFactory(jar, module, name,
                       _silly=('__doc__',), _globals={},
                       ):
    """Class factory without ZClass support.
    """
    try:
        m = __import__(module, _globals, _globals, _silly)
        return getattr(m, name)
    except:
        return OFS.Uninstalled.Broken(jar, None, (module, name))

class_factories['simple'] = simpleClassFactory



def zopeClassFactory(jar, module, name,
                     _silly=('__doc__',), _globals={},
                     ):
    """Class factory with ZClass support.
    """
    try:
        if module[:1]=='*':
            # ZCLass! Yee ha!
            return jar.root()['ZGlobals'][module]
        else:
            m=__import__(module, _globals, _globals, _silly)

        return getattr(m, name)
    except:
        return OFS.Uninstalled.Broken(jar, None, (module, name))

class_factories['zope'] = zopeClassFactory



def autoClassFactory(jar, module, name):
    """Class factory with ZClasses and support for central class definitions.
    """
    # If not the root connection, use the class factory from
    # the root database, otherwise use the Zope class factory.
    root_conn = getattr(jar, '_root_connection', None)
    root_db = getattr(root_conn, '_db', None)
    if root_db is not None:
        return root_db._classFactory(root_conn, module, name)
    else:
        return zopeClassFactory(jar, module, name)

class_factories['auto'] = autoClassFactory



=== Added File Zope/lib/python/DBTab/DBTab.py ===
##############################################################################
#
# Copyright (c) 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
# 
##############################################################################
"""DBTab and DatabaseFactory classes.

$Id: DBTab.py,v 1.1 2003/07/20 02:55:58 chrism Exp $
"""

import sys
from thread import allocate_lock

from ZODB.ActivityMonitor import ActivityMonitor
import Globals

from Exceptions import DBTabConfigurationError


class DBTab:
    """A Zope database configuration, similar in purpose to /etc/fstab.
    """

    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 }

    def startup(self):
        """Opens the databases set to open_at_startup."""
        if self._started:
            return
        self._started = 1
        for name, factory in self.db_factories.items():
            if factory.getOpenAtStartup():
                self.getDatabase(name=name)

    def listMountPaths(self):
        """Returns a sequence of (virtual_mount_path, database_name).
        """
        return self.mount_paths.items()


    def listDatabaseNames(self):
        """Returns a sequence of names.
        """
        return self.db_factories.keys()


    def hasDatabase(self, name):
        """Returns true if name is the name of a configured database."""
        return self.db_factories.has_key(name)


    def _mountPathError(self, mount_path):
        if mount_path == '/':
            raise DBTabConfigurationError(
                "No root database configured")
        else:
            raise DBTabConfigurationError(
                "No database configured for mount point at %s"
                % mount_path)


    def getDatabase(self, mount_path=None, name=None, is_root=0):
        """Returns an opened database.  Requires either mount_path or name.
        """
        self.startup()
        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)
        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()
        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)
        return self.db_factories[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



=== Added File Zope/lib/python/DBTab/Exceptions.py ===
##############################################################################
#
# Copyright (c) 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
# 
##############################################################################
"""DBTab exception classes.

$Id: Exceptions.py,v 1.1 2003/07/20 02:55:58 chrism Exp $
"""


class DBTabConfigurationError (Exception):
    """Error in dbtab configuration"""
    args = ()

class DBTabOverrideError (Exception):
    """DBTab has taken over some piece of functionality"""
    args = ()



=== Added File Zope/lib/python/DBTab/__init__.py ===
##############################################################################
#
# Copyright (c) 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
# 
##############################################################################
"""DBTab product.

$Id: __init__.py,v 1.1 2003/07/20 02:55:58 chrism Exp $
"""

# importing ThreadedAsync has the side effect of patching asyncore so
# that loop callbacks get invoked.  You need this to
# mount a ZEO client connection if the main database is not a ZEO client.
# Otherwise ZEO never receives the message telling it to start using the
# main async loop.
import ThreadedAsync