923
by Christophe Simonis
add encoding comment and vim comment |
1 |
# -*- encoding: utf-8 -*-
|
1
by pinky
New trunk |
2 |
##############################################################################
|
3 |
#
|
|
1230
by Christophe Simonis
passing in GPL-3 |
4 |
# OpenERP, Open Source Management Solution
|
1556
by Stephane Wirtel
[IMP] Update the copyright to 2009 |
5 |
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
1230
by Christophe Simonis
passing in GPL-3 |
6 |
# $Id$
|
7 |
#
|
|
8 |
# This program is free software: you can redistribute it and/or modify
|
|
9 |
# it under the terms of the GNU General Public License as published by
|
|
10 |
# the Free Software Foundation, either version 3 of the License, or
|
|
11 |
# (at your option) any later version.
|
|
12 |
#
|
|
13 |
# This program is distributed in the hope that it will be useful,
|
|
14 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16 |
# GNU General Public License for more details.
|
|
17 |
#
|
|
18 |
# You should have received a copy of the GNU General Public License
|
|
19 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20 |
#
|
|
21 |
##############################################################################
|
|
1
by pinky
New trunk |
22 |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
23 |
__all__ = ['db_connect', 'close_db'] |
24 |
||
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
25 |
import netsvc |
1680.1.5
by Christophe Simonis
[FIX] database connections aren't serialized by default |
26 |
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
27 |
from psycopg2.psycopg1 import cursor as psycopg1cursor |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
28 |
from psycopg2.pool import PoolError |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
29 |
|
30 |
import psycopg2.extensions |
|
1398
by Fabien Pinckaers
improvements_bugfixes |
31 |
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
32 |
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) |
33 |
||
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
34 |
types_mapping = { |
35 |
'date': (1082,), |
|
36 |
'time': (1083,), |
|
37 |
'datetime': (1114,), |
|
38 |
}
|
|
39 |
||
1398
by Fabien Pinckaers
improvements_bugfixes |
40 |
def unbuffer(symb, cr): |
41 |
if symb is None: return None |
|
42 |
return str(symb) |
|
43 |
||
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
44 |
def undecimalize(symb, cr): |
45 |
if symb is None: return None |
|
46 |
return float(symb) |
|
47 |
||
48 |
for name, typeoid in types_mapping.items(): |
|
49 |
psycopg2.extensions.register_type(psycopg2.extensions.new_type(typeoid, name, lambda x, cr: x)) |
|
50 |
psycopg2.extensions.register_type(psycopg2.extensions.new_type((700, 701, 1700,), 'float', undecimalize)) |
|
51 |
||
52 |
||
1
by pinky
New trunk |
53 |
import tools |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
54 |
from tools.func import wraps |
55 |
from datetime import datetime as mdt |
|
1886
by Christophe Simonis
[IMP] sql_log |
56 |
from datetime import timedelta |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
57 |
import threading |
58 |
||
1
by pinky
New trunk |
59 |
import re |
522
by ced
Improve RE in sql logging to add possibility of "" in table definition |
60 |
re_from = re.compile('.* from "?([a-zA-Z_0-9]+)"? .*$'); |
61 |
re_into = re.compile('.* into "?([a-zA-Z_0-9]+)"? .*$'); |
|
399
by ced
kernel: add log to sql query |
62 |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
63 |
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
64 |
def log(msg, lvl=netsvc.LOG_DEBUG): |
65 |
logger = netsvc.Logger() |
|
66 |
logger.notifyChannel('sql', lvl, msg) |
|
67 |
||
68 |
class Cursor(object): |
|
943
by Christophe Simonis
move, rename and refactor use of ID_MAX |
69 |
IN_MAX = 1000 |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
70 |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
71 |
def check(f): |
72 |
@wraps(f) |
|
73 |
def wrapper(self, *args, **kwargs): |
|
1766.2.3
by Christophe Simonis
[FIX] do not relay on _obj to know if the cursor has been closed |
74 |
if self.__closed: |
1387
by Christophe Simonis
[FIX] free the database connecion in all cases |
75 |
raise psycopg2.ProgrammingError('Unable to use the cursor after having closing it') |
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
76 |
return f(self, *args, **kwargs) |
77 |
return wrapper |
|
922
by Christophe Simonis
convert tabs to 4 spaces |
78 |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
79 |
def __init__(self, pool, dbname, serialized=False): |
80 |
self.sql_from_log = {} |
|
81 |
self.sql_into_log = {} |
|
82 |
self.sql_log = False |
|
83 |
self.sql_log_count = 0 |
|
84 |
||
85 |
self.__closed = True # avoid the call of close() (by __del__) if an exception |
|
86 |
# is raised by any of the following initialisations
|
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
87 |
self._pool = pool |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
88 |
self.dbname = dbname |
1680.1.5
by Christophe Simonis
[FIX] database connections aren't serialized by default |
89 |
self._serialized = serialized |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
90 |
self._cnx = pool.borrow(dsn(dbname)) |
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
91 |
self._obj = self._cnx.cursor(cursor_factory=psycopg1cursor) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
92 |
self.__closed = False # real initialisation value |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
93 |
self.autocommit(False) |
1607
by Stephane Wirtel
[IMP] Improve the speed - Use the inspect module only if we specify the debug log level |
94 |
|
95 |
if tools.config['log_level'] in (netsvc.LOG_DEBUG, netsvc.LOG_DEBUG_RPC): |
|
96 |
from inspect import stack |
|
97 |
self.__caller = tuple(stack()[2][1:3]) |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
98 |
|
1387
by Christophe Simonis
[FIX] free the database connecion in all cases |
99 |
def __del__(self): |
1766.2.3
by Christophe Simonis
[FIX] do not relay on _obj to know if the cursor has been closed |
100 |
if not self.__closed: |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
101 |
# Oops. 'self' has not been closed explicitly.
|
102 |
# The cursor will be deleted by the garbage collector,
|
|
103 |
# but the database connection is not put back into the connection
|
|
104 |
# pool, preventing some operation on the database like dropping it.
|
|
105 |
# This can also lead to a server overload.
|
|
1607
by Stephane Wirtel
[IMP] Improve the speed - Use the inspect module only if we specify the debug log level |
106 |
if tools.config['log_level'] in (netsvc.LOG_DEBUG, netsvc.LOG_DEBUG_RPC): |
107 |
msg = "Cursor not closed explicitly\n" \ |
|
108 |
"Cursor was created at %s:%s" % self.__caller |
|
109 |
log(msg, netsvc.LOG_WARNING) |
|
1387
by Christophe Simonis
[FIX] free the database connecion in all cases |
110 |
self.close() |
111 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
112 |
@check
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
113 |
def execute(self, query, params=None): |
114 |
if '%d' in query or '%f' in query: |
|
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
115 |
log(query, netsvc.LOG_WARNING) |
1766.2.8
by Jay(Open ERP)
[FIX] Corrected arguement passed to cursor's execute method(when params=[] |
116 |
log("SQL queries mustn't contain %d or %f anymore. Use only %s", netsvc.LOG_WARNING) |
1461
by Christophe Simonis
[IMP] Track where a cursor is created when this cursor is not closed explicitly |
117 |
if params: |
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
118 |
query = query.replace('%d', '%s').replace('%f', '%s') |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
119 |
|
922
by Christophe Simonis
convert tabs to 4 spaces |
120 |
if self.sql_log: |
121 |
now = mdt.now() |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
122 |
|
1635
by Christophe Simonis
[IMP] log queries that fail |
123 |
try: |
1766.2.8
by Jay(Open ERP)
[FIX] Corrected arguement passed to cursor's execute method(when params=[] |
124 |
params = params or None |
1635
by Christophe Simonis
[IMP] log queries that fail |
125 |
res = self._obj.execute(query, params) |
1688.1.1
by Christophe Simonis
[IMP] bad queries are logged in debug mode (log also the exception) |
126 |
except Exception, e: |
127 |
log("bad query: %s" % self._obj.query) |
|
128 |
log(e) |
|
1635
by Christophe Simonis
[IMP] log queries that fail |
129 |
raise
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
130 |
|
922
by Christophe Simonis
convert tabs to 4 spaces |
131 |
if self.sql_log: |
1886
by Christophe Simonis
[IMP] sql_log |
132 |
delay = mdt.now() - now |
133 |
delay = delay.seconds * 1E6 + delay.microseconds |
|
134 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
135 |
log("query: %s" % self._obj.query) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
136 |
self.sql_log_count+=1 |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
137 |
res_from = re_from.match(query.lower()) |
922
by Christophe Simonis
convert tabs to 4 spaces |
138 |
if res_from: |
139 |
self.sql_from_log.setdefault(res_from.group(1), [0, 0]) |
|
140 |
self.sql_from_log[res_from.group(1)][0] += 1 |
|
1886
by Christophe Simonis
[IMP] sql_log |
141 |
self.sql_from_log[res_from.group(1)][1] += delay |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
142 |
res_into = re_into.match(query.lower()) |
922
by Christophe Simonis
convert tabs to 4 spaces |
143 |
if res_into: |
144 |
self.sql_into_log.setdefault(res_into.group(1), [0, 0]) |
|
145 |
self.sql_into_log[res_into.group(1)][0] += 1 |
|
1886
by Christophe Simonis
[IMP] sql_log |
146 |
self.sql_into_log[res_into.group(1)][1] += delay |
922
by Christophe Simonis
convert tabs to 4 spaces |
147 |
return res |
148 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
149 |
def print_log(self): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
150 |
if not self.sql_log: |
151 |
return
|
|
152 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
153 |
def process(type): |
154 |
sqllogs = {'from':self.sql_from_log, 'into':self.sql_into_log} |
|
155 |
if not sqllogs[type]: |
|
156 |
return
|
|
157 |
sqllogitems = sqllogs[type].items() |
|
158 |
sqllogitems.sort(key=lambda k: k[1][1]) |
|
159 |
sum = 0 |
|
160 |
log("SQL LOG %s:" % (type,)) |
|
161 |
for r in sqllogitems: |
|
1886
by Christophe Simonis
[IMP] sql_log |
162 |
delay = timedelta(microseconds=r[1][1]) |
163 |
log("table: %s: %s/%s" %(r[0], str(delay), r[1][0])) |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
164 |
sum+= r[1][1] |
1886
by Christophe Simonis
[IMP] sql_log |
165 |
sum = timedelta(microseconds=sum) |
166 |
log("SUM:%s/%d" % (str(sum), self.sql_log_count)) |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
167 |
sqllogs[type].clear() |
168 |
process('from') |
|
169 |
process('into') |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
170 |
self.sql_log_count = 0 |
1461
by Christophe Simonis
[IMP] Track where a cursor is created when this cursor is not closed explicitly |
171 |
self.sql_log = False |
922
by Christophe Simonis
convert tabs to 4 spaces |
172 |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
173 |
@check
|
922
by Christophe Simonis
convert tabs to 4 spaces |
174 |
def close(self): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
175 |
if not self._obj: |
176 |
return
|
|
177 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
178 |
self.print_log() |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
179 |
|
180 |
if not self._serialized: |
|
181 |
self.rollback() # Ensure we close the current transaction. |
|
182 |
||
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
183 |
self._obj.close() |
922
by Christophe Simonis
convert tabs to 4 spaces |
184 |
|
1080
by Jay Vora
Accepted Uppercase DB names and displayed on terminal |
185 |
# This force the cursor to be freed, and thus, available again. It is
|
186 |
# important because otherwise we can overload the server very easily
|
|
922
by Christophe Simonis
convert tabs to 4 spaces |
187 |
# because of a cursor shortage (because cursors are not garbage
|
1080
by Jay Vora
Accepted Uppercase DB names and displayed on terminal |
188 |
# collected as fast as they should). The problem is probably due in
|
922
by Christophe Simonis
convert tabs to 4 spaces |
189 |
# part because browse records keep a reference to the cursor.
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
190 |
del self._obj |
1766.2.3
by Christophe Simonis
[FIX] do not relay on _obj to know if the cursor has been closed |
191 |
self.__closed = True |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
192 |
self._pool.give_back(self._cnx) |
193 |
||
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
194 |
@check
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
195 |
def autocommit(self, on): |
1680.1.5
by Christophe Simonis
[FIX] database connections aren't serialized by default |
196 |
offlevel = [ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE][bool(self._serialized)] |
197 |
self._cnx.set_isolation_level([offlevel, ISOLATION_LEVEL_AUTOCOMMIT][bool(on)]) |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
198 |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
199 |
@check
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
200 |
def commit(self): |
201 |
return self._cnx.commit() |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
202 |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
203 |
@check
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
204 |
def rollback(self): |
205 |
return self._cnx.rollback() |
|
922
by Christophe Simonis
convert tabs to 4 spaces |
206 |
|
1382
by Christophe Simonis
[IMP] check that the cursor has not been closed before execute a query |
207 |
@check
|
922
by Christophe Simonis
convert tabs to 4 spaces |
208 |
def __getattr__(self, name): |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
209 |
return getattr(self._obj, name) |
1
by pinky
New trunk |
210 |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
211 |
|
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
212 |
class ConnectionPool(object): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
213 |
|
214 |
def locked(fun): |
|
215 |
@wraps(fun) |
|
216 |
def _locked(self, *args, **kwargs): |
|
217 |
self._lock.acquire() |
|
218 |
try: |
|
219 |
return fun(self, *args, **kwargs) |
|
220 |
finally: |
|
221 |
self._lock.release() |
|
222 |
return _locked |
|
223 |
||
224 |
||
225 |
def __init__(self, maxconn=64): |
|
226 |
self._connections = [] |
|
227 |
self._maxconn = max(maxconn, 1) |
|
228 |
self._lock = threading.Lock() |
|
229 |
self._logger = netsvc.Logger() |
|
230 |
||
231 |
def _debug(self, msg): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
232 |
self._logger.notifyChannel('ConnectionPool', netsvc.LOG_DEBUG, msg) |
233 |
#pass
|
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
234 |
|
235 |
@locked
|
|
236 |
def borrow(self, dsn): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
237 |
self._debug('Borrow connection to %s' % (dsn,)) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
238 |
|
239 |
result = None |
|
240 |
for i, (cnx, used) in enumerate(self._connections): |
|
1885
by Christophe Simonis
[FIX] connection pool when database password is provided (thanks to Syleam Crew) |
241 |
if not used and dsn_are_equals(cnx.dsn, dsn): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
242 |
self._debug('Existing connection found at index %d' % i) |
243 |
||
244 |
self._connections.pop(i) |
|
245 |
self._connections.append((cnx, True)) |
|
246 |
||
247 |
result = cnx |
|
248 |
break
|
|
249 |
if result: |
|
250 |
return result |
|
251 |
||
252 |
if len(self._connections) >= self._maxconn: |
|
253 |
# try to remove the older connection not used
|
|
254 |
for i, (cnx, used) in enumerate(self._connections): |
|
255 |
if not used: |
|
256 |
self._debug('Removing old connection at index %d: %s' % (i, cnx.dsn)) |
|
257 |
self._connections.pop(i) |
|
258 |
break
|
|
259 |
else: |
|
260 |
# note: this code is called only if the for loop has completed (no break)
|
|
261 |
raise PoolError('Connection Pool Full') |
|
262 |
||
263 |
self._debug('Create new connection') |
|
264 |
result = psycopg2.connect(dsn=dsn) |
|
265 |
self._connections.append((result, True)) |
|
266 |
return result |
|
267 |
||
268 |
@locked
|
|
269 |
def give_back(self, connection): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
270 |
self._debug('Give back connection to %s' % (connection.dsn,)) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
271 |
for i, (cnx, used) in enumerate(self._connections): |
272 |
if cnx is connection: |
|
273 |
self._connections.pop(i) |
|
274 |
self._connections.append((cnx, False)) |
|
275 |
break
|
|
276 |
else: |
|
277 |
raise PoolError('This connection does not below to the pool') |
|
278 |
||
279 |
@locked
|
|
280 |
def close_all(self, dsn): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
281 |
self._debug('Close all connections to %s' % (dsn,)) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
282 |
for i, (cnx, used) in tools.reverse_enumerate(self._connections): |
1885
by Christophe Simonis
[FIX] connection pool when database password is provided (thanks to Syleam Crew) |
283 |
if dsn_are_equals(cnx.dsn, dsn): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
284 |
cnx.close() |
285 |
self._connections.pop(i) |
|
286 |
||
287 |
||
288 |
class Connection(object): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
289 |
def _debug(self, msg): |
290 |
self._logger.notifyChannel('Connection', netsvc.LOG_DEBUG, msg) |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
291 |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
292 |
def __init__(self, pool, dbname): |
922
by Christophe Simonis
convert tabs to 4 spaces |
293 |
self.dbname = dbname |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
294 |
self._pool = pool |
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
295 |
self._logger = netsvc.Logger() |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
296 |
|
297 |
def cursor(self, serialized=False): |
|
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
298 |
cursor_type = serialized and 'serialized ' or '' |
299 |
self._debug('create %scursor to "%s"' % (cursor_type, self.dbname,)) |
|
1879
by Christophe Simonis
[IMP] better connection pool (global) |
300 |
return Cursor(self._pool, self.dbname, serialized=serialized) |
1341.1.15
by Christophe Simonis
[IMP] use psycopg2 instead of psycopg1 |
301 |
|
1680.1.5
by Christophe Simonis
[FIX] database connections aren't serialized by default |
302 |
def serialized_cursor(self): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
303 |
return self.cursor(True) |
304 |
||
1892
by Christophe Simonis
[FIX] db_exist method works as expected |
305 |
def __nonzero__(self): |
306 |
"""Check if connection is possible"""
|
|
307 |
try: |
|
308 |
cr = self.cursor() |
|
309 |
cr.close() |
|
310 |
return True |
|
311 |
except: |
|
312 |
return False |
|
313 |
||
1879
by Christophe Simonis
[IMP] better connection pool (global) |
314 |
|
315 |
_dsn = '' |
|
316 |
for p in ('host', 'port', 'user', 'password'): |
|
317 |
cfg = tools.config['db_' + p] |
|
318 |
if cfg: |
|
319 |
_dsn += '%s=%s ' % (p, cfg) |
|
320 |
||
321 |
def dsn(db_name): |
|
322 |
return '%sdbname=%s' % (_dsn, db_name) |
|
323 |
||
1885
by Christophe Simonis
[FIX] connection pool when database password is provided (thanks to Syleam Crew) |
324 |
def dsn_are_equals(first, second): |
325 |
def key(dsn): |
|
326 |
k = dict(x.split('=', 1) for x in dsn.strip().split()) |
|
327 |
k.pop('password', None) # password is not relevant |
|
328 |
return k |
|
329 |
return key(first) == key(second) |
|
330 |
||
1879
by Christophe Simonis
[IMP] better connection pool (global) |
331 |
|
332 |
_Pool = ConnectionPool(int(tools.config['db_maxconn'])) |
|
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
333 |
|
1587.3.1
by Christophe Simonis
[FIX] delete the connection pool to template1 when finished |
334 |
def db_connect(db_name): |
1935
by Christophe Simonis
[FIX] remove the lock on database connections |
335 |
return Connection(_Pool, db_name) |
923
by Christophe Simonis
add encoding comment and vim comment |
336 |
|
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
337 |
def close_db(db_name): |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
338 |
_Pool.close_all(dsn(db_name)) |
1561.1.1
by Christophe Simonis
[IMP] improve cache system |
339 |
tools.cache.clean_caches_for_db(db_name) |
1879
by Christophe Simonis
[IMP] better connection pool (global) |
340 |
|
1341.1.19
by Christophe Simonis
[FIX] psycopg2: convert types & update web_services |
341 |
|
923
by Christophe Simonis
add encoding comment and vim comment |
342 |
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
343 |