1
2
3
4
5
6 from __future__ import with_statement
7
8 import collections
9 import eventlet
10 from eventlet import queue
11 from eventlet.timeout import Timeout
12
13 from restkit.pool import PoolInterface
14 from restkit import sock
15
17
19 self._addr = address
20 self.pool = queue.LightQueue(0)
21 self.free_connections = collections.deque()
22 self.nb_connections = 0
23
25 return max(0, self.pool.getting() - self.pool.putting())
26
28 """
29 Eventlet pool to manage connections. after a specific timeout the
30 sockets are closes. Default timeout is 300s.
31
32 To use restkit with eventlet::
33
34 >>> import eventlet
35 >>> eventlet.monkey_patch(all=False, socket=True)
36 >>> from restkit import request
37 >>> from restkit.ext.eventlet_pool import EventletPool
38 >>> pool = EventletPool(max_connections=5)
39 >>> r = request('http://friendpaste.com', pool_instance=pool)
40
41 """
42
43 - def __init__(self, max_connections=4, timeout=300):
44 """ Initialize EventletPool
45
46 :param max_connexions: int, number max of connections in the pool.
47 Default is 4
48 :param timeout: int, number max of second a connection is kept alive.
49 Default is 300s.
50 """
51 self.max_connections = max_connections
52 self.timeout = 60
53 self.hosts = {}
54 self.sockets = {}
55
56 - def get(self, address):
57 """ Get connection for (Host, Port) address
58 :param address: tuple (Host, address)
59 """
60
61 host = self.hosts.get(address)
62 if not host:
63 return None
64 if host.free_connections:
65 socket = host.free_connections.popleft()
66 eventlet.spawn(self._remove_socket, socket)
67 return socket
68 if host.nb_connections < self.max_connections:
69 host.nb_connections += 1
70 return None
71 socket = host.pool.get()
72 eventlet.spawn(self._remove_socket, socket)
73 return socket
74
76 """ function used to monitor the socket """
77 with Timeout(self.timeout, False):
78 if fn in self.sockets:
79 socket = self.sockets[fn]
80 sock.close(socket)
81 del self.sockets[fn]
82
84 self.sockets[socket.fileno()] = socket
85 eventlet.spawn(self._monitor_socket, socket.fileno())
86
87 - def put(self, address, socket):
88 """ release socket in the pool
89
90 :param address: tuple (Host, address)
91 :param socket: a socket object
92 """
93 host = self.hosts.get(address)
94 if not host:
95 host = _Host(address)
96
97 if host.nb_connections > self.max_connections:
98 sock.close(socket)
99 host.nb_connections -= 1
100
101 elif host.waiting():
102 host.pool.put(socket)
103 self.monitor_socket(socket)
104 else:
105 host.free_connections.append(socket)
106 self.monitor_socket(socket)
107
108
109 - def clean(self, address):
110 """ close all sockets in the pool for this address
111
112 :param address: tuple (Host, address)
113 """
114 host = self.hosts.get(address)
115 if not host:
116 return
117 if host.free_connections:
118 while host.free_connections:
119 socket = host.free_connections.popleft()
120 sock.close(socket)
121 while host.nb_connections:
122 socket = host.pool.get()
123 sock.close(socket)
124 host.nb_connections -= 1
125