[IMP] sql_db.py: backport changes from stable branch

bzr revid: chs@openerp.com-20100514131506-yx7qsu2nuylk1v5e
This commit is contained in:
Christophe Simonis 2010-05-14 15:15:06 +02:00
parent 441d653c59
commit b3f8f4313b
1 changed files with 30 additions and 14 deletions

View File

@ -100,7 +100,7 @@ class Cursor(object):
msg = "Cursor not closed explicitly\n" \
"Cursor was created at %s:%s"
self.__logger.warn(msg, *self.__caller)
self.close()
self._close(True)
@check
def execute(self, query, params=None):
@ -177,6 +177,9 @@ class Cursor(object):
@check
def close(self):
return self._close(False)
def _close(self, leak=False):
if not self._obj:
return
@ -194,7 +197,12 @@ class Cursor(object):
# part because browse records keep a reference to the cursor.
del self._obj
self.__closed = True
self._pool.give_back(self._cnx)
if leak:
self._cnx.leaked = True
else:
keep_in_pool = self.dbname not in ('template1', 'template0', 'postgres')
self._pool.give_back(self._cnx, keep_in_pool=keep_in_pool)
@check
def autocommit(self, on):
@ -214,6 +222,9 @@ class Cursor(object):
return getattr(self._obj, name)
class PsycoConnection(psycopg2.extensions.connection):
pass
class ConnectionPool(object):
__logger = logging.getLogger('db.connection_pool')
@ -247,42 +258,47 @@ class ConnectionPool(object):
def borrow(self, dsn):
self._debug('Borrow connection to %s' % (dsn,))
result = None
# free leaked connections
for i, (cnx, _) in tools.reverse_enumerate(self._connections):
if getattr(cnx, 'leaked', False):
delattr(cnx, 'leaked')
self._connections.pop(i)
self._connections.append((cnx, False))
self._debug('Free leaked connection to %s' % (cnx.dsn,))
for i, (cnx, used) in enumerate(self._connections):
if not used and dsn_are_equals(cnx.dsn, dsn):
self._debug('Existing connection found at index %d' % i)
self._connections.pop(i)
self._connections.append((cnx, True))
self._debug('Existing connection found at index %d' % i)
result = cnx
break
if result:
return result
return cnx
if len(self._connections) >= self._maxconn:
# try to remove the oldest connection not used
for i, (cnx, used) in enumerate(self._connections):
if not used:
self._debug('Removing old connection at index %d: %s' % (i, cnx.dsn))
self._connections.pop(i)
self._debug('Removing old connection at index %d: %s' % (i, cnx.dsn))
break
else:
# note: this code is called only if the for loop has completed (no break)
raise PoolError('The Connection Pool Is Full')
self._debug('Create new connection')
result = psycopg2.connect(dsn=dsn)
result = psycopg2.connect(dsn=dsn, connection_factory=PsycoConnection)
self._connections.append((result, True))
self._debug('Create new connection')
return result
@locked
def give_back(self, connection):
def give_back(self, connection, keep_in_pool=True):
self._debug('Give back connection to %s' % (connection.dsn,))
for i, (cnx, used) in enumerate(self._connections):
if cnx is connection:
self._connections.pop(i)
self._connections.append((cnx, False))
if keep_in_pool:
self._connections.append((cnx, False))
self._debug('Put connection to %s in pool' % (cnx.dsn,))
break
else:
raise PoolError('This connection does not below to the pool')