|
1 # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
3 # |
|
4 # This file is part of CubicWeb. |
|
5 # |
|
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
|
7 # terms of the GNU Lesser General Public License as published by the Free |
|
8 # Software Foundation, either version 2.1 of the License, or (at your option) |
|
9 # any later version. |
|
10 # |
|
11 # logilab-common is distributed in the hope that it will be useful, but WITHOUT |
|
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
|
14 # details. |
|
15 # |
|
16 # You should have received a copy of the GNU Lesser General Public License along |
|
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
1 """twisted server for CubicWeb web instances |
18 """twisted server for CubicWeb web instances |
2 |
19 |
3 :organization: Logilab |
|
4 :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
|
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
|
7 """ |
20 """ |
8 __docformat__ = "restructuredtext en" |
21 __docformat__ = "restructuredtext en" |
9 |
22 |
10 import sys |
23 import sys |
11 import os |
24 import os |
12 import select |
25 import select |
13 import errno |
26 import errno |
14 import hotshot |
|
15 from time import mktime |
27 from time import mktime |
16 from datetime import date, timedelta |
28 from datetime import date, timedelta |
17 from urlparse import urlsplit, urlunsplit |
29 from urlparse import urlsplit, urlunsplit |
18 |
30 |
19 from twisted.internet import reactor, task, threads |
31 from twisted.internet import reactor, task, threads |
284 return http.Response(code, req.headers_out, content) |
292 return http.Response(code, req.headers_out, content) |
285 |
293 |
286 from twisted.internet import defer |
294 from twisted.internet import defer |
287 from twisted.web2 import fileupload |
295 from twisted.web2 import fileupload |
288 |
296 |
289 # XXX set max file size to 100Mo: put max upload size in the configuration |
297 # XXX set max file size to 200MB: put max upload size in the configuration |
290 # line below for twisted >= 8.0, default param value for earlier version |
298 # line below for twisted >= 8.0, default param value for earlier version |
291 resource.PostableResource.maxSize = 100*1024*1024 |
299 resource.PostableResource.maxSize = 200*1024*1024 |
292 def parsePOSTData(request, maxMem=100*1024, maxFields=1024, |
300 def parsePOSTData(request, maxMem=100*1024, maxFields=1024, |
293 maxSize=100*1024*1024): |
301 maxSize=200*1024*1024): |
294 if request.stream.length == 0: |
302 if request.stream.length == 0: |
295 return defer.succeed(None) |
303 return defer.succeed(None) |
296 |
304 |
297 ctype = request.headers.getHeader('content-type') |
305 ctype = request.headers.getHeader('content-type') |
298 |
306 |
335 from logging import getLogger |
343 from logging import getLogger |
336 from cubicweb import set_log_methods |
344 from cubicweb import set_log_methods |
337 set_log_methods(CubicWebRootResource, getLogger('cubicweb.twisted')) |
345 set_log_methods(CubicWebRootResource, getLogger('cubicweb.twisted')) |
338 |
346 |
339 |
347 |
340 |
348 listiterator = type(iter([])) |
341 def _gc_debug(): |
349 |
|
350 def _gc_debug(all=True): |
342 import gc |
351 import gc |
343 from pprint import pprint |
352 from pprint import pprint |
344 from cubicweb.appobject import AppObject |
353 from cubicweb.appobject import AppObject |
345 gc.collect() |
354 gc.collect() |
346 count = 0 |
355 count = 0 |
347 acount = 0 |
356 acount = 0 |
|
357 fcount = 0 |
|
358 rcount = 0 |
|
359 ccount = 0 |
|
360 scount = 0 |
348 ocount = {} |
361 ocount = {} |
|
362 from rql.stmts import Union |
|
363 from cubicweb.schema import CubicWebSchema |
|
364 from cubicweb.rset import ResultSet |
|
365 from cubicweb.dbapi import Connection, Cursor |
|
366 from cubicweb.req import RequestSessionBase |
|
367 from cubicweb.server.repository import Repository |
|
368 from cubicweb.server.sources.native import NativeSQLSource |
|
369 from cubicweb.server.session import Session |
|
370 from cubicweb.devtools.testlib import CubicWebTC |
|
371 from logilab.common.testlib import TestSuite |
|
372 from optparse import Values |
|
373 import types, weakref |
349 for obj in gc.get_objects(): |
374 for obj in gc.get_objects(): |
350 if isinstance(obj, CubicWebTwistedRequestAdapter): |
375 if isinstance(obj, RequestSessionBase): |
351 count += 1 |
376 count += 1 |
|
377 if isinstance(obj, Session): |
|
378 print ' session', obj, referrers(obj, True) |
352 elif isinstance(obj, AppObject): |
379 elif isinstance(obj, AppObject): |
353 acount += 1 |
380 acount += 1 |
354 else: |
381 elif isinstance(obj, ResultSet): |
|
382 rcount += 1 |
|
383 #print ' rset', obj, referrers(obj) |
|
384 elif isinstance(obj, Repository): |
|
385 print ' REPO', obj, referrers(obj, True) |
|
386 #elif isinstance(obj, NativeSQLSource): |
|
387 # print ' SOURCe', obj, referrers(obj) |
|
388 elif isinstance(obj, CubicWebTC): |
|
389 print ' TC', obj, referrers(obj) |
|
390 elif isinstance(obj, TestSuite): |
|
391 print ' SUITE', obj, referrers(obj) |
|
392 #elif isinstance(obj, Values): |
|
393 # print ' values', '%#x' % id(obj), referrers(obj, True) |
|
394 elif isinstance(obj, Connection): |
|
395 ccount += 1 |
|
396 #print ' cnx', obj, referrers(obj) |
|
397 #elif isinstance(obj, Cursor): |
|
398 # ccount += 1 |
|
399 # print ' cursor', obj, referrers(obj) |
|
400 elif isinstance(obj, file): |
|
401 fcount += 1 |
|
402 # print ' open file', file.name, file.fileno |
|
403 elif isinstance(obj, CubicWebSchema): |
|
404 scount += 1 |
|
405 print ' schema', obj, referrers(obj) |
|
406 elif not isinstance(obj, (type, tuple, dict, list, set, frozenset, |
|
407 weakref.ref, weakref.WeakKeyDictionary, |
|
408 listiterator, |
|
409 property, classmethod, |
|
410 types.ModuleType, types.MemberDescriptorType, |
|
411 types.FunctionType, types.MethodType)): |
355 try: |
412 try: |
356 ocount[obj.__class__] += 1 |
413 ocount[obj.__class__] += 1 |
357 except KeyError: |
414 except KeyError: |
358 ocount[obj.__class__] = 1 |
415 ocount[obj.__class__] = 1 |
359 except AttributeError: |
416 except AttributeError: |
360 pass |
417 pass |
361 print 'IN MEM REQUESTS', count |
418 if count: |
362 print 'IN MEM APPOBJECTS', acount |
419 print ' NB REQUESTS/SESSIONS', count |
363 ocount = sorted(ocount.items(), key=lambda x: x[1], reverse=True)[:20] |
420 if acount: |
364 pprint(ocount) |
421 print ' NB APPOBJECTS', acount |
365 print 'UNREACHABLE', gc.garbage |
422 if ccount: |
|
423 print ' NB CONNECTIONS', ccount |
|
424 if rcount: |
|
425 print ' NB RSETS', rcount |
|
426 if scount: |
|
427 print ' NB SCHEMAS', scount |
|
428 if fcount: |
|
429 print ' NB FILES', fcount |
|
430 if all: |
|
431 ocount = sorted(ocount.items(), key=lambda x: x[1], reverse=True)[:20] |
|
432 pprint(ocount) |
|
433 if gc.garbage: |
|
434 print 'UNREACHABLE', gc.garbage |
|
435 |
|
436 def referrers(obj, showobj=False): |
|
437 try: |
|
438 return sorted(set((type(x), showobj and x or getattr(x, '__name__', '%#x' % id(x))) |
|
439 for x in _referrers(obj))) |
|
440 except TypeError: |
|
441 s = set() |
|
442 unhashable = [] |
|
443 for x in _referrers(obj): |
|
444 try: |
|
445 s.add(x) |
|
446 except TypeError: |
|
447 unhashable.append(x) |
|
448 return sorted(s) + unhashable |
|
449 |
|
450 def _referrers(obj, seen=None, level=0): |
|
451 import gc, types |
|
452 from cubicweb.schema import CubicWebRelationSchema, CubicWebEntitySchema |
|
453 interesting = [] |
|
454 if seen is None: |
|
455 seen = set() |
|
456 for x in gc.get_referrers(obj): |
|
457 if id(x) in seen: |
|
458 continue |
|
459 seen.add(id(x)) |
|
460 if isinstance(x, types.FrameType): |
|
461 continue |
|
462 if isinstance(x, (CubicWebRelationSchema, CubicWebEntitySchema)): |
|
463 continue |
|
464 if isinstance(x, (list, tuple, set, dict, listiterator)): |
|
465 if level >= 5: |
|
466 pass |
|
467 #interesting.append(x) |
|
468 else: |
|
469 interesting += _referrers(x, seen, level+1) |
|
470 else: |
|
471 interesting.append(x) |
|
472 return interesting |
366 |
473 |
367 def run(config, debug): |
474 def run(config, debug): |
368 # create the site |
475 # create the site |
369 root_resource = CubicWebRootResource(config, debug) |
476 root_resource = CubicWebRootResource(config, debug) |
370 website = server.Site(root_resource) |
477 website = server.Site(root_resource) |