[Zodb-checkins] SVN: ZODB/branches/tim-simpler_connection/src/ZODB/
Added a new _ConnectionPool class, for DB.py.
Tim Peters
tim.one at comcast.net
Mon Oct 25 19:33:08 EDT 2004
Log message for revision 28246:
Added a new _ConnectionPool class, for DB.py.
Also gave WeakSet a suitable __contains__ implementation.
Changed:
U ZODB/branches/tim-simpler_connection/src/ZODB/DB.py
U ZODB/branches/tim-simpler_connection/src/ZODB/utils.py
-=-
Modified: ZODB/branches/tim-simpler_connection/src/ZODB/DB.py
===================================================================
--- ZODB/branches/tim-simpler_connection/src/ZODB/DB.py 2004-10-25 21:48:26 UTC (rev 28245)
+++ ZODB/branches/tim-simpler_connection/src/ZODB/DB.py 2004-10-25 23:33:07 UTC (rev 28246)
@@ -24,6 +24,7 @@
from ZODB.broken import find_global
from ZODB.Connection import Connection
from ZODB.serialize import referencesf
+from ZODB.utils import WeakSet
import transaction
@@ -32,6 +33,89 @@
# A unique marker for detecting use of deprecated arguments.
_deprecated = object()
+
+class _ConnectionPool(object):
+ """Manage a pool of connections.
+
+ CAUTION: All methods should be called under the protection of a lock.
+ This class does no locking of its own.
+
+ There's no limit on the number of connections this can keep track of,
+ but a warning is logged if there are more than pool_size active
+ connections, and a critical problem if more than twice pool_size.
+
+ New connections are registered via push(). This will log a message if
+ "too many" connections are active.
+
+ When a connection is explicitly closed, tell the pool via repush().
+ That adds the connection to a stack of connections available for
+ reuse, and throws away the oldest stack entries if the pool is too large.
+ get() pops this stack.
+
+ If a connection is obtained via get(), the pool holds only a weak
+ reference to it thereafter. It's not necessary to inform the pool
+ if the connection goes away. A connection handed out by get() counts
+ against pool_size only so long as it exists, and provided it isn't
+ repush()'ed.
+ """
+
+ def __init__(self, pool_size):
+ # The largest # of connections we expect to see alive simultaneously.
+ self.pool_size = pool_size
+
+ # A weak set of all connections we've seen. A connection vanishes
+ # from this set if get() hands it out, it's not reregistered via
+ # repush(), and it becomes unreachable.
+ self.all = WeakSet()
+
+ # A stack of connections available to hand out. This is a subset
+ # of self.all. push() and repush() add to this, and may remove
+ # the oldest available connections if the pool is too large.
+ # get() pops this stack.
+ self.available = []
+
+ def set_pool_size(self, pool_size):
+ self.pool_size = pool_size + 1 # _reduce_size shoots for < pool_size
+ self._reduce_size()
+ self.pool_size = pool_size
+
+ # Register a new available connection. We must not know about c already.
+ def push(self, c):
+ assert c not in self.all
+ assert c not in self.available
+ self._reduce_size()
+ self.all.add(c)
+ self.available.append(c)
+ n, limit = len(self.all), self.pool_size
+ if n > limit:
+ reporter = logger.warn
+ if n > 2 * limit:
+ reporter = logger.critical
+ reporter("DB.open() has %s open connections with a pool_size "
+ "of %s", n, limit)
+
+ # Reregister an available connection formerly obtained via get().
+ def repush(self, c):
+ assert c in self.all
+ assert c not in self.available
+ self._reduce_size()
+ self.available.append(c)
+
+ # Prior to pushing a connection onto self.available, throw away the
+ # oldest available connections until we're under our target size.
+ # It may not be possible be achieve this.
+ def _reduce_size(self):
+ while self.available and len(self.all) >= self.pool_size:
+ c = self.available.pop(0)
+ self.all.remove(c)
+
+ def get(self):
+ # Leave it in self.all, so we can still get at it for statistics
+ # while it's alive.
+ return self.available.pop()
+
+
+
class DB(object):
"""The Object Database
-------------------
Modified: ZODB/branches/tim-simpler_connection/src/ZODB/utils.py
===================================================================
--- ZODB/branches/tim-simpler_connection/src/ZODB/utils.py 2004-10-25 21:48:26 UTC (rev 28245)
+++ ZODB/branches/tim-simpler_connection/src/ZODB/utils.py 2004-10-25 23:33:07 UTC (rev 28246)
@@ -190,6 +190,9 @@
def __len__(self):
return len(self.data)
+ def __contains__(self, obj):
+ return id(obj) in self.data
+
# Same as a Set, add obj to the collection.
def add(self, obj):
self.data[id(obj)] = obj
More information about the Zodb-checkins
mailing list