Commit bbd03b3a authored by Adam Groszer's avatar Adam Groszer Committed by Kirill Smelkov

Clean DB properties on close (#123)

( This is ZODB4 backport of upstream commit e9c7492a )

* clean up references to DBs and Connections in pools
* Implement an explicit clear() method for clearing all the items in the pool.

--------

Kirr: with wendelin.core 2 this release of resources becomes important
because if DB.close does not clear connection pools, and something
continues to reference DB object, the connections - that stay referenced
from DB.pool - will be kept alive, and so will be WCFS client connection
associated with those ZODB Connections. As the result, even after proper
zconn.close() and DB.close(), WCFS server stays referenced via files
opened by WCFS client connections, and so cannot be unmounted cleanly.
parent 703f290f
...@@ -104,6 +104,10 @@ class AbstractConnectionPool(object): ...@@ -104,6 +104,10 @@ class AbstractConnectionPool(object):
size = property(getSize, lambda self, v: self.setSize(v)) size = property(getSize, lambda self, v: self.setSize(v))
def clear(self):
pass
class ConnectionPool(AbstractConnectionPool): class ConnectionPool(AbstractConnectionPool):
def __init__(self, size, timeout=1<<31): def __init__(self, size, timeout=1<<31):
...@@ -224,6 +228,11 @@ class ConnectionPool(AbstractConnectionPool): ...@@ -224,6 +228,11 @@ class ConnectionPool(AbstractConnectionPool):
self.available[:] = [i for i in self.available self.available[:] = [i for i in self.available
if i[1] not in to_remove] if i[1] not in to_remove]
def clear(self):
while self.pop():
pass
class KeyedConnectionPool(AbstractConnectionPool): class KeyedConnectionPool(AbstractConnectionPool):
# this pool keeps track of keyed connections all together. It makes # this pool keeps track of keyed connections all together. It makes
# it possible to make assertions about total numbers of keyed connections. # it possible to make assertions about total numbers of keyed connections.
...@@ -279,6 +288,11 @@ class KeyedConnectionPool(AbstractConnectionPool): ...@@ -279,6 +288,11 @@ class KeyedConnectionPool(AbstractConnectionPool):
if not pool.all: if not pool.all:
del self.pools[key] del self.pools[key]
def clear(self):
for pool in self.pools.values():
pool.clear()
self.pools.clear()
@property @property
def test_all(self): def test_all(self):
result = set() result = set()
...@@ -648,6 +662,11 @@ class DB(object): ...@@ -648,6 +662,11 @@ class DB(object):
self.storage.close() self.storage.close()
del self.storage del self.storage
# clean up references to other DBs
self.databases = {}
# clean up the connection pool
self.pool.clear()
self.historical_pool.clear()
def getCacheSize(self): def getCacheSize(self):
return self._cache_size return self._cache_size
......
...@@ -137,7 +137,7 @@ an exception: ...@@ -137,7 +137,7 @@ an exception:
Clean up: Clean up:
>>> for a_db in dbmap.values(): >>> for a_db in list(dbmap.values()):
... a_db.close() ... a_db.close()
......
...@@ -362,6 +362,31 @@ def minimally_test_connection_timeout(): ...@@ -362,6 +362,31 @@ def minimally_test_connection_timeout():
""" """
def cleanup_on_close():
"""Verify that various references are cleared on close
>>> db = ZODB.DB(None)
>>> conn = db.open()
>>> conn.root.x = 'x'
>>> transaction.commit()
>>> conn.close()
>>> historical_conn = db.open(at=db.lastTransaction())
>>> historical_conn.close()
>>> db.close()
>>> db.databases
{}
>>> db.pool.pop() is None
True
>>> [pool is None for pool in db.historical_pool.pools.values()]
[]
"""
def test_suite(): def test_suite():
s = unittest.makeSuite(DBTests) s = unittest.makeSuite(DBTests)
s.addTest(doctest.DocTestSuite( s.addTest(doctest.DocTestSuite(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment