Statistics
| Branch: | Tag: | Revision:

root / snf-common / synnefo / lib / pool / http.py @ c156d23a

History | View | Annotate | Download (2.4 kB)

1

    
2
from synnefo.lib.pool import ObjectPool
3
from select import select
4

    
5
from httplib import (
6
        HTTPConnection  as http_class,
7
        HTTPSConnection as https_class,
8
        HTTPException,
9
        ResponseNotReady
10
)
11

    
12
from urlparse import urlparse
13
from new import instancemethod
14

    
15

    
16
_pools = {}
17
pool_size = 8
18

    
19

    
20
USAGE_LIMIT = 1000
21

    
22

    
23
def init_http_pooling(size):
24
    global pool_size
25
    pool_size = size
26

    
27

    
28
def put_http_connection(conn):
29
    pool = conn._pool
30
    if pool is None:
31
        return
32
    conn._pool = None
33
    pool.pool_put(conn)
34

    
35

    
36
class HTTPConnectionPool(ObjectPool):
37

    
38
    _scheme_to_class = {
39
            'http'  :   http_class,
40
            'https' :   https_class,
41
    }
42

    
43
    def __init__(self, scheme, netloc, size=None):
44
        ObjectPool.__init__(self, size=size)
45

    
46
        connection_class = self._scheme_to_class.get(scheme, None)
47
        if connection_class is None:
48
            m = 'Unsupported scheme: %s' % (scheme,)
49
            raise ValueError(m)
50

    
51
        self.connection_class = connection_class
52
        self.scheme = scheme
53
        self.netloc = netloc
54

    
55
    def _pool_create(self):
56
        conn = self.connection_class(self.netloc)
57
        conn._use_counter = USAGE_LIMIT
58
        conn._pool = self
59
        conn._real_close = conn.close
60
        conn.close = instancemethod(put_http_connection, conn, type(conn))
61
        return conn
62

    
63
    def _pool_verify(self, conn):
64
        if conn is None:
65
            return False
66
        sock = conn.sock
67
        if sock is None:
68
            return True
69
        if select((conn.sock,), (), (), 0)[0]:
70
            return False
71
        return True
72

    
73
    def _pool_cleanup(self, conn):
74
        # every connection can be used a finite number of times
75
        conn._use_counter -= 1
76

    
77
        # see httplib source for connection states documentation
78
        if conn._use_counter > 0 and conn._HTTPConnection__state == 'Idle':
79
            try:
80
                resp = conn.getresponse()
81
            except ResponseNotReady:
82
               return False
83

    
84
        conn._real_close()
85
        return True
86

    
87

    
88
def get_http_connection(netloc=None, scheme='http', pool_size=pool_size):
89
    if netloc is None:
90
        m = "netloc cannot be None"
91
        raise ValueError(m)
92
    # does the pool need to be created?
93
    if netloc not in _pools:
94
        pool = HTTPConnectionPool(scheme, netloc, size=pool_size)
95
        _pools[netloc] = pool
96

    
97
    return _pools[netloc].pool_get()
98