diff options
Diffstat (limited to 'keystone-moon/keystone/common/sql/core.py')
-rw-r--r-- | keystone-moon/keystone/common/sql/core.py | 110 |
1 files changed, 39 insertions, 71 deletions
diff --git a/keystone-moon/keystone/common/sql/core.py b/keystone-moon/keystone/common/sql/core.py index ebd61bb7..cb026356 100644 --- a/keystone-moon/keystone/common/sql/core.py +++ b/keystone-moon/keystone/common/sql/core.py @@ -18,14 +18,13 @@ Before using this module, call initialize(). This has to be done before CONF() because it sets up configuration options. """ -import contextlib import functools from oslo_config import cfg from oslo_db import exception as db_exception from oslo_db import options as db_options +from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import models -from oslo_db.sqlalchemy import session as db_session from oslo_log import log from oslo_serialization import jsonutils import six @@ -34,6 +33,7 @@ from sqlalchemy.ext import declarative from sqlalchemy.orm.attributes import flag_modified, InstrumentedAttribute from sqlalchemy import types as sql_types +from keystone.common import driver_hints from keystone.common import utils from keystone import exception from keystone.i18n import _ @@ -68,7 +68,6 @@ flag_modified = flag_modified def initialize(): """Initialize the module.""" - db_options.set_defaults( CONF, connection="sqlite:///keystone.db") @@ -166,77 +165,47 @@ class ModelDictMixin(object): return {name: getattr(self, name) for name in names} -_engine_facade = None +_main_context_manager = None -def _get_engine_facade(): - global _engine_facade +def _get_main_context_manager(): + global _main_context_manager - if not _engine_facade: - _engine_facade = db_session.EngineFacade.from_config(CONF) + if not _main_context_manager: + _main_context_manager = enginefacade.transaction_context() - return _engine_facade + return _main_context_manager def cleanup(): - global _engine_facade + global _main_context_manager - _engine_facade = None + _main_context_manager = None -def get_engine(): - return _get_engine_facade().get_engine() +_CONTEXT = None -def get_session(expire_on_commit=False): - return _get_engine_facade().get_session(expire_on_commit=expire_on_commit) +def _get_context(): + global _CONTEXT + if _CONTEXT is None: + # NOTE(dims): Delay the `threading.local` import to allow for + # eventlet/gevent monkeypatching to happen + import threading + _CONTEXT = threading.local() + return _CONTEXT -@contextlib.contextmanager -def transaction(expire_on_commit=False): - """Return a SQLAlchemy session in a scoped transaction.""" - session = get_session(expire_on_commit=expire_on_commit) - with session.begin(): - yield session +def session_for_read(): + return _get_main_context_manager().reader.using(_get_context()) -def truncated(f): - """Ensure list truncation is detected in Driver list entity methods. +def session_for_write(): + return _get_main_context_manager().writer.using(_get_context()) - This is designed to wrap and sql Driver list_{entity} methods in order to - calculate if the resultant list has been truncated. Provided a limit dict - is found in the hints list, we increment the limit by one so as to ask the - wrapped function for one more entity than the limit, and then once the list - has been generated, we check to see if the original limit has been - exceeded, in which case we truncate back to that limit and set the - 'truncated' boolean to 'true' in the hints limit dict. - """ - @functools.wraps(f) - def wrapper(self, hints, *args, **kwargs): - if not hasattr(hints, 'limit'): - raise exception.UnexpectedError( - _('Cannot truncate a driver call without hints list as ' - 'first parameter after self ')) - - if hints.limit is None: - return f(self, hints, *args, **kwargs) - - # A limit is set, so ask for one more entry than we need - list_limit = hints.limit['limit'] - hints.set_limit(list_limit + 1) - ref_list = f(self, hints, *args, **kwargs) - - # If we got more than the original limit then trim back the list and - # mark it truncated. In both cases, make sure we set the limit back - # to its original value. - if len(ref_list) > list_limit: - hints.set_limit(list_limit, truncated=True) - return ref_list[:list_limit] - else: - hints.set_limit(list_limit) - return ref_list - return wrapper +def truncated(f): + return driver_hints.truncated(f) class _WontMatch(Exception): @@ -325,42 +294,41 @@ def _filter(model, query, hints): satisfied_filters.append(filter_) return query.filter(query_term) - def exact_filter(model, filter_, cumulative_filter_dict): + def exact_filter(model, query, filter_, satisfied_filters): """Applies an exact filter to a query. :param model: the table model in question + :param query: query to apply filters to :param dict filter_: describes this filter - :param dict cumulative_filter_dict: describes the set of exact filters - built up so far - + :param list satisfied_filters: filter_ will be added if it is + satisfied. + :returns query: query updated to add any exact filters we could + satisfy """ key = filter_['name'] col = getattr(model, key) if isinstance(col.property.columns[0].type, sql.types.Boolean): - cumulative_filter_dict[key] = ( - utils.attr_as_boolean(filter_['value'])) + filter_val = utils.attr_as_boolean(filter_['value']) else: _WontMatch.check(filter_['value'], col) - cumulative_filter_dict[key] = filter_['value'] + filter_val = filter_['value'] + + satisfied_filters.append(filter_) + return query.filter(col == filter_val) try: - filter_dict = {} satisfied_filters = [] for filter_ in hints.filters: if filter_['name'] not in model.attributes: continue if filter_['comparator'] == 'equals': - exact_filter(model, filter_, filter_dict) - satisfied_filters.append(filter_) + query = exact_filter(model, query, filter_, + satisfied_filters) else: query = inexact_filter(model, query, filter_, satisfied_filters) - # Apply any exact filters we built up - if filter_dict: - query = query.filter_by(**filter_dict) - # Remove satisfied filters, then the caller will know remaining filters for filter_ in satisfied_filters: hints.filters.remove(filter_) @@ -377,7 +345,7 @@ def _limit(query, hints): :param query: query to apply filters to :param hints: contains the list of filters and limit details. - :returns updated query + :returns: updated query """ # NOTE(henry-nash): If we were to implement pagination, then we |