# HG changeset patch # User Sylvain Thénault # Date 1274381233 -7200 # Node ID a64f48dd5fe49fda648f155fe4c6868bae5d0e98 # Parent 25fd74c23f91c983d33b128ea74ca8bc26f5b01d# Parent 9b7bdbfee68b96bdd9322c0e8bcc79cc4b5dbcbb backport stable diff -r 25fd74c23f91 -r a64f48dd5fe4 __pkginfo__.py --- a/__pkginfo__.py Tue May 18 18:18:08 2010 +0200 +++ b/__pkginfo__.py Thu May 20 20:47:13 2010 +0200 @@ -40,7 +40,7 @@ ] __depends__ = { - 'logilab-common': '>= 0.50.1', + 'logilab-common': '>= 0.50.2', 'logilab-mtconverter': '>= 0.6.0', 'rql': '>= 0.26.0', 'yams': '>= 0.28.1', diff -r 25fd74c23f91 -r a64f48dd5fe4 debian/control --- a/debian/control Tue May 18 18:18:08 2010 +0200 +++ b/debian/control Thu May 20 20:47:13 2010 +0200 @@ -97,7 +97,7 @@ Package: cubicweb-common Architecture: all XB-Python-Version: ${python:Versions} -Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.50.1), python-yams (>= 0.29.0), python-rql (>= 0.26.0), python-lxml +Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.50.2), python-yams (>= 0.29.0), python-rql (>= 0.26.0), python-lxml Recommends: python-simpletal (>= 4.0), python-crypto Conflicts: cubicweb-core Replaces: cubicweb-core diff -r 25fd74c23f91 -r a64f48dd5fe4 devtools/__init__.py --- a/devtools/__init__.py Tue May 18 18:18:08 2010 +0200 +++ b/devtools/__init__.py Thu May 20 20:47:13 2010 +0200 @@ -274,7 +274,6 @@ def init_test_database_sqlite(config): """initialize a fresh sqlite databse used for testing purpose""" # remove database file if it exists - dbfile = config.sources()['system']['db-name'] if not reset_test_database_sqlite(config): # initialize the database import shutil diff -r 25fd74c23f91 -r a64f48dd5fe4 etwist/server.py --- a/etwist/server.py Tue May 18 18:18:08 2010 +0200 +++ b/etwist/server.py Thu May 20 20:47:13 2010 +0200 @@ -41,6 +41,7 @@ from cubicweb.web import dumps from logilab.common.decorators import monkeypatch +from logilab.common.daemon import daemonize from cubicweb import AuthenticationError, ConfigurationError, CW_EVENT_MANAGER from cubicweb.web import Redirect, DirectResponse, StatusResponse, LogOut @@ -49,30 +50,6 @@ from cubicweb.etwist.request import CubicWebTwistedRequestAdapter from cubicweb.etwist.http import HTTPResponse -def daemonize(): - # XXX unix specific - # XXX factorize w/ code in cw.server.server and cw.server.serverctl - # (start-repository command) - # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 - if os.fork(): # launch child and... - return 1 - os.setsid() - if os.fork(): # launch child again. - return 1 - # move to the root to avoit mount pb - os.chdir('/') - # set paranoid umask - os.umask(077) - null = os.open('/dev/null', os.O_RDWR) - for i in range(3): - try: - os.dup2(null, i) - except OSError, e: - if e.errno != errno.EBADF: - raise - os.close(null) - return None - def start_task(interval, func): lc = task.LoopingCall(func) # wait until interval has expired to actually start the task, else we have @@ -423,15 +400,8 @@ raise ConfigurationError("Under windows, you must use the service management " "commands (e.g : 'net start my_instance)'") print 'instance starting in the background' - if daemonize(): + if daemonize(config['pid-file']): return # child process - if config['pid-file']: - # ensure the directory where the pid-file should be set exists (for - # instance /var/run/cubicweb may be deleted on computer restart) - piddir = os.path.dirname(config['pid-file']) - if not os.path.exists(piddir): - os.makedirs(piddir) - file(config['pid-file'], 'w').write(str(os.getpid())) root_resource.init_publisher() # before changing uid if config['uid'] is not None: try: diff -r 25fd74c23f91 -r a64f48dd5fe4 etwist/twconfig.py --- a/etwist/twconfig.py Tue May 18 18:18:08 2010 +0200 +++ b/etwist/twconfig.py Thu May 20 20:47:13 2010 +0200 @@ -39,18 +39,30 @@ options = merge_options(( # ctl configuration + ('port', + {'type' : 'int', + 'default': None, + 'help': 'http server port number (default to 8080)', + 'group': 'web', 'level': 0, + }), + ('max-post-length', + {'type' : 'bytes', + 'default': '100MB', + 'help': 'maximum length of HTTP request. Default to 100 MB.', + 'group': 'web', 'level': 1, + }), + ('profile', + {'type' : 'string', + 'default': None, + 'help': 'profile code and use the specified file to store stats if this option is set', + 'group': 'web', 'level': 3, + }), ('host', {'type' : 'string', 'default': None, 'help': 'host name if not correctly detectable through gethostname', 'group': 'main', 'level': 1, }), - ('port', - {'type' : 'int', - 'default': None, - 'help': 'http server port number (default to 8080)', - 'group': 'main', 'level': 0, - }), ('pid-file', {'type' : 'string', 'default': Method('default_pid_file'), @@ -64,24 +76,12 @@ the repository rather than the user running the command', 'group': 'main', 'level': WebConfiguration.mode == 'system' }), - ('max-post-length', - {'type' : 'bytes', - 'default': '100MB', - 'help': 'maximum length of HTTP request. Default to 100 MB.', - 'group': 'main', 'level': 1, - }), ('session-time', {'type' : 'time', 'default': '30min', 'help': 'session expiration time, default to 30 minutes', 'group': 'main', 'level': 1, }), - ('profile', - {'type' : 'string', - 'default': None, - 'help': 'profile code and use the specified file to store stats if this option is set', - 'group': 'main', 'level': 3, - }), ('pyro-server', {'type' : 'yn', # pyro is only a recommends by default, so don't activate it here diff -r 25fd74c23f91 -r a64f48dd5fe4 server/migractions.py --- a/server/migractions.py Tue May 18 18:18:08 2010 +0200 +++ b/server/migractions.py Thu May 20 20:47:13 2010 +0200 @@ -1200,11 +1200,15 @@ source = self.repo.system_source storage = source.storage(etype, attribute) source.unset_storage(etype, attribute) - rset = self.rqlexec('Any X,A WHERE X is %s, X %s A' - % (etype, attribute), ask_confirm=False) + rset = self.rqlexec('Any X WHERE X is %s' % etype, ask_confirm=False) pb = ProgressBar(len(rset)) for entity in rset.entities(): + # fill cache. Do not fetch that attribute using the global rql query + # since we may exhaust memory doing that.... + getattr(entity, attribute) storage.migrate_entity(entity, attribute) + # remove from entity cache to avoid memory exhaustion + del entity[attribute] pb.update() print source.set_storage(etype, attribute, storage) diff -r 25fd74c23f91 -r a64f48dd5fe4 server/server.py --- a/server/server.py Tue May 18 18:18:08 2010 +0200 +++ b/server/server.py Thu May 20 20:47:13 2010 +0200 @@ -15,9 +15,8 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -"""Pyro RQL server +"""Pyro RQL server""" -""" __docformat__ = "restructuredtext en" import os @@ -26,6 +25,8 @@ import warnings from time import localtime, mktime +from logilab.common.daemon import daemonize + from cubicweb.cwconfig import CubicWebConfiguration from cubicweb.server.repository import Repository @@ -83,7 +84,6 @@ self.quiting = None # event queue self.events = [] - # start repository looping tasks def add_event(self, event): """add an event to the loop""" @@ -103,6 +103,7 @@ def run(self, req_timeout=5.0): """enter the service loop""" + # start repository looping tasks self.repo.start_looping_tasks() while self.quiting is None: try: @@ -130,35 +131,7 @@ signal.signal(signal.SIGINT, lambda x, y, s=self: s.quit()) signal.signal(signal.SIGTERM, lambda x, y, s=self: s.quit()) - def daemonize(self, pid_file=None): - """daemonize the process""" - # fork so the parent can exist - if (os.fork()): - return -1 - # deconnect from tty and create a new session - os.setsid() - # fork again so the parent, (the session group leader), can exit. - # as a non-session group leader, we can never regain a controlling - # terminal. - if (os.fork()): - return -1 - # move to the root to avoit mount pb - os.chdir('/') - # set paranoid umask - os.umask(077) - if pid_file is not None: - # write pid in a file - f = open(pid_file, 'w') - f.write(str(os.getpid())) - f.close() - # filter warnings - warnings.filterwarnings('ignore') - # close standard descriptors - sys.stdin.close() - sys.stdout.close() - sys.stderr.close() - from logging import getLogger from cubicweb import set_log_methods LOGGER = getLogger('cubicweb.reposerver') -set_log_methods(CubicWebConfiguration, LOGGER) +set_log_methods(RepositoryServer, LOGGER) diff -r 25fd74c23f91 -r a64f48dd5fe4 server/serverctl.py --- a/server/serverctl.py Tue May 18 18:18:08 2010 +0200 +++ b/server/serverctl.py Thu May 20 20:47:13 2010 +0200 @@ -525,6 +525,7 @@ ) def run(self, args): + from logilab.common.daemon import daemonize from cubicweb.server.server import RepositoryServer appid = pop_arg(args, msg='No instance specified !') config = ServerConfiguration.config_for(appid) @@ -544,7 +545,7 @@ piddir = os.path.dirname(pidfile) if not os.path.exists(piddir): os.makedirs(piddir) - if not debug and server.daemonize(pidfile) == -1: + if not debug and daemonize(pidfile) == -1: return uid = config['uid'] if uid is not None: diff -r 25fd74c23f91 -r a64f48dd5fe4 server/sources/native.py --- a/server/sources/native.py Tue May 18 18:18:08 2010 +0200 +++ b/server/sources/native.py Thu May 20 20:47:13 2010 +0200 @@ -33,6 +33,7 @@ from datetime import datetime from base64 import b64decode, b64encode from contextlib import contextmanager +from os.path import abspath from logilab.common.compat import any from logilab.common.cache import Cache @@ -264,6 +265,7 @@ if self.dbdriver == 'sqlite' and \ not getattr(repo.config, 'no_sqlite_wrap', False): from cubicweb.server.sources.extlite import ConnectionWrapper + self.dbhelper.dbname = abspath(self.dbhelper.dbname) self.get_connection = lambda: ConnectionWrapper(self) self.check_connection = lambda cnx: cnx def pool_reset(cnx): diff -r 25fd74c23f91 -r a64f48dd5fe4 server/sources/storages.py --- a/server/sources/storages.py Tue May 18 18:18:08 2010 +0200 +++ b/server/sources/storages.py Thu May 20 20:47:13 2010 +0200 @@ -82,7 +82,7 @@ XXX subject to race condition. """ - path = osp.join(dirpath, basename) + path = osp.join(dirpath, basename.replace(osp.sep, '-')) if not osp.isfile(path): return path base, ext = osp.splitext(path) diff -r 25fd74c23f91 -r a64f48dd5fe4 web/form.py --- a/web/form.py Tue May 18 18:18:08 2010 +0200 +++ b/web/form.py Thu May 20 20:47:13 2010 +0200 @@ -80,8 +80,6 @@ __metaclass__ = metafieldsform __registry__ = 'forms' - internal_fields = ('__errorurl',) + controller.NAV_FORM_PARAMETERS - parent_form = None force_session_key = None domid = 'form' diff -r 25fd74c23f91 -r a64f48dd5fe4 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Tue May 18 18:18:08 2010 +0200 +++ b/web/views/basecontrollers.py Thu May 20 20:47:13 2010 +0200 @@ -314,6 +314,9 @@ for name, value in zip(names, values): # remove possible __action_xxx inputs if name.startswith('__action'): + if action is None: + # strip '__action_' to get the actual action name + action = name[9:] continue # form.setdefault(name, []).append(value) if name in form: diff -r 25fd74c23f91 -r a64f48dd5fe4 web/views/forms.py --- a/web/views/forms.py Tue May 18 18:18:08 2010 +0200 +++ b/web/views/forms.py Thu May 20 20:47:13 2010 +0200 @@ -222,8 +222,6 @@ __regid__ = 'base' __select__ = (match_kwargs('entity') | (one_line_rset() & non_final_entity())) - - internal_fields = FieldsForm.internal_fields + ('__type', 'eid', '__maineid') domid = 'entityForm' @iclassmethod diff -r 25fd74c23f91 -r a64f48dd5fe4 web/webconfig.py --- a/web/webconfig.py Tue May 18 18:18:08 2010 +0200 +++ b/web/webconfig.py Thu May 20 20:47:13 2010 +0200 @@ -86,20 +86,20 @@ {'type' : 'string', 'default': None, 'help': 'login of the CubicWeb user account to use for anonymous user (if you want to allow anonymous)', - 'group': 'main', 'level': 1, + 'group': 'web', 'level': 1, }), ('anonymous-password', {'type' : 'string', 'default': None, 'help': 'password of the CubicWeb user account to use for anonymous user, ' 'if anonymous-user is set', - 'group': 'main', 'level': 1, + 'group': 'web', 'level': 1, }), ('query-log-file', {'type' : 'string', 'default': None, 'help': 'web instance query log file', - 'group': 'main', 'level': 3, + 'group': 'web', 'level': 3, }), # web configuration ('https-url',