diff --git a/gunicorn/config.py b/gunicorn/config.py index bba7aea8..1bec3827 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -15,12 +15,14 @@ class Config(object): DEFAULT_CONFIG_FILE = 'gunicorn.conf.py' DEFAULTS = dict( + arbiter="egg:gunicorn", backlog=2048, bind='127.0.0.1:8000', daemon=False, debug=False, default_proc_name = os.getcwd(), group=None, + keepalive=2, logfile='-', loglevel='info', pidfile=None, @@ -30,6 +32,7 @@ class Config(object): umask="0", user=None, workers=1, + worker_connections=1000, after_fork=lambda server, worker: server.log.info( "Worker spawned (pid: %s)" % worker.pid), @@ -93,7 +96,16 @@ class Config(object): def __iter__(self): return self.conf.iteritems() - + + @property + def arbiter(self): + uri = self.conf.get('arbiter', 'egg:gunicorn') + arbiter = util.parse_arbiter_uri(uri) + print arbiter + if hasattr(arbiter, 'setup'): + arbiter.setup() + return arbiter + @property def workers(self): if not self.conf.get('workers'): diff --git a/gunicorn/main.py b/gunicorn/main.py index eebf5622..d1f16dd9 100644 --- a/gunicorn/main.py +++ b/gunicorn/main.py @@ -32,6 +32,9 @@ def options(): help='Adress to listen on. Ex. 127.0.0.1:8000 or unix:/tmp/gunicorn.sock'), op.make_option('-w', '--workers', dest='workers', help='Number of workers to spawn. [1]'), + op.make_option('-a', '--arbiter', dest='arbiter', + help="gunicorn arbiter entry point or module "+ + "[egg:gunicorn#main]"), op.make_option('-p','--pid', dest='pidfile', help='set the background PID FILE'), op.make_option('-D', '--daemon', dest='daemon', action="store_true", @@ -112,7 +115,7 @@ def main(usage, get_app): app = get_app(parser, opts, args) conf = Config(opts.__dict__, opts.config) - arbiter = Arbiter(conf.address, conf.workers, app, config=conf, + arbiter = conf.arbiter(conf.address, conf.workers, app, config=conf, debug=conf['debug'], pidfile=conf['pidfile']) if conf['daemon']: daemonize() @@ -147,7 +150,7 @@ def paste_server(app, global_conf=None, host="127.0.0.1", port=None, options['default_proc_name'] = options['__file__'] conf = Config(options) - arbiter = Arbiter(conf.address, conf.workers, app, debug=conf["debug"], + arbiter = conf.arbiter(conf.address, conf.workers, app, debug=conf["debug"], pidfile=conf["pidfile"], config=conf) if conf["daemon"] : daemonize() diff --git a/gunicorn/util.py b/gunicorn/util.py index 4f809571..75224f82 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -3,9 +3,11 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. + import ctypes import fcntl import os +import pkg_resources import resource import socket import textwrap @@ -35,7 +37,30 @@ try: except ImportError: def _setproctitle(title): return - + +def parse_arbiter_uri(uri): + if uri.startswith("egg:"): + # uses entry points + entry_str = uri.split("egg:")[1] + parsed_ept = entry_str.split("#", 1) + try: + dist, name = entry_str.rsplit("#",1) + except: + dist = entry_str + name = "main" + + return pkg_resources.load_entry_point(dist, "gunicorn.arbiter", + name) + else: + components = uri.split('.') + if len(components) == 1: + raise RuntimeError("arbiter uri invalid") + klass = components.pop(-1) + mod = __import__('.'.join(components)) + for comp in components[1:]: + mod = getattr(mod, comp) + return getattr(mod, klass) + def set_owner_process(uid,gid): """ set user and group of workers processes """ if gid: @@ -76,9 +101,8 @@ def get_maxfd(): return maxfd def close_on_exec(fd): - flags = fcntl.fcntl(fd, fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(fd, fcntl.F_SETFD, flags) + flags = fcntl.fcntl(fd, fcntl.F_GETFD) | fcntl.FD_CLOEXEC + fcntl.fcntl(fd, fcntl.F_SETFL, flags) def set_non_blocking(fd): flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK diff --git a/setup.py b/setup.py index 1804f7bb..2fe84c4a 100644 --- a/setup.py +++ b/setup.py @@ -47,9 +47,13 @@ setup( gunicorn=gunicorn.main:run gunicorn_django=gunicorn.main:run_django gunicorn_paster=gunicorn.main:run_paster + + [gunicorn.arbiter] + main=gunicorn.arbiter:Arbiter + [paste.server_runner] main=gunicorn.main:paste_server """, test_suite = 'nose.collector', -) \ No newline at end of file +)