My Object pool isnt working
sam
westernsam at hotmail.com
Fri Apr 4 04:45:17 EST 2003
Hi,
I need to pool some database connections so i thought I'd write a
object pool. I thought I'd use a design I've used in Java before -
having a locked and unlocked hashtable and keeping references of the
connections in two states (i.e. allocated and unallocated). The
problem is that the total number of connections always seems to rise.
Also the total number of connections is less than the sum of the
lengths of the hashtables (dictionaries) which shouldn't happen. I
believe the problems are connected. As I said I've used this design
before in Java and its been fine. The only difference I can think of
(barring shoddy implementation, which I can't rule out) is that
Hashtables in Java are thread safe, but I'm not sure if the built in
dict type in python is.
I've decided to use jonpy's dbpooling module
(http://sourceforge.net/projects/jonpy) instead of writing my own now,
but I'd still like to know whats going on. I have tested on python
1.52 and python 2.2 (both on win2k) and get the same result. All
thoughts appriciated
Regards
Sam Owen
<code>
from Threading import *
import time
import random
import sys
class Object:
def sayHello(self, caller):
print "hello", self, caller
time.sleep(int(random.random() * 5))
class ObjectPool:
LOCKED= {}
UNLOCKED= {}
sema_connect = Semaphore(1)
sema_return = Semaphore(1)
expiretime = 60 #30 mins
totalConns=0
numAllocated = 0
numReturned = 0
def getConnection(self):
try:
self.sema_connect.acquire()
if len(self.UNLOCKED):
for ts in self.UNLOCKED.keys() :
if ts + self.expiretime < time.time():
print "deleting ..."
self.totalConns = self.totalConns-1
del self.UNLOCKED[ts]
else:
print "allocating ..."
self.numAllocated = self.numAllocated+1
o = self.UNLOCKED[ts]
self.LOCKED[o]=1
del self.UNLOCKED[ts]
return o
print "creating ..."
self.numAllocated = self.numAllocated+1
self.totalConns = self.totalConns+1
o = Object()
self.LOCKED[o] = 1
return o
finally:
self.sema_connect.release()
def returnConnection(self, con):
try:
self.sema_return.acquire()
if self.LOCKED.has_key(con):
print "returning"
self.numReturned = self.numReturned +1
self.UNLOCKED[time.time()]=con
del self.LOCKED[con]
return
else:
print con, "was not found in LOCKED ?????"
finally:
self.sema_return.release()
class ObjectUser(Thread):
def __init__(self, pool):
self.pool = pool
Thread.__init__(self)
def run(self):
while 1:
o = pool.getConnection()
o.sayHello(self)
pool.returnConnection(o)
time.sleep(int(random.random() * 5))
if __name__ == '__main__':
pool = ObjectPool()
for i in range(2):
thread = ObjectUser(pool)
thread.start()
while 1:
print "LOCKED --> ", len(pool.LOCKED), "\nUNLOCKED -->",
len(pool.UNLOCKED), "\ntotal conns", pool.totalConns
print "allocates", pool.numAllocated, "\nreturns",
pool.numReturned
time.sleep(5)
</code>
<sample output>
creating ...
LOCKED --> 1
UNLOCKED --> 0
total conns 1
allocates 1
returns 0
creating ...
hello <__main__.Object instance at 8797a8> <ObjectUser(Thread-2,
started)>
hello <__main__.Object instance at 879790> <ObjectUser(Thread-1,
started)>
returning
allocating ...
hello <__main__.Object instance at 879790> <ObjectUser(Thread-1,
started)>
returning
LOCKED --> 1
UNLOCKED --> 1
total conns 2
allocates 3
returns 2
allocating ...
hello <__main__.Object instance at 8797a8> <ObjectUser(Thread-2,
started)>
returning
returning
allocating ...
hello <__main__.Object instance at 8797a8> <ObjectUser(Thread-2,
started)>
returning
allocating ...
hello <__main__.Object instance at 8797a8> <ObjectUser(Thread-2,
started)>
creating ...
hello <__main__.Object instance at 85efe8> <ObjectUser(Thread-1,
started)>
LOCKED --> 2
UNLOCKED --> 0
total conns 3
allocates 7
returns 5
returning
returning
allocating ...
hello <__main__.Object instance at 8797a8> <ObjectUser(Thread-1,
started)>
returning
</sample output>
More information about the Python-list
mailing list