summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-08-01 23:57:30 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-08-01 23:57:30 +0000
commita3efe722d916d66e3125ee20ad77117a1bf262f8 (patch)
tree696fdd3ad1964c5f78360a8e28997ef335694194
parent16b0c038a17c88859fe65aa384163f38db314e17 (diff)
downloadsqlalchemy-a3efe722d916d66e3125ee20ad77117a1bf262f8.tar.gz
- fixed another occasional race condition which could occur
when using pool with threadlocal setting
-rw-r--r--CHANGES3
-rw-r--r--lib/sqlalchemy/pool.py18
-rw-r--r--test/engine/pool.py15
3 files changed, 20 insertions, 16 deletions
diff --git a/CHANGES b/CHANGES
index 9d75e2dfb..43b8213db 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,9 @@
- added a check for joining from A->B using join(), along two
different m2m tables. this raises an error in 0.3 but is
possible in 0.4 when aliases are used. [ticket:687]
+- engine
+ - fixed another occasional race condition which could occur
+ when using pool with threadlocal setting
- mssql
- added support for TIME columns (simulated using DATETIME) [ticket:679]
- index names are now quoted when dropping from reflected tables [ticket:684]
diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py
index 8670464a0..bb6997e90 100644
--- a/lib/sqlalchemy/pool.py
+++ b/lib/sqlalchemy/pool.py
@@ -162,13 +162,15 @@ class Pool(object):
return _ConnectionFairy(self).checkout()
try:
- return self._threadconns[thread.get_ident()].connfairy().checkout()
+ return self._threadconns[thread.get_ident()].checkout()
except KeyError:
- agent = _ConnectionFairy(self).checkout()
- self._threadconns[thread.get_ident()] = agent._threadfairy
- return agent
+ agent = _ConnectionFairy(self)
+ self._threadconns[thread.get_ident()] = agent
+ return agent.checkout()
def return_conn(self, agent):
+ if self._use_threadlocal and thread.get_ident() in self._threadconns:
+ del self._threadconns[thread.get_ident()]
self.do_return_conn(agent._connection_record)
def get(self):
@@ -230,17 +232,10 @@ class _ConnectionRecord(object):
self.__pool.log("Error on connect(): %s" % (str(e)))
raise
-class _ThreadFairy(object):
- """Mark a thread identifier as owning a connection, for a thread local pool."""
-
- def __init__(self, connfairy):
- self.connfairy = weakref.ref(connfairy)
-
class _ConnectionFairy(object):
"""Proxy a DBAPI connection object and provides return-on-dereference support."""
def __init__(self, pool):
- self._threadfairy = _ThreadFairy(self)
self._cursors = weakref.WeakKeyDictionary()
self._pool = pool
self.__counter = 0
@@ -340,7 +335,6 @@ class _ConnectionFairy(object):
self._pool.return_conn(self)
self.connection = None
self._connection_record = None
- self._threadfairy = None
self._cursors = None
class _CursorFairy(object):
diff --git a/test/engine/pool.py b/test/engine/pool.py
index 85e9d59fd..023ab70b7 100644
--- a/test/engine/pool.py
+++ b/test/engine/pool.py
@@ -1,6 +1,6 @@
import testbase
from testbase import PersistTest
-import unittest, sys, os, time
+import unittest, sys, os, time, gc
import threading, thread
import sqlalchemy.pool as pool
@@ -300,7 +300,14 @@ class PoolTest(PersistTest):
assert not con.closed
c1.close()
assert con.closed
-
+
+ def test_threadfairy(self):
+ p = pool.QueuePool(creator = lambda: mock_dbapi.connect('foo.db'), pool_size = 3, max_overflow = -1, use_threadlocal = True)
+ c1 = p.connect()
+ c1.close()
+ c2 = p.connect()
+ assert c2.connection is not None
+
def testthreadlocal_del(self):
self._do_testthreadlocal(useclose=False)
@@ -328,7 +335,7 @@ class PoolTest(PersistTest):
c2.close()
else:
c2 = None
-
+
if useclose:
c1 = p.connect()
c2 = p.connect()
@@ -340,7 +347,7 @@ class PoolTest(PersistTest):
c1 = c2 = c3 = None
- # extra tests with QueuePool to insure connections get __del__()ed when dereferenced
+ # extra tests with QueuePool to ensure connections get __del__()ed when dereferenced
if isinstance(p, pool.QueuePool):
self.assert_(p.checkedout() == 0)
c1 = p.connect()