summaryrefslogtreecommitdiffstats
path: root/keystone/common/sql/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone/common/sql/core.py')
-rw-r--r--keystone/common/sql/core.py65
1 files changed, 53 insertions, 12 deletions
diff --git a/keystone/common/sql/core.py b/keystone/common/sql/core.py
index d75c73a8..2d3114f2 100644
--- a/keystone/common/sql/core.py
+++ b/keystone/common/sql/core.py
@@ -32,10 +32,12 @@ from keystone import exception
from keystone.openstack.common import jsonutils
+LOG = logging.getLogger(__name__)
CONF = config.CONF
-# maintain a single engine reference for sqlite in-memory
+# maintain a single engine reference for sqlalchemy engine
GLOBAL_ENGINE = None
+GLOBAL_ENGINE_CALLBACKS = set()
ModelBase = declarative.declarative_base()
@@ -78,13 +80,6 @@ def initialize_decorator(init):
v = str(v)
if column.type.length and \
column.type.length < len(v):
- #if signing.token_format == 'PKI', the id will
- #store it's public key which is very long.
- if config.CONF.signing.token_format == 'PKI' and \
- self.__tablename__ == 'token' and \
- k == 'id':
- continue
-
raise exception.StringLengthExceeded(
string=v, type=k, length=column.type.length)
@@ -95,9 +90,49 @@ ModelBase.__init__ = initialize_decorator(ModelBase.__init__)
def set_global_engine(engine):
+ """Set the global engine.
+
+ This sets the current global engine, which is returned by
+ Base.get_engine(allow_global_engine=True).
+
+ When the global engine is changed, all of the callbacks registered via
+ register_global_engine_callback since the last time set_global_engine was
+ changed are called. The callback functions are invoked with no arguments.
+
+ """
+
global GLOBAL_ENGINE
+ global GLOBAL_ENGINE_CALLBACKS
+
+ if engine is GLOBAL_ENGINE:
+ # It's the same engine so nothing to do.
+ return
+
GLOBAL_ENGINE = engine
+ cbs = GLOBAL_ENGINE_CALLBACKS
+ GLOBAL_ENGINE_CALLBACKS = set()
+ for cb in cbs:
+ try:
+ cb()
+ except Exception:
+ LOG.exception(_("Global engine callback raised."))
+ # Just logging the exception so can process other callbacks.
+
+
+def register_global_engine_callback(cb_fn):
+ """Register a function to be called when the global engine is set.
+
+ Note that the callback will be called only once or not at all, so to get
+ called each time the global engine is changed the function must be
+ re-registered.
+
+ """
+
+ global GLOBAL_ENGINE_CALLBACKS
+
+ GLOBAL_ENGINE_CALLBACKS.add(cb_fn)
+
# Special Fields
class JsonBlob(sql_types.TypeDecorator):
@@ -208,10 +243,12 @@ class Base(object):
def get_session(self, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session."""
- self._engine = self._engine or self.get_engine()
- self._sessionmaker = self._sessionmaker or self.get_sessionmaker(
- self._engine)
- return self._sessionmaker()
+ if not self._engine:
+ self._engine = self.get_engine()
+ self._sessionmaker = self.get_sessionmaker(self._engine)
+ register_global_engine_callback(self.clear_engine)
+ return self._sessionmaker(autocommit=autocommit,
+ expire_on_commit=expire_on_commit)
def get_engine(self, allow_global_engine=True):
"""Return a SQLAlchemy engine.
@@ -264,6 +301,10 @@ class Base(object):
autocommit=autocommit,
expire_on_commit=expire_on_commit)
+ def clear_engine(self):
+ self._engine = None
+ self._sessionmaker = None
+
def handle_conflicts(type='object'):
"""Converts IntegrityError into HTTP 409 Conflict."""