author | Julien Cristau <julien.cristau@logilab.fr> |
Thu, 12 Dec 2013 16:18:58 +0100 | |
changeset 9371 | 1348202527a6 |
parent 8696 | 0bb18407c053 |
child 9456 | a79e88aad555 |
permissions | -rw-r--r-- |
8544
3d049071957e
massive copyright update to avoid clutering later patches
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8238
diff
changeset
|
1 |
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
3 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
4 |
# This file is part of CubicWeb. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
5 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
6 |
# CubicWeb is free software: you can redistribute it and/or modify it under the |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
7 |
# terms of the GNU Lesser General Public License as published by the Free |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
8 |
# Software Foundation, either version 2.1 of the License, or (at your option) |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
9 |
# any later version. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
10 |
# |
5424
8ecbcbff9777
replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5421
diff
changeset
|
11 |
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
12 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
13 |
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
14 |
# details. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
15 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
16 |
# You should have received a copy of the GNU Lesser General Public License along |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4721
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
18 |
"""CubicWeb server connections set : the repository has a limited number of |
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
19 |
:class:`ConnectionsSet` (defined in configuration, default to 4). Each of them |
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
20 |
hold a connection for each source used by the repository. |
5824 | 21 |
""" |
0 | 22 |
|
23 |
__docformat__ = "restructuredtext en" |
|
24 |
||
25 |
import sys |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
26 |
|
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
27 |
class ConnectionsSet(object): |
0 | 28 |
"""handle connections on a set of sources, at some point associated to a |
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
29 |
:class:`Session` |
0 | 30 |
""" |
31 |
||
32 |
def __init__(self, sources): |
|
8238
087bb529035c
[spelling] fix dictionnary -> dictionary typo
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
33 |
# dictionary of (source, connection), indexed by sources'uri |
0 | 34 |
self.source_cnxs = {} |
35 |
for source in sources: |
|
6427
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
36 |
self.add_source(source) |
0 | 37 |
if not 'system' in self.source_cnxs: |
38 |
self.source_cnxs['system'] = self.source_cnxs[sources[0].uri] |
|
39 |
self._cursors = {} |
|
40 |
||
2765
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
41 |
def __getitem__(self, uri): |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
42 |
"""subscription notation provide access to sources'cursors""" |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
43 |
try: |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
44 |
cursor = self._cursors[uri] |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
45 |
except KeyError: |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
46 |
cursor = self.source_cnxs[uri][1].cursor() |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
47 |
if cursor is not None: |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
48 |
# None possible on sources without cursor support such as ldap |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
49 |
self._cursors[uri] = cursor |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
50 |
return cursor |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
51 |
|
6427
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
52 |
def add_source(self, source): |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
53 |
assert not source.uri in self.source_cnxs |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
54 |
self.source_cnxs[source.uri] = (source, source.get_connection()) |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
55 |
|
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
56 |
def remove_source(self, source): |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
57 |
source, cnx = self.source_cnxs.pop(source.uri) |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
58 |
cnx.close() |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
59 |
self._cursors.pop(source.uri, None) |
c8a5ac2d1eaa
[schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
60 |
|
0 | 61 |
def commit(self): |
62 |
"""commit the current transaction for this user""" |
|
63 |
# FIXME: what happends if a commit fail |
|
64 |
# would need a two phases commit or like, but I don't know how to do |
|
65 |
# this using the db-api... |
|
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
66 |
for source, cnx in self.source_cnxs.itervalues(): |
0 | 67 |
# let exception propagates |
68 |
cnx.commit() |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
69 |
|
0 | 70 |
def rollback(self): |
71 |
"""rollback the current transaction for this user""" |
|
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
72 |
for source, cnx in self.source_cnxs.itervalues(): |
0 | 73 |
# catch exceptions, rollback other sources anyway |
74 |
try: |
|
75 |
cnx.rollback() |
|
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7398
diff
changeset
|
76 |
except Exception: |
0 | 77 |
source.critical('rollback error', exc_info=sys.exc_info()) |
5976
00b1b6b906cf
[transaction] if error on rollbacking a source, replace the connection by a new one
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5824
diff
changeset
|
78 |
# error on rollback, the connection is much probably in a really |
00b1b6b906cf
[transaction] if error on rollbacking a source, replace the connection by a new one
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5824
diff
changeset
|
79 |
# bad state. Replace it by a new one. |
00b1b6b906cf
[transaction] if error on rollbacking a source, replace the connection by a new one
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5824
diff
changeset
|
80 |
self.reconnect(source) |
0 | 81 |
|
82 |
def close(self, i_know_what_i_do=False): |
|
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
83 |
"""close all connections in the set""" |
0 | 84 |
if i_know_what_i_do is not True: # unexpected closing safety belt |
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
85 |
raise RuntimeError('connections set shouldn\'t be closed') |
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
86 |
for cu in self._cursors.itervalues(): |
0 | 87 |
try: |
88 |
cu.close() |
|
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7398
diff
changeset
|
89 |
except Exception: |
0 | 90 |
continue |
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
91 |
for _, cnx in self.source_cnxs.itervalues(): |
0 | 92 |
try: |
93 |
cnx.close() |
|
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7398
diff
changeset
|
94 |
except Exception: |
0 | 95 |
continue |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
96 |
|
0 | 97 |
# internals ############################################################### |
98 |
||
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
99 |
def cnxset_set(self): |
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
100 |
"""connections set is being set on a session""" |
0 | 101 |
self.check_connections() |
102 |
||
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
103 |
def cnxset_freed(self): |
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
104 |
"""connections set is being freed from a session""" |
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
105 |
for source, cnx in self.source_cnxs.itervalues(): |
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
106 |
source.cnxset_freed(cnx) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
107 |
|
0 | 108 |
def sources(self): |
7398
26695dd703d8
[repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6427
diff
changeset
|
109 |
"""return the source objects handled by this connections set""" |
0 | 110 |
# implementation details of flying insert requires the system source |
111 |
# first |
|
2765
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
112 |
yield self.source_cnxs['system'][0] |
4721
8f63691ccb7f
pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4710
diff
changeset
|
113 |
for uri, (source, cnx) in self.source_cnxs.items(): |
0 | 114 |
if uri == 'system': |
115 |
continue |
|
116 |
yield source |
|
8696
0bb18407c053
[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8544
diff
changeset
|
117 |
#return [source_cnx[0] for source_cnx in self.source_cnxs.itervalues()] |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
118 |
|
0 | 119 |
def source(self, uid): |
120 |
"""return the source object with the given uri""" |
|
121 |
return self.source_cnxs[uid][0] |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1132
diff
changeset
|
122 |
|
0 | 123 |
def connection(self, uid): |
124 |
"""return the connection on the source object with the given uri""" |
|
125 |
return self.source_cnxs[uid][1] |
|
126 |
||
2765
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
127 |
def reconnect(self, source=None): |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
128 |
"""reopen a connection for this source or all sources if none specified |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
129 |
""" |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
130 |
if source is None: |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
131 |
sources = self.sources() |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
132 |
else: |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
133 |
sources = (source,) |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
134 |
for source in sources: |
4710
4d9ad6a4f261
[pool] properly close existing connection before reconnection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
135 |
try: |
4d9ad6a4f261
[pool] properly close existing connection before reconnection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
136 |
# properly close existing connection if any |
4d9ad6a4f261
[pool] properly close existing connection before reconnection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
137 |
self.source_cnxs[source.uri][1].close() |
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7398
diff
changeset
|
138 |
except Exception: |
4710
4d9ad6a4f261
[pool] properly close existing connection before reconnection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
139 |
pass |
2765
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
140 |
source.info('trying to reconnect') |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
141 |
self.source_cnxs[source.uri] = (source, source.get_connection()) |
5e2525d7b1b1
reconnect without argument reconnect all sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2063
diff
changeset
|
142 |
self._cursors.pop(source.uri, None) |
0 | 143 |
|
144 |
def check_connections(self): |
|
145 |
for source, cnx in self.source_cnxs.itervalues(): |
|
146 |
newcnx = source.check_connection(cnx) |
|
147 |
if newcnx is not None: |
|
148 |
self.reset_connection(source, newcnx) |
|
149 |
||
150 |
def reset_connection(self, source, cnx): |
|
151 |
self.source_cnxs[source.uri] = (source, cnx) |
|
152 |
self._cursors.pop(source.uri, None) |
|
153 |
||
154 |
||
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5976
diff
changeset
|
155 |
from cubicweb.server.hook import Operation, LateOperation, SingleLastOperation |
2835
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2765
diff
changeset
|
156 |
from logilab.common.deprecation import class_moved, class_renamed |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2765
diff
changeset
|
157 |
Operation = class_moved(Operation) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2765
diff
changeset
|
158 |
PreCommitOperation = class_renamed('PreCommitOperation', Operation) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2765
diff
changeset
|
159 |
LateOperation = class_moved(LateOperation) |
04034421b072
[hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2765
diff
changeset
|
160 |
SingleLastOperation = class_moved(SingleLastOperation) |