152 |
152 |
153 class _CnxSetPool(object): |
153 class _CnxSetPool(object): |
154 |
154 |
155 def __init__(self, source, size): |
155 def __init__(self, source, size): |
156 self._cnxsets = [] |
156 self._cnxsets = [] |
157 self._queue = queue.Queue() |
157 if size is not None: |
158 for i in range(size): |
158 self._queue = queue.Queue() |
159 cnxset = source.wrapped_connection() |
159 for i in range(size): |
160 self._cnxsets.append(cnxset) |
160 cnxset = source.wrapped_connection() |
161 self._queue.put_nowait(cnxset) |
161 self._cnxsets.append(cnxset) |
|
162 self._queue.put_nowait(cnxset) |
|
163 else: |
|
164 self._queue = None |
|
165 self._source = source |
162 super(_CnxSetPool, self).__init__() |
166 super(_CnxSetPool, self).__init__() |
163 |
167 |
164 def qsize(self): |
168 def qsize(self): |
165 return self._queue.qsize() |
169 q = self._queue |
|
170 if q is None: |
|
171 return None |
|
172 return q.qsize() |
166 |
173 |
167 def get(self): |
174 def get(self): |
|
175 q = self._queue |
|
176 if q is None: |
|
177 return self._source.wrapped_connection() |
168 try: |
178 try: |
169 return self._queue.get(True, timeout=5) |
179 return self._queue.get(True, timeout=5) |
170 except queue.Empty: |
180 except queue.Empty: |
171 raise Exception('no connections set available after 5 secs, probably either a ' |
181 raise Exception('no connections set available after 5 secs, probably either a ' |
172 'bug in code (too many uncommited/rolled back ' |
182 'bug in code (too many uncommited/rolled back ' |
173 'connections) or too much load on the server (in ' |
183 'connections) or too much load on the server (in ' |
174 'which case you can try to set a bigger ' |
184 'which case you can try to set a bigger ' |
175 'connections pool size)') |
185 'connections pool size)') |
176 |
186 |
177 def release(self, cnxset): |
187 def release(self, cnxset): |
178 self._queue.put_nowait(cnxset) |
188 q = self._queue |
|
189 if q is None: |
|
190 cnxset.close(True) |
|
191 else: |
|
192 self._queue.put_nowait(cnxset) |
179 |
193 |
180 def __iter__(self): |
194 def __iter__(self): |
181 for cnxset in self._cnxsets: |
195 for cnxset in self._cnxsets: |
182 yield cnxset |
196 yield cnxset |
183 |
197 |
184 def close(self): |
198 def close(self): |
185 q = self._queue |
199 q = self._queue |
186 while not q.empty(): |
200 if q is not None: |
187 cnxset = q.get_nowait() |
201 while not q.empty(): |
188 try: |
202 cnxset = q.get_nowait() |
189 cnxset.close(True) |
203 try: |
190 except Exception: |
204 cnxset.close(True) |
191 self.exception('error while closing %s' % cnxset) |
205 except Exception: |
|
206 self.exception('error while closing %s' % cnxset) |
192 |
207 |
193 |
208 |
194 class Repository(object): |
209 class Repository(object): |
195 """a repository provides access to a set of persistent storages for |
210 """a repository provides access to a set of persistent storages for |
196 entities and relations |
211 entities and relations |
246 """should be called bootstrap_repository, as this is what it does""" |
261 """should be called bootstrap_repository, as this is what it does""" |
247 config = self.config |
262 config = self.config |
248 # copy pool size here since config.init_cube() and config.load_schema() |
263 # copy pool size here since config.init_cube() and config.load_schema() |
249 # reload configuration from file and could reset a manually set pool |
264 # reload configuration from file and could reset a manually set pool |
250 # size. |
265 # size. |
251 pool_size = config['connections-pool-size'] |
266 if config['connections-pooler-enabled']: |
252 # 0. init a cnxset of size 1 that will be used to fetch bootstrap information from |
267 pool_size, min_pool_size = config['connections-pool-size'], 1 |
|
268 else: |
|
269 pool_size = min_pool_size = None |
|
270 # 0. init a cnxset that will be used to fetch bootstrap information from |
253 # the database |
271 # the database |
254 self.cnxsets = _CnxSetPool(self.system_source, 1) |
272 self.cnxsets = _CnxSetPool(self.system_source, min_pool_size) |
255 # 1. set used cubes |
273 # 1. set used cubes |
256 if config.creating or not config.read_instance_schema: |
274 if config.creating or not config.read_instance_schema: |
257 config.bootstrap_cubes() |
275 config.bootstrap_cubes() |
258 else: |
276 else: |
259 self.set_schema(self.config.load_bootstrap_schema(), resetvreg=False) |
277 self.set_schema(self.config.load_bootstrap_schema(), resetvreg=False) |
265 # |
283 # |
266 # restrict appobject_path to only load hooks and entity classes in |
284 # restrict appobject_path to only load hooks and entity classes in |
267 # the registry |
285 # the registry |
268 config.cube_appobject_path = set(('hooks', 'entities')) |
286 config.cube_appobject_path = set(('hooks', 'entities')) |
269 config.cubicweb_appobject_path = set(('hooks', 'entities')) |
287 config.cubicweb_appobject_path = set(('hooks', 'entities')) |
270 # limit connections pool to 1 |
288 # limit connections pool size |
271 pool_size = 1 |
289 pool_size = min_pool_size |
272 if config.quick_start or config.creating or not config.read_instance_schema: |
290 if config.quick_start or config.creating or not config.read_instance_schema: |
273 # load schema from the file system |
291 # load schema from the file system |
274 if not config.creating: |
292 if not config.creating: |
275 self.info("set fs instance'schema") |
293 self.info("set fs instance'schema") |
276 self.set_schema(config.load_schema(expand_cubes=True)) |
294 self.set_schema(config.load_schema(expand_cubes=True)) |