summaryrefslogtreecommitdiff
path: root/mailman/bin/master.py
diff options
context:
space:
mode:
Diffstat (limited to 'mailman/bin/master.py')
-rw-r--r--mailman/bin/master.py62
1 files changed, 42 insertions, 20 deletions
diff --git a/mailman/bin/master.py b/mailman/bin/master.py
index 1c45e04f8..d3676629d 100644
--- a/mailman/bin/master.py
+++ b/mailman/bin/master.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2008 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
@@ -32,12 +32,13 @@ import socket
import logging
from datetime import timedelta
+from lazr.config import as_boolean
from locknix import lockfile
from munepy import Enum
from mailman import Defaults
-from mailman import loginit
-from mailman.configuration import config
+from mailman.config import config
+from mailman.core.logging import reopen
from mailman.i18n import _
from mailman.options import Options
@@ -237,7 +238,7 @@ class Loop:
signal.alarm(int(Defaults.days(1)))
# SIGHUP tells the qrunners to close and reopen their log files.
def sighup_handler(signum, frame):
- loginit.reopen()
+ reopen()
for pid in self._kids:
os.kill(pid, signal.SIGHUP)
log.info('Master watcher caught SIGHUP. Re-opening log files.')
@@ -269,7 +270,9 @@ class Loop:
:param spec: A queue runner spec, in a format acceptable to
bin/qrunner's --runner argument, e.g. name:slice:count
+ :type spec: string
:return: The process id of the child queue runner.
+ :rtype: int
"""
pid = os.fork()
if pid:
@@ -292,26 +295,43 @@ class Loop:
# We should never get here.
raise RuntimeError('os.execl() failed')
- def start_qrunners(self, qrunners=None):
+ def start_qrunners(self, qrunner_names=None):
"""Start all the configured qrunners.
:param qrunners: If given, a sequence of queue runner names to start.
If not given, this sequence is taken from the configuration file.
+ :type qrunners: a sequence of strings
"""
- if not qrunners:
- spec_parts = config.qrunners.items()
- else:
- spec_parts = []
- for qrname in qrunners:
- if '.' in qrname:
- spec_parts.append((qrname, 1))
- else:
- spec_parts.append((config.qrunner_shortcuts[qrname], 1))
- for qrname, count in spec_parts:
+ if not qrunner_names:
+ qrunner_names = []
+ for qrunner_config in config.qrunner_configs:
+ # Strip off the 'qrunner.' prefix.
+ assert qrunner_config.name.startswith('qrunner.'), (
+ 'Unexpected qrunner configuration section name: %s',
+ qrunner_config.name)
+ qrunner_names.append(qrunner_config.name[8:])
+ # For each qrunner we want to start, find their config section, which
+ # will tell us the name of the class to instantiate, along with the
+ # number of hash space slices to manage.
+ for name in qrunner_names:
+ section_name = 'qrunner.' + name
+ # Let AttributeError propagate.
+ qrunner_config = getattr(config, section_name)
+ if not as_boolean(qrunner_config.start):
+ continue
+ package, class_name = qrunner_config['class'].rsplit(DOT, 1)
+ __import__(package)
+ # Let AttributeError propagate.
+ class_ = getattr(sys.modules[package], class_name)
+ # Find out how many qrunners to instantiate. This must be a power
+ # of 2.
+ count = int(qrunner_config.instances)
+ assert (count & (count - 1)) == 0, (
+ 'Queue runner "%s", not a power of 2: %s', name, count)
for slice_number in range(count):
# qrunner name, slice #, # of slices, restart count
- info = (qrname, slice_number, count, 0)
- spec = '%s:%d:%d' % (qrname, slice_number, count)
+ info = (name, slice_number, count, 0)
+ spec = '%s:%d:%d' % (name, slice_number, count)
pid = self._start_runner(spec)
log = logging.getLogger('mailman.qrunner')
log.debug('[%d] %s', pid, spec)
@@ -349,12 +369,14 @@ class Loop:
# command line switch was not given. This lets us better handle
# runaway restarts (e.g. if the subprocess had a syntax error!)
qrname, slice_number, count, restarts = self._kids.pop(pid)
+ config_name = 'qrunner.' + qrname
restart = False
if why == signal.SIGUSR1 and self._restartable:
restart = True
# Have we hit the maximum number of restarts?
restarts += 1
- if restarts > config.MAX_RESTARTS:
+ max_restarts = int(getattr(config, config_name).max_restarts)
+ if restarts > max_restarts:
restart = False
# Are we permanently non-restartable?
log.debug("""\
@@ -363,10 +385,10 @@ Master detected subprocess exit
pid, why, qrname, slice_number + 1, count,
('[restarting]' if restart else ''))
# See if we've reached the maximum number of allowable restarts
- if restarts > config.MAX_RESTARTS:
+ if restarts > max_restarts:
log.info("""\
qrunner %s reached maximum restart limit of %d, not restarting.""",
- qrname, config.MAX_RESTARTS)
+ qrname, max_restarts)
# Now perhaps restart the process unless it exited with a
# SIGTERM or we aren't restarting.
if restart: