diff options
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/db/enginestrategy.py')
-rw-r--r-- | lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/db/enginestrategy.py | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/db/enginestrategy.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/db/enginestrategy.py deleted file mode 100644 index 2be80f9a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/db/enginestrategy.py +++ /dev/null @@ -1,206 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -""" -A wrapper around `sqlalchemy.create_engine` that handles all of the -special cases that Buildbot needs. Those include: - - - pool_recycle for MySQL - - %(basedir) substitution - - optimal thread pool size calculation - -""" - -import os -import sqlalchemy as sa -from twisted.python import log -from sqlalchemy.engine import strategies, url -from sqlalchemy.pool import NullPool -from buildbot.util import sautils - -# from http://www.mail-archive.com/sqlalchemy@googlegroups.com/msg15079.html -class ReconnectingListener(object): - def __init__(self): - self.retried = False - -class BuildbotEngineStrategy(strategies.ThreadLocalEngineStrategy): - # A subclass of the ThreadLocalEngineStrategy that can effectively interact - # with Buildbot. - # - # This adjusts the passed-in parameters to ensure that we get the behaviors - # Buildbot wants from particular drivers, and wraps the outgoing Engine - # object so that its methods run in threads and return deferreds. - - name = 'buildbot' - - def special_case_sqlite(self, u, kwargs): - """For sqlite, percent-substitute %(basedir)s and use a full - path to the basedir. If using a memory database, force the - pool size to be 1.""" - max_conns = None - - # when given a database path, stick the basedir in there - if u.database: - - # Use NullPool instead of the sqlalchemy-0.6.8-default - # SingletonThreadpool for sqlite to suppress the error in - # http://groups.google.com/group/sqlalchemy/msg/f8482e4721a89589, - # which also explains that NullPool is the new default in - # sqlalchemy 0.7 for non-memory SQLite databases. - kwargs.setdefault('poolclass', NullPool) - - u.database = u.database % dict(basedir = kwargs['basedir']) - if not os.path.isabs(u.database[0]): - u.database = os.path.join(kwargs['basedir'], u.database) - - # in-memory databases need exactly one connection - if not u.database: - kwargs['pool_size'] = 1 - max_conns = 1 - - # allow serializing access to the db - if 'serialize_access' in u.query: - u.query.pop('serialize_access') - max_conns = 1 - - return u, kwargs, max_conns - - def set_up_sqlite_engine(self, u, engine): - """Special setup for sqlite engines""" - # try to enable WAL logging - if u.database: - def connect_listener(connection, record): - connection.execute("pragma checkpoint_fullfsync = off") - - if sautils.sa_version() < (0,7,0): - class CheckpointFullfsyncDisabler(object): - pass - disabler = CheckpointFullfsyncDisabler() - disabler.connect = connect_listener - engine.pool.add_listener(disabler) - else: - sa.event.listen(engine.pool, 'connect', connect_listener) - - log.msg("setting database journal mode to 'wal'") - try: - engine.execute("pragma journal_mode = wal") - except: - log.msg("failed to set journal mode - database may fail") - - def special_case_mysql(self, u, kwargs): - """For mysql, take max_idle out of the query arguments, and - use its value for pool_recycle. Also, force use_unicode and - charset to be True and 'utf8', failing if they were set to - anything else.""" - - kwargs['pool_recycle'] = int(u.query.pop('max_idle', 3600)) - - # default to the InnoDB storage engine - storage_engine = u.query.pop('storage_engine', 'MyISAM') - kwargs['connect_args'] = { - 'init_command' : 'SET storage_engine=%s' % storage_engine, - } - - if 'use_unicode' in u.query: - if u.query['use_unicode'] != "True": - raise TypeError("Buildbot requires use_unicode=True " + - "(and adds it automatically)") - else: - u.query['use_unicode'] = True - - if 'charset' in u.query: - if u.query['charset'] != "utf8": - raise TypeError("Buildbot requires charset=utf8 " + - "(and adds it automatically)") - else: - u.query['charset'] = 'utf8' - - return u, kwargs, None - - def set_up_mysql_engine(self, u, engine): - """Special setup for mysql engines""" - # add the reconnecting PoolListener that will detect a - # disconnected connection and automatically start a new - # one. This provides a measure of additional safety over - # the pool_recycle parameter, and is useful when e.g., the - # mysql server goes away - def checkout_listener(dbapi_con, con_record, con_proxy): - try: - cursor = dbapi_con.cursor() - cursor.execute("SELECT 1") - except dbapi_con.OperationalError, ex: - if ex.args[0] in (2006, 2013, 2014, 2045, 2055): - # sqlalchemy will re-create the connection - raise sa.exc.DisconnectionError() - raise - - # older versions of sqlalchemy require the listener to be specified - # in the kwargs, in a class instance - if sautils.sa_version() < (0,7,0): - class ReconnectingListener(object): - pass - rcl = ReconnectingListener() - rcl.checkout = checkout_listener - engine.pool.add_listener(rcl) - else: - sa.event.listen(engine.pool, 'checkout', checkout_listener) - - def create(self, name_or_url, **kwargs): - if 'basedir' not in kwargs: - raise TypeError('no basedir supplied to create_engine') - - max_conns = None - - # apply special cases - u = url.make_url(name_or_url) - if u.drivername.startswith('sqlite'): - u, kwargs, max_conns = self.special_case_sqlite(u, kwargs) - elif u.drivername.startswith('mysql'): - u, kwargs, max_conns = self.special_case_mysql(u, kwargs) - - # remove the basedir as it may confuse sqlalchemy - basedir = kwargs.pop('basedir') - - # calculate the maximum number of connections from the pool parameters, - # if it hasn't already been specified - if max_conns is None: - max_conns = kwargs.get('pool_size', 5) + kwargs.get('max_overflow', 10) - - engine = strategies.ThreadLocalEngineStrategy.create(self, - u, **kwargs) - - # annotate the engine with the optimal thread pool size; this is used - # by DBConnector to configure the surrounding thread pool - engine.optimal_thread_pool_size = max_conns - - # keep the basedir - engine.buildbot_basedir = basedir - - if u.drivername.startswith('sqlite'): - self.set_up_sqlite_engine(u, engine) - elif u.drivername.startswith('mysql'): - self.set_up_mysql_engine(u, engine) - - return engine - -BuildbotEngineStrategy() - -# this module is really imported for the side-effects, but pyflakes will like -# us to use something from the module -- so offer a copy of create_engine, -# which explicitly adds the strategy argument -def create_engine(*args, **kwargs): - kwargs['strategy'] = 'buildbot' - - return sa.create_engine(*args, **kwargs) |