[IMP] sql_db.py: backport changes from stable branch
bzr revid: chs@openerp.com-20100514131506-yx7qsu2nuylk1v5e
This commit is contained in:
parent
441d653c59
commit
b3f8f4313b
|
@ -100,7 +100,7 @@ class Cursor(object):
|
||||||
msg = "Cursor not closed explicitly\n" \
|
msg = "Cursor not closed explicitly\n" \
|
||||||
"Cursor was created at %s:%s"
|
"Cursor was created at %s:%s"
|
||||||
self.__logger.warn(msg, *self.__caller)
|
self.__logger.warn(msg, *self.__caller)
|
||||||
self.close()
|
self._close(True)
|
||||||
|
|
||||||
@check
|
@check
|
||||||
def execute(self, query, params=None):
|
def execute(self, query, params=None):
|
||||||
|
@ -177,6 +177,9 @@ class Cursor(object):
|
||||||
|
|
||||||
@check
|
@check
|
||||||
def close(self):
|
def close(self):
|
||||||
|
return self._close(False)
|
||||||
|
|
||||||
|
def _close(self, leak=False):
|
||||||
if not self._obj:
|
if not self._obj:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -194,7 +197,12 @@ class Cursor(object):
|
||||||
# part because browse records keep a reference to the cursor.
|
# part because browse records keep a reference to the cursor.
|
||||||
del self._obj
|
del self._obj
|
||||||
self.__closed = True
|
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
|
@check
|
||||||
def autocommit(self, on):
|
def autocommit(self, on):
|
||||||
|
@ -214,6 +222,9 @@ class Cursor(object):
|
||||||
return getattr(self._obj, name)
|
return getattr(self._obj, name)
|
||||||
|
|
||||||
|
|
||||||
|
class PsycoConnection(psycopg2.extensions.connection):
|
||||||
|
pass
|
||||||
|
|
||||||
class ConnectionPool(object):
|
class ConnectionPool(object):
|
||||||
|
|
||||||
__logger = logging.getLogger('db.connection_pool')
|
__logger = logging.getLogger('db.connection_pool')
|
||||||
|
@ -247,42 +258,47 @@ class ConnectionPool(object):
|
||||||
def borrow(self, dsn):
|
def borrow(self, dsn):
|
||||||
self._debug('Borrow connection to %s' % (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):
|
for i, (cnx, used) in enumerate(self._connections):
|
||||||
if not used and dsn_are_equals(cnx.dsn, dsn):
|
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.pop(i)
|
||||||
self._connections.append((cnx, True))
|
self._connections.append((cnx, True))
|
||||||
|
self._debug('Existing connection found at index %d' % i)
|
||||||
|
|
||||||
result = cnx
|
return cnx
|
||||||
break
|
|
||||||
if result:
|
|
||||||
return result
|
|
||||||
|
|
||||||
if len(self._connections) >= self._maxconn:
|
if len(self._connections) >= self._maxconn:
|
||||||
# try to remove the oldest connection not used
|
# try to remove the oldest connection not used
|
||||||
for i, (cnx, used) in enumerate(self._connections):
|
for i, (cnx, used) in enumerate(self._connections):
|
||||||
if not used:
|
if not used:
|
||||||
self._debug('Removing old connection at index %d: %s' % (i, cnx.dsn))
|
|
||||||
self._connections.pop(i)
|
self._connections.pop(i)
|
||||||
|
self._debug('Removing old connection at index %d: %s' % (i, cnx.dsn))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# note: this code is called only if the for loop has completed (no break)
|
# note: this code is called only if the for loop has completed (no break)
|
||||||
raise PoolError('The Connection Pool Is Full')
|
raise PoolError('The Connection Pool Is Full')
|
||||||
|
|
||||||
self._debug('Create new connection')
|
result = psycopg2.connect(dsn=dsn, connection_factory=PsycoConnection)
|
||||||
result = psycopg2.connect(dsn=dsn)
|
|
||||||
self._connections.append((result, True))
|
self._connections.append((result, True))
|
||||||
|
self._debug('Create new connection')
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@locked
|
@locked
|
||||||
def give_back(self, connection):
|
def give_back(self, connection, keep_in_pool=True):
|
||||||
self._debug('Give back connection to %s' % (connection.dsn,))
|
self._debug('Give back connection to %s' % (connection.dsn,))
|
||||||
for i, (cnx, used) in enumerate(self._connections):
|
for i, (cnx, used) in enumerate(self._connections):
|
||||||
if cnx is connection:
|
if cnx is connection:
|
||||||
self._connections.pop(i)
|
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
|
break
|
||||||
else:
|
else:
|
||||||
raise PoolError('This connection does not below to the pool')
|
raise PoolError('This connection does not below to the pool')
|
||||||
|
|
Loading…
Reference in New Issue