[CalendarServer-changes] [3443] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Dec 2 14:50:48 PST 2008


Revision: 3443
          http://trac.macosforge.org/projects/calendarserver/changeset/3443
Author:   wsanchez at apple.com
Date:     2008-12-02 14:50:47 -0800 (Tue, 02 Dec 2008)
Log Message:
-----------
Merge cluster.py into tap/caldav.py

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tap/caldav.py

Removed Paths:
-------------
    CalendarServer/trunk/twistedcaldav/cluster.py

Modified: CalendarServer/trunk/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/caldav.py	2008-12-02 22:17:03 UTC (rev 3442)
+++ CalendarServer/trunk/calendarserver/tap/caldav.py	2008-12-02 22:50:47 UTC (rev 3443)
@@ -21,7 +21,9 @@
 ]
 
 import os
+import sys
 
+from tempfile import mkstemp
 from subprocess import Popen, PIPE
 from pwd import getpwnam
 from grp import getgrnam
@@ -29,14 +31,17 @@
 
 from zope.interface import implements
 
-from twisted.internet.address import IPv4Address
 from twisted.python.log import FileLogObserver
 from twisted.python.usage import Options, UsageError
 from twisted.python.reflect import namedClass
-from twisted.application.internet import TCPServer, SSLServer
-from twisted.application.service import MultiService, IServiceMaker
 from twisted.plugin import IPlugin
+from twisted.internet.reactor import callLater
+from twisted.internet.process import ProcessExitedAlready
+from twisted.internet.address import IPv4Address
+from twisted.application.internet import TCPServer, SSLServer, UNIXServer
+from twisted.application.service import Service, MultiService, IServiceMaker
 from twisted.scripts.mktap import getid
+from twisted.runner import procmon
 from twisted.cred.portal import Portal
 from twisted.web2.dav import auth
 from twisted.web2.auth.basic import BasicCredentialFactory
@@ -45,10 +50,8 @@
 from twext.internet.ssl import ChainingOpenSSLContextFactory
 
 from twistedcaldav.log import Logger, logLevelForNamespace, setLogLevelForNamespace
-from twistedcaldav.accesslog import DirectoryLogWrapperResource
-from twistedcaldav.accesslog import RotatingFileAccessLoggingObserver
-from twistedcaldav.accesslog import AMPCommonAccessLoggingObserver
-from twistedcaldav.cluster import makeService_Combined, makeService_Master
+from twistedcaldav.accesslog import DirectoryLogWrapperResource, RotatingFileAccessLoggingObserver
+from twistedcaldav.accesslog import AMPLoggingFactory, AMPCommonAccessLoggingObserver
 from twistedcaldav.config import config, defaultConfig, defaultConfigFile, ConfigurationError
 from twistedcaldav.root import RootResource
 from twistedcaldav.resource import CalDAVResource
@@ -67,6 +70,7 @@
 from twistedcaldav.pdmonster import PDClientAddressWrapper
 from twistedcaldav import memcachepool
 from twistedcaldav.notify import installNotificationClient
+from twistedcaldav.util import getNCPU
 
 log = Logger()
 
@@ -303,6 +307,63 @@
     imipResourceClass            = IMIPInboxResource
     timezoneServiceResourceClass = TimezoneServiceFile
 
+    def makeService(self, options):
+
+        # Now do any on disk upgrades we might need.
+        UpgradeTheServer.doUpgrade()
+
+        serverType = config.ProcessType
+
+        serviceMethod = getattr(self, "makeService_%s" % (serverType,), None)
+
+        if not serviceMethod:
+            raise UsageError(
+                "Unknown server type %s. "
+                "Please choose: Master, Slave, Single or Combined"
+                % (serverType,)
+            )
+        else:
+            service = serviceMethod(options)
+
+            #
+            # Note: if there is a stopped process in the same session
+            # as the calendar server and the calendar server is the
+            # group leader then when twistd forks to drop privileges a
+            # SIGHUP may be sent by the kernel, which can cause the
+            # process to exit. This SIGHUP should be, at a minimum,
+            # ignored.
+            #
+
+            def location(frame):
+                if frame is None:
+                    return "Unknown"
+                else:
+                    return "%s: %s" % (frame.f_code.co_name, frame.f_lineno)
+
+            import signal
+            def sighup_handler(num, frame):
+                log.info("SIGHUP recieved at %s" % (location(frame),))
+
+                # Reload the config file
+                config.reload()
+
+                # If combined service send signal to all caldavd children
+                if serverType == "Combined":
+                    service.processMonitor.signalAll(signal.SIGHUP, "caldav")
+
+                # FIXME: There is no memcachepool.getCachePool
+                #   Also, better option is probably to add a hook to
+                #   the config object instead of doing things here.
+                #log.info("Suggesting new max clients for memcache.")
+                #memcachepool.getCachePool().suggestMaxClients(
+                #    config.Memcached.MaxClients
+                #)
+
+            signal.signal(signal.SIGHUP, sighup_handler)
+
+            return service
+
+
     def makeService_Slave(self, options):
         #
         # Change default log level to "info" as its useful to have
@@ -618,67 +679,417 @@
 
         return service
 
-    makeService_Combined = makeService_Combined
-    makeService_Master   = makeService_Master
     makeService_Single   = makeService_Slave
 
-    def makeService(self, options):
+    def makeService_Combined(self, options):
+        s = MultiService()
+        monitor = DelayedStartupProcessMonitor()
+        monitor.setServiceParent(s)
+        s.processMonitor = monitor
 
-        # Now do any on disk upgrades we might need.
-        UpgradeTheServer.doUpgrade()
+        parentEnv = {
+            "PATH": os.environ.get("PATH", ""),
+            "PYTHONPATH": os.environ.get("PYTHONPATH", ""),
+        }
 
-        serverType = config.ProcessType
+        hosts = []
+        sslHosts = []
 
-        serviceMethod = getattr(self, "makeService_%s" % (serverType,), None)
+        port = [config.HTTPPort,]
+        sslPort = [config.SSLPort,]
 
-        if not serviceMethod:
-            raise UsageError(
-                "Unknown server type %s. "
-                "Please choose: Master, Slave, Single or Combined"
-                % (serverType,)
+        bindAddress = ["127.0.0.1"]
+
+        #
+        # Attempt to calculate the number of processes to use 1 per processor
+        #
+        if config.MultiProcess.ProcessCount == 0:
+            try:
+                cpuCount = getNCPU()
+            except NotImplementedError, e:
+                error = str(e)
+            else:
+                if cpuCount > 0:
+                    error = None
+                else:
+                    error = "No processors detected, which is difficult to believe."
+
+            if error is None:
+                log.msg(
+                    "%d processors found, configuring %d processes."
+                    % (cpuCount, cpuCount)
+                )
+            else:
+                log.err("Could not autodetect number of CPUs: %s" % (error,))
+                log.err("Assuming one CPU, configuring one process.")
+                cpuCount = 1
+
+            config.MultiProcess.ProcessCount = cpuCount
+
+        if config.MultiProcess.ProcessCount > 1:
+            if config.BindHTTPPorts:
+                port = [list(reversed(config.BindHTTPPorts))[0]]
+
+            if config.BindSSLPorts:
+                sslPort = [list(reversed(config.BindSSLPorts))[0]]
+
+        elif config.MultiProcess.ProcessCount == 1:
+            if config.BindHTTPPorts:
+                port = config.BindHTTPPorts
+
+            if config.BindSSLPorts:
+                sslPort = config.BindSSLPorts
+
+        if port[0] == 0:
+            port = None
+
+        if sslPort[0] == 0:
+            sslPort = None
+
+        # If the load balancer isn"t enabled, or if we only have one process
+        # We listen directly on the interfaces.
+
+        if (
+            not config.MultiProcess.LoadBalancer.Enabled or
+            config.MultiProcess.ProcessCount == 1
+        ):
+            bindAddress = config.BindAddresses
+
+        for p in xrange(0, config.MultiProcess.ProcessCount):
+            if config.MultiProcess.ProcessCount > 1:
+                if port is not None:
+                    port = [port[0] + 1]
+
+                if sslPort is not None:
+                    sslPort = [sslPort[0] + 1]
+
+            process = TwistdSlaveProcess(
+                config.Twisted.twistd,
+                self.tapname,
+                options["config"],
+                bindAddress,
+                port,
+                sslPort
             )
-        else:
-            service = serviceMethod(options)
 
-            #
-            # Note: if there is a stopped process in the same session
-            # as the calendar server and the calendar server is the
-            # group leader then when twistd forks to drop privileges a
-            # SIGHUP may be sent by the kernel, which can cause the
-            # process to exit. This SIGHUP should be, at a minimum,
-            # ignored.
-            #
+            monitor.addProcess(
+                process.getName(),
+                process.getCommandLine(),
+                env=parentEnv
+            )
 
-            def location(frame):
-                if frame is None:
-                    return "Unknown"
-                else:
-                    return "%s: %s" % (frame.f_code.co_name, frame.f_lineno)
+            if config.HTTPPort:
+                hosts.append(process.getHostLine())
 
-            import signal
-            def sighup_handler(num, frame):
-                log.info("SIGHUP recieved at %s" % (location(frame),))
+            if config.SSLPort:
+                sslHosts.append(process.getHostLine(ssl=True))
 
-                # Reload the config file
-                config.reload()
+        #
+        # Set up pydirector config file.
+        #
+        if (config.MultiProcess.LoadBalancer.Enabled and
+            config.MultiProcess.ProcessCount > 1):
+            services = []
 
-                # If combined service send signal to all caldavd children
-                if serverType == "Combined":
-                    service.processMonitor.signalAll(signal.SIGHUP, "caldav")
+            if not config.BindAddresses:
+                config.BindAddresses = [""]
 
-                # FIXME: There is no memcachepool.getCachePool
-                #   Also, better option is probably to add a hook to
-                #   the config object instead of doing things here.
-                #log.info("Suggesting new max clients for memcache.")
-                #memcachepool.getCachePool().suggestMaxClients(
-                #    config.Memcached.MaxClients
-                #)
+            scheduler_map = {
+                "LeastConnections": "leastconns",
+                "RoundRobin": "roundrobin",
+                "LeastConnectionsAndRoundRobin": "leastconnsrr",
+            }
 
-            signal.signal(signal.SIGHUP, sighup_handler)
+            for bindAddress in config.BindAddresses:
+                httpListeners = []
+                sslListeners = []
 
-            return service
+                httpPorts = config.BindHTTPPorts
+                if not httpPorts:
+                    if config.HTTPPort != 0:
+                        httpPorts = (config.HTTPPort,)
 
+                sslPorts = config.BindSSLPorts
+                if not sslPorts:
+                    if config.SSLPort != 0:
+                        sslPorts = (config.SSLPort,)
 
+                for ports, listeners in (
+                    (httpPorts, httpListeners),
+                    (sslPorts, sslListeners)
+                ):
+                    for port in ports:
+                        listeners.append(
+                            """<listen ip="%s:%s" />""" % (bindAddress, port)
+                        )
+
+                scheduler = config.MultiProcess.LoadBalancer.Scheduler
+
+                pydirServiceTemplate = (
+                    """<service name="%(name)s">"""
+                    """%(listeningInterfaces)s"""
+                    """<group name="main" scheduler="%(scheduler)s">%(hosts)s</group>"""
+                    """<enable group="main" />"""
+                    """</service>"""
+                )
+
+                if httpPorts:
+                    services.append(
+                        pydirServiceTemplate % {
+                            "name": "http",
+                            "listeningInterfaces": "\n".join(httpListeners),
+                            "scheduler": scheduler_map[scheduler],
+                            "hosts": "\n".join(hosts)
+                        }
+                    )
+
+                if sslPorts:
+                    services.append(
+                        pydirServiceTemplate % {
+                            "name": "https",
+                            "listeningInterfaces": "\n".join(sslListeners),
+                            "scheduler": scheduler_map[scheduler],
+                            "hosts": "\n".join(sslHosts),
+                        }
+                    )
+
+            pdconfig = """<pdconfig>%s<control socket="%s" /></pdconfig>""" % (
+                "\n".join(services), config.PythonDirector.ControlSocket,
+            )
+
+            fd, fname = mkstemp(prefix="pydir")
+            os.write(fd, pdconfig)
+            os.close(fd)
+
+            log.msg("Adding pydirector service with configuration: %s" % (fname,))
+
+            monitor.addProcess(
+                "pydir",
+                [sys.executable, config.PythonDirector.pydir, fname],
+                env=parentEnv,
+            )
+
+        if config.Memcached.ServerEnabled:
+            log.msg("Adding memcached service")
+
+            memcachedArgv = [
+                config.Memcached.memcached,
+                "-p", str(config.Memcached.Port),
+                "-l", config.Memcached.BindAddress,
+            ]
+
+            if config.Memcached.MaxMemory is not 0:
+                memcachedArgv.extend(["-m", str(config.Memcached.MaxMemory)])
+
+            if config.UserName:
+                memcachedArgv.extend(["-u", config.UserName])
+
+            memcachedArgv.extend(config.Memcached.Options)
+
+            monitor.addProcess("memcached", memcachedArgv, env=parentEnv)
+
+        if (
+            config.Notifications.Enabled and
+            config.Notifications.InternalNotificationHost == "localhost"
+        ):
+            log.msg("Adding notification service")
+
+            notificationsArgv = [
+                sys.executable,
+                config.Twisted.twistd,
+                "-n", "caldav_notifier",
+                "-f", options["config"],
+            ]
+            monitor.addProcess("notifications", notificationsArgv, env=parentEnv)
+
+        if (
+            config.Scheduling.iMIP.Enabled and
+            config.Scheduling.iMIP.MailGatewayServer == "localhost"
+        ):
+            log.msg("Adding mail gateway service")
+
+            mailGatewayArgv = [
+                sys.executable,
+                config.Twisted.twistd,
+                "-n", "caldav_mailgateway",
+                "-f", options["config"],
+            ]
+            monitor.addProcess("mailgateway", mailGatewayArgv, env=parentEnv)
+
+
+        logger = AMPLoggingFactory(
+            RotatingFileAccessLoggingObserver(config.AccessLogFile)
+        )
+
+        loggingService = UNIXServer(config.ControlSocket, logger)
+
+        loggingService.setServiceParent(s)
+
+        return s
+
+    def makeService_Master(self, options):
+        service = procmon.ProcessMonitor()
+
+        parentEnv = {"PYTHONPATH": os.environ.get("PYTHONPATH", "")}
+
+        log.msg("Adding pydirector service with configuration: %s"
+                % (config.PythonDirector.ConfigFile,))
+
+        service.addProcess(
+            "pydir",
+            [
+                sys.executable,
+                config.PythonDirector.pydir,
+                config.PythonDirector.ConfigFile
+            ],
+            env=parentEnv
+        )
+
+        return service
+
+
+class TwistdSlaveProcess(object):
+    prefix = "caldav"
+
+    def __init__(self, twistd, tapname, configFile, interfaces, port, sslPort):
+        self.twistd = twistd
+
+        self.tapname = tapname
+
+        self.configFile = configFile
+
+        self.ports = port
+        self.sslPorts = sslPort
+
+        self.interfaces = interfaces
+
+    def getName(self):
+        if self.ports is not None:
+            return "%s-%s" % (self.prefix, self.ports[0])
+        elif self.sslPorts is not None:
+            return "%s-%s" % (self.prefix, self.sslPorts[0])
+
+        raise ConfigurationError(
+            "Can't create TwistdSlaveProcess without a TCP Port"
+        )
+
+    def getCommandLine(self):
+        args = [sys.executable, self.twistd]
+
+        if config.UserName:
+            args.extend(("-u", config.UserName))
+
+        if config.GroupName:
+            args.extend(("-g", config.GroupName))
+
+        if config.Profiling.Enabled:
+            args.append(
+                "--profile=%s/%s.pstats"
+                % (config.Profiling.BaseDirectory, self.getName())
+            )
+            args.extend(("--savestats", "--nothotshot"))
+
+        args.extend([
+            "--reactor=%s" % (config.Twisted.reactor,),
+            "-n", self.tapname,
+            "-f", self.configFile,
+            "-o", "ProcessType=Slave",
+            "-o", "BindAddresses=%s" % (",".join(self.interfaces),),
+            "-o", "PIDFile=None",
+            "-o", "ErrorLogFile=None",
+            "-o", "MultiProcess/ProcessCount=%d"
+                  % (config.MultiProcess.ProcessCount,)
+        ])
+
+        if config.Memcached.ServerEnabled:
+            args.extend(["-o", "Memcached/ClientEnabled=True"])
+
+        if self.ports:
+            args.extend([
+                "-o", "BindHTTPPorts=%s" % (",".join(map(str, self.ports)),)
+            ])
+
+        if self.sslPorts:
+            args.extend([
+                "-o", "BindSSLPorts=%s" % (",".join(map(str, self.sslPorts)),)
+            ])
+
+        return args
+
+    def getHostLine(self, ssl=False):
+        name = self.getName()
+        port = None
+
+        if self.ports is not None:
+            port = self.ports
+
+        if ssl and self.sslPorts is not None:
+            port = self.sslPorts
+
+        if port is None:
+            raise ConfigurationError("Can not add a host without a port")
+
+        return """<host name="%s" ip="127.0.0.1:%s" />""" % (name, port[0])
+
+
+class DelayedStartupProcessMonitor(procmon.ProcessMonitor):
+    def startService(self):
+        Service.startService(self)
+        self.active = 1
+
+        delay = 0
+
+        if config.MultiProcess.StaggeredStartup.Enabled:
+            delay_interval = config.MultiProcess.StaggeredStartup.Interval
+        else:
+            delay_interval = 0
+
+        for name in self.processes.keys():
+            if name.startswith("caldav"):
+                when = delay
+                delay += delay_interval
+            else:
+                when = 0
+            callLater(when, self.startProcess, name)
+
+        self.consistency = callLater(
+            self.consistencyDelay,
+            self._checkConsistency
+        )
+
+    def signalAll(self, signal, startswithname=None):
+        """
+        Send a signal to all child processes.
+
+        @param signal: the signal to send
+        @type signal: C{int}
+        @param startswithname: is set only signal those processes
+            whose name starts with this string
+        @type signal: C{str}
+        """
+        for name in self.processes.keys():
+            if startswithname is None or name.startswith(startswithname):
+                self.signalProcess(signal, name)
+
+    def signalProcess(self, signal, name):
+        """
+        Send a signal to each monitored process
+        
+        @param signal: the signal to send
+        @type signal: C{int}
+        @param startswithname: is set only signal those processes
+            whose name starts with this string
+        @type signal: C{str}
+        """
+        if not self.protocols.has_key(name):
+            return
+        proc = self.protocols[name].transport
+        try:
+            proc.signalProcess(signal)
+        except ProcessExitedAlready:
+            pass
+
+
 def getSSLPassphrase(*ignored):
 
     if not config.SSLPrivateKey:

Deleted: CalendarServer/trunk/twistedcaldav/cluster.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/cluster.py	2008-12-02 22:17:03 UTC (rev 3442)
+++ CalendarServer/trunk/twistedcaldav/cluster.py	2008-12-02 22:50:47 UTC (rev 3443)
@@ -1,462 +0,0 @@
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import os
-import sys
-import tempfile
-
-from twisted.runner import procmon
-from twisted.application import internet, service
-from twisted.internet import reactor, process
-
-from twistedcaldav.accesslog import AMPLoggingFactory, RotatingFileAccessLoggingObserver
-from twistedcaldav.config import config, ConfigurationError
-from twistedcaldav.util import getNCPU
-from twistedcaldav.log import Logger
-
-log = Logger()
-
-serviceTemplate = """
-    <service name="%(name)s">
-        %(listeningInterfaces)s
-    <group name="main" scheduler="%(scheduler)s">
-        %(hosts)s
-        </group>
-        <enable group="main" />
-    </service>
-"""
-
-configTemplate = """
-<pdconfig>
-    %(services)s
-    <control socket="%(controlSocket)s" />
-</pdconfig>
-"""
-
-listenTemplate = '<listen ip="%(bindAddress)s:%(port)s" />'
-
-hostTemplate = '<host name="%(name)s" ip="%(bindAddress)s:%(port)s" />'
-
-
-class TwistdSlaveProcess(object):
-    prefix = "caldav"
-
-    def __init__(self, twistd, tapname, configFile, interfaces, port, sslPort):
-        self.twistd = twistd
-
-        self.tapname = tapname
-
-        self.configFile = configFile
-
-        self.ports = port
-        self.sslPorts = sslPort
-
-        self.interfaces = interfaces
-
-    def getName(self):
-        if self.ports is not None:
-            return "%s-%s" % (self.prefix, self.ports[0])
-        elif self.sslPorts is not None:
-            return "%s-%s" % (self.prefix, self.sslPorts[0])
-
-        raise ConfigurationError(
-            "Can't create TwistdSlaveProcess without a TCP Port"
-        )
-
-    def getCommandLine(self):
-        args = [sys.executable, self.twistd]
-
-        if config.UserName:
-            args.extend(("-u", config.UserName))
-
-        if config.GroupName:
-            args.extend(("-g", config.GroupName))
-
-        if config.Profiling.Enabled:
-            args.append(
-                "--profile=%s/%s.pstats"
-                % (config.Profiling.BaseDirectory, self.getName())
-            )
-            args.extend(("--savestats", "--nothotshot"))
-
-        args.extend([
-            "--reactor=%s" % (config.Twisted.reactor,),
-            "-n", self.tapname,
-            "-f", self.configFile,
-            "-o", "ProcessType=Slave",
-            "-o", "BindAddresses=%s" % (",".join(self.interfaces),),
-            "-o", "PIDFile=None",
-            "-o", "ErrorLogFile=None",
-            "-o", "MultiProcess/ProcessCount=%d"
-                  % (config.MultiProcess.ProcessCount,)
-        ])
-
-        if config.Memcached.ServerEnabled:
-            args.extend(["-o", "Memcached/ClientEnabled=True"])
-
-        if self.ports:
-            args.extend([
-                "-o", "BindHTTPPorts=%s" % (",".join(map(str, self.ports)),)
-            ])
-
-        if self.sslPorts:
-            args.extend([
-                "-o", "BindSSLPorts=%s" % (",".join(map(str, self.sslPorts)),)
-            ])
-
-        return args
-
-    def getHostLine(self, ssl=False):
-        name = self.getName()
-        port = None
-
-        if self.ports is not None:
-            port = self.ports
-
-        if ssl and self.sslPorts is not None:
-            port = self.sslPorts
-
-        if port is None:
-            raise ConfigurationError("Can not add a host without a port")
-
-        return hostTemplate % {
-            "name": name,
-            "port": port[0],
-            "bindAddress": "127.0.0.1"
-        }
-
-
-class DelayedStartupProcessMonitor(procmon.ProcessMonitor):
-
-    def startService(self):
-        service.Service.startService(self)
-        self.active = 1
-
-        delay = 0
-
-        if config.MultiProcess.StaggeredStartup.Enabled:
-            delay_interval = config.MultiProcess.StaggeredStartup.Interval
-        else:
-            delay_interval = 0
-
-        for name in self.processes.keys():
-            if name.startswith("caldav"):
-                when = delay
-                delay += delay_interval
-            else:
-                when = 0
-            reactor.callLater(when, self.startProcess, name)
-
-        self.consistency = reactor.callLater(
-            self.consistencyDelay,
-            self._checkConsistency
-        )
-
-    def signalAll(self, signal, startswithname=None):
-        """
-        Send a signal to all child processes.
-
-        @param signal: the signal to send
-        @type signal: C{int}
-        @param startswithname: is set only signal those processes
-            whose name starts with this string
-        @type signal: C{str}
-        """
-        for name in self.processes.keys():
-            if startswithname is None or name.startswith(startswithname):
-                self.signalProcess(signal, name)
-
-    def signalProcess(self, signal, name):
-        """
-        Send a signal to each monitored process
-        
-        @param signal: the signal to send
-        @type signal: C{int}
-        @param startswithname: is set only signal those processes
-            whose name starts with this string
-        @type signal: C{str}
-        """
-        if not self.protocols.has_key(name):
-            return
-        proc = self.protocols[name].transport
-        try:
-            proc.signalProcess(signal)
-        except process.ProcessExitedAlready:
-            pass
-
-def makeService_Combined(self, options):
-    s = service.MultiService()
-    monitor = DelayedStartupProcessMonitor()
-    monitor.setServiceParent(s)
-    s.processMonitor = monitor
-
-    parentEnv = {
-        "PATH": os.environ.get("PATH", ""),
-        "PYTHONPATH": os.environ.get("PYTHONPATH", ""),
-    }
-
-    hosts = []
-    sslHosts = []
-
-    port = [config.HTTPPort,]
-    sslPort = [config.SSLPort,]
-
-    bindAddress = ["127.0.0.1"]
-
-    #
-    # Attempt to calculate the number of processes to use 1 per processor
-    #
-    if config.MultiProcess.ProcessCount == 0:
-        try:
-            cpuCount = getNCPU()
-        except NotImplementedError, e:
-            error = str(e)
-        else:
-            if cpuCount > 0:
-                error = None
-            else:
-                error = "No processors detected, which is difficult to believe."
-
-        if error is None:
-            log.msg(
-                "%d processors found, configuring %d processes."
-                % (cpuCount, cpuCount)
-            )
-        else:
-            log.err("Could not autodetect number of CPUs: %s" % (error,))
-            log.err("Assuming one CPU, configuring one process.")
-            cpuCount = 1
-
-        config.MultiProcess.ProcessCount = cpuCount
-
-    if config.MultiProcess.ProcessCount > 1:
-        if config.BindHTTPPorts:
-            port = [list(reversed(config.BindHTTPPorts))[0]]
-
-        if config.BindSSLPorts:
-            sslPort = [list(reversed(config.BindSSLPorts))[0]]
-
-    elif config.MultiProcess.ProcessCount == 1:
-        if config.BindHTTPPorts:
-            port = config.BindHTTPPorts
-
-        if config.BindSSLPorts:
-            sslPort = config.BindSSLPorts
-
-    if port[0] == 0:
-        port = None
-
-    if sslPort[0] == 0:
-        sslPort = None
-
-    # If the load balancer isn"t enabled, or if we only have one process
-    # We listen directly on the interfaces.
-
-    if (
-        not config.MultiProcess.LoadBalancer.Enabled or
-        config.MultiProcess.ProcessCount == 1
-    ):
-        bindAddress = config.BindAddresses
-
-    for p in xrange(0, config.MultiProcess.ProcessCount):
-        if config.MultiProcess.ProcessCount > 1:
-            if port is not None:
-                port = [port[0] + 1]
-
-            if sslPort is not None:
-                sslPort = [sslPort[0] + 1]
-
-        process = TwistdSlaveProcess(
-            config.Twisted.twistd,
-            self.tapname,
-            options["config"],
-            bindAddress,
-            port,
-            sslPort
-        )
-
-        monitor.addProcess(
-            process.getName(),
-            process.getCommandLine(),
-            env=parentEnv
-        )
-
-        if config.HTTPPort:
-            hosts.append(process.getHostLine())
-
-        if config.SSLPort:
-            sslHosts.append(process.getHostLine(ssl=True))
-
-    #
-    # Set up pydirector config file.
-    #
-    if (config.MultiProcess.LoadBalancer.Enabled and
-        config.MultiProcess.ProcessCount > 1):
-        services = []
-
-        if not config.BindAddresses:
-            config.BindAddresses = [""]
-
-        scheduler_map = {
-            "LeastConnections": "leastconns",
-            "RoundRobin": "roundrobin",
-            "LeastConnectionsAndRoundRobin": "leastconnsrr",
-        }
-
-        for bindAddress in config.BindAddresses:
-            httpListeners = []
-            sslListeners = []
-
-            httpPorts = config.BindHTTPPorts
-            if not httpPorts:
-                if config.HTTPPort != 0:
-                    httpPorts = (config.HTTPPort,)
-
-            sslPorts = config.BindSSLPorts
-            if not sslPorts:
-                if config.SSLPort != 0:
-                    sslPorts = (config.SSLPort,)
-
-            for ports, listeners in (
-                (httpPorts, httpListeners),
-                (sslPorts, sslListeners)
-            ):
-                for port in ports:
-                    listeners.append(
-                        listenTemplate % {
-                            "bindAddress": bindAddress,
-                            "port": port
-                        }
-                    )
-
-            scheduler = config.MultiProcess.LoadBalancer.Scheduler
-
-            if httpPorts:
-                services.append(
-                    serviceTemplate % {
-                        "name": "http",
-                        "listeningInterfaces": "\n".join(httpListeners),
-                        "bindAddress": bindAddress,
-                        "scheduler": scheduler_map[scheduler],
-                        "hosts": "\n".join(hosts)
-                    }
-                )
-
-            if sslPorts:
-                services.append(
-                    serviceTemplate % {
-                        "name": "https",
-                        "listeningInterfaces": "\n".join(sslListeners),
-                        "bindAddress": bindAddress,
-                        "scheduler": scheduler_map[scheduler],
-                        "hosts": "\n".join(sslHosts),
-                    }
-                )
-
-        pdconfig = configTemplate % {
-            "services": "\n".join(services),
-            "controlSocket": config.PythonDirector.ControlSocket,
-        }
-
-        fd, fname = tempfile.mkstemp(prefix="pydir")
-        os.write(fd, pdconfig)
-        os.close(fd)
-
-        log.msg("Adding pydirector service with configuration: %s" % (fname,))
-
-        monitor.addProcess(
-            "pydir",
-            [sys.executable, config.PythonDirector.pydir, fname],
-            env=parentEnv,
-        )
-
-    if config.Memcached.ServerEnabled:
-        log.msg("Adding memcached service")
-
-        memcachedArgv = [
-            config.Memcached.memcached,
-            "-p", str(config.Memcached.Port),
-            "-l", config.Memcached.BindAddress,
-        ]
-
-        if config.Memcached.MaxMemory is not 0:
-            memcachedArgv.extend(["-m", str(config.Memcached.MaxMemory)])
-
-        if config.UserName:
-            memcachedArgv.extend(["-u", config.UserName])
-
-        memcachedArgv.extend(config.Memcached.Options)
-
-        monitor.addProcess("memcached", memcachedArgv, env=parentEnv)
-
-    if (
-        config.Notifications.Enabled and
-        config.Notifications.InternalNotificationHost == "localhost"
-    ):
-        log.msg("Adding notification service")
-
-        notificationsArgv = [
-            sys.executable,
-            config.Twisted.twistd,
-            "-n", "caldav_notifier",
-            "-f", options["config"],
-        ]
-        monitor.addProcess("notifications", notificationsArgv, env=parentEnv)
-
-    if (
-        config.Scheduling.iMIP.Enabled and
-        config.Scheduling.iMIP.MailGatewayServer == "localhost"
-    ):
-        log.msg("Adding mail gateway service")
-
-        mailGatewayArgv = [
-            sys.executable,
-            config.Twisted.twistd,
-            "-n", "caldav_mailgateway",
-            "-f", options["config"],
-        ]
-        monitor.addProcess("mailgateway", mailGatewayArgv, env=parentEnv)
-
-
-    logger = AMPLoggingFactory(
-        RotatingFileAccessLoggingObserver(config.AccessLogFile)
-    )
-
-    loggingService = internet.UNIXServer(config.ControlSocket, logger)
-
-    loggingService.setServiceParent(s)
-
-    return s
-
-def makeService_Master(self, options):
-    service = procmon.ProcessMonitor()
-
-    parentEnv = {"PYTHONPATH": os.environ.get("PYTHONPATH", "")}
-
-    log.msg("Adding pydirector service with configuration: %s"
-            % (config.PythonDirector.ConfigFile,))
-
-    service.addProcess(
-        "pydir",
-        [
-            sys.executable,
-            config.PythonDirector.pydir,
-            config.PythonDirector.ConfigFile
-        ],
-        env=parentEnv
-    )
-
-    return service
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081202/d8e5cdf6/attachment-0001.html>


More information about the calendarserver-changes mailing list