On Thu, 2002-05-02 at 15:57, Costas Malamas wrote:
> I remember there was a conversation here about DBPool.py and how it is not 
> really pooling DB Connections.  Has anybody attacked this problem?
> 
> Thanks,
> 

I've got a ConnectionPool class that I wrote.
And your welcome to have a look at it.  It
would be nice if it inherited from Configurable
so that max size would work.  Also right now
it only pools connections to one database.  That
should be easy to change though.

--Karl

> Costas
> 
> 
> 
> _________________________________________________________________
> Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp.
> 
> 
> _______________________________________________________________
> 
> Have big pipes? SourceForge.net is looking for download mirrors. We supply
> the hardware. You get the recognition. Email Us: [EMAIL PROTECTED]
> _______________________________________________
> Webware-discuss mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/webware-discuss

#!/usr/bin/env python

import threading
import Queue
import psycopg
import time

GET_TIMEOUT = 10 # roughly seconds
GET_WAIT_INTERVAL = .005 # roughly seconds

class ConnectionPool:
    busy_connections = None
    connections = None
    lock = threading.Lock()
    def __init__(self, MAX_CONNECTIONS=5):
        ConnectionPool.lock.acquire()
        if ConnectionPool.connections == None:
            ConnectionPool.connections = Queue.Queue(MAX_CONNECTIONS)
            ConnectionPool.busy_connections = []
            for i in range(MAX_CONNECTIONS):
                ConnectionPool.connections.put(psycopg.connect('host=localhost dbname=shipeze'))
        ConnectionPool.lock.release()

    def get(self):
        timeout = 0
        while timeout < GET_TIMEOUT:
            try:
                conn = ConnectionPool.connections.get_nowait() # throws QEE
                bconns = ConnectionPool.busy_connections
                lock = ConnectionPool.lock
                try:
                    lock.acquire()
                    if conn in bconns:
                        raise ConnectionPoolInternalError('%s already allocated' % str(conn))
                    else:
                        bconns.append(conn)
                    return conn
                finally:
                    if lock.locked(): lock.release()
            except Queue.Empty:
                timeout += GET_WAIT_INTERVAL
                print 'Waiting for connection for %f seconds' % timeout
                time.sleep(GET_WAIT_INTERVAL)
        # got here so we timed out on the connection
        raise ConnectionPoolTimeout()

    def put(self, conn):
        lock = ConnectionPool.lock
        bconns = ConnectionPool.busy_connections
        try:
            lock.acquire()
            while conn in bconns:
                bconns.remove(conn)
            lock.release()
            try:
                ConnectionPool.connections.put_nowait(conn) # throws QFE
            except Queue.Full:
                raise ConnectionPoolInternalError('Too many connection in pool: %s' % str(conn))
        finally:
            if lock.locked(): lock.release()



class ConnectionPoolTimeout(Exception): pass
class ConnectionPoolInternalError(Exception): 
    def __init__(self, message='Unknown Internal Error'):
        self.message = message
    def __str__(self):
        return self.message
        

Reply via email to