[Checkins] SVN: z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/ - changed
the caching of the connection and session object for Zope wrapper
Andreas Jung
andreas at andreas-jung.com
Tue May 1 05:54:46 EDT 2007
Log message for revision 74956:
- changed the caching of the connection and session object for Zope wrapper
since the id of a transaction is not reliable (different transaction
object can re-use the same memory address leading to cache errors)
Changed:
U z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/CHANGES.txt
U z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/base.py
-=-
Modified: z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/CHANGES.txt
===================================================================
--- z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/CHANGES.txt 2007-05-01 09:01:30 UTC (rev 74955)
+++ z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/CHANGES.txt 2007-05-01 09:54:45 UTC (rev 74956)
@@ -3,6 +3,16 @@
- added check for the 'mapper_class' attribute (classes from now
on must be a subclass of MapperClassBase)
+ - a Zope-aware SAWrapper now has a 'connection' property that can
+ be used to execute SQL statements directly. 'connection' is an
+ instance of sqlalchemy.Connection and directly tied to the current
+ Zope transaction.
+
+ - changed the caching of the connection and session object for Zope wrapper
+ since the id of a transaction is not reliable (different transaction
+ object can re-use the same memory address leading to cache errors)
+
+
0.1.10 (30.04.2007)
- fixed a bug in mapper (unfortunately I forgot to commit a
Modified: z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/base.py
===================================================================
--- z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/base.py 2007-05-01 09:01:30 UTC (rev 74955)
+++ z3c.sqlalchemy/trunk/src/z3c/sqlalchemy/base.py 2007-05-01 09:54:45 UTC (rev 74956)
@@ -23,6 +23,30 @@
from transaction.interfaces import IDataManager
+class SynchronizedThreadCache(object):
+
+ def __init__(self):
+ self.lock = threading.Lock()
+ self.cache = threading.local()
+
+
+ def set(self, **kw):
+
+ self.lock.acquire()
+ for k,v in kw.items():
+ setattr(self.cache, k, v)
+ self.lock.release()
+
+
+ def get(self, *names):
+ self.lock.acquire()
+ lst = []
+ for name in names:
+ lst.append(getattr(self.cache, name, None))
+ self.lock.release()
+ return lst
+
+
class BaseWrapper(object):
implements(ISQLAlchemyWrapper)
@@ -113,8 +137,8 @@
def _createEngine(self):
return sqlalchemy.create_engine(self.dsn, **self.kw)
-_session_cache = threading.local() # module-level cache
-_connection_cache = threading.local() # module-level cache
+session_cache = SynchronizedThreadCache()
+connection_cache = SynchronizedThreadCache()
class SessionDataManager(object):
@@ -131,10 +155,12 @@
def abort(self, trans):
self.transaction.rollback()
+ session_cache.set(last_session=None, last_transaction=None)
def commit(self, trans):
self.session.flush()
self.transaction.commit()
+ session_cache.set(last_session=None, last_transaction=None)
def tpc_vote(self, trans):
pass
@@ -165,11 +191,13 @@
self.transaction.rollback()
self.connection.close()
self.connection = None
+ connection_cache.set(last_connection=None, last_transaction=None)
def commit(self, trans):
self.transaction.commit()
self.connection.close()
self.connection = None
+ connection_cache.set(last_connection=None, last_transaction=None)
def tpc_vote(self, trans):
pass
@@ -192,28 +220,21 @@
@property
def session(self):
- if not hasattr(_session_cache, 'last_transaction'):
- _session_cache.last_transaction = None
- _session_cache.last_session = None
+ last_session, = connection_cache.get('last_session')
- # get current transaction
- txn = transaction.get()
- txn_str = str(txn)
-
# return cached session if we are within the same transaction
# and same thread
- if txn_str == _session_cache.last_transaction:
- return _session_cache.last_session
+ if last_session is not None:
+ return last_session
# no cached session, let's create a new one
session = sqlalchemy.create_session(self._engine)
# register a DataManager with the current transaction
- txn.join(SessionDataManager(session))
+ transaction.get().join(SessionDataManager(session))
# update thread-local cache
- _session_cache.last_transaction = txn_str
- _session_cache.last_session = session
+ session_cache.set(last_session=session)
# return the session
return session
@@ -221,28 +242,21 @@
@property
def connection(self):
- if not hasattr(_connection_cache, 'last_connection'):
- _connection_cache.last_transaction = None
- _connection_cache.last_connection = None
+ last_connection, = connection_cache.get('last_connection')
- # get current transaction
- txn = transaction.get()
- txn_str = str(txn)
-
# return cached connection if we are within the same transaction
# and same thread
- if txn_str == _connection_cache.last_transaction:
- return _connection_cache.last_connection
+ if last_connection is not None:
+ return last_connection
# no cached connection, let's create a new one
connection = self.engine.connect()
# register a DataManager with the current transaction
- txn.join(ConnectionDataManager(connection))
+ transaction.get().join(ConnectionDataManager(connection))
# update thread-local cache
- _connection_cache.last_transaction = txn_str
- _connection_cache.last_connection = connection
+ connection_cache.set(last_connection=connection)
# return the connection
return connection
More information about the Checkins
mailing list