backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 20 May 2010 20:47:13 +0200
changeset 5555 a64f48dd5fe4
parent 5545 25fd74c23f91 (current diff)
parent 5554 9b7bdbfee68b (diff)
child 5556 9ab2b4c74baf
backport stable
__pkginfo__.py
debian/control
devtools/__init__.py
etwist/server.py
server/serverctl.py
web/views/basecontrollers.py
web/webconfig.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',
--- 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
--- 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
--- 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:
--- 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
--- 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)
--- 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 <http://www.gnu.org/licenses/>.
-"""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)
--- 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:
--- 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):
--- 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)
--- 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'
--- 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:
--- 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
--- 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',