From 62540cffaab693fdc2f4c4abbf4489541061b371 Mon Sep 17 00:00:00 2001 From: benoitc Date: Sat, 22 May 2010 21:11:25 +0200 Subject: [PATCH] commit changes from @davisp + some fixes --- gunicorn/app/base.py | 6 ++++++ gunicorn/app/djangoapp.py | 2 ++ gunicorn/app/pasterapp.py | 1 + gunicorn/arbiter.py | 5 ++--- gunicorn/config.py | 25 +++++++++++++++---------- gunicorn/workers/async.py | 2 +- gunicorn/workers/base.py | 4 +--- gunicorn/workers/gtornado.py | 4 ++-- gunicorn/workers/sync.py | 2 +- 9 files changed, 31 insertions(+), 20 deletions(-) diff --git a/gunicorn/app/base.py b/gunicorn/app/base.py index 45dd9655..3a027013 100644 --- a/gunicorn/app/base.py +++ b/gunicorn/app/base.py @@ -21,6 +21,7 @@ class Application(object): def __init__(self, usage=None): self.log = logging.getLogger(__name__) self.cfg = Config(usage) + self.callable = None parser = self.cfg.parser() opts, args = parser.parse_args() @@ -67,6 +68,11 @@ class Application(object): def load(self): raise NotImplementedError + + def wsgi(self): + if self.callable is None: + self.callable = self.load() + return self.callable def run(self): if self.cfg.spew: diff --git a/gunicorn/app/djangoapp.py b/gunicorn/app/djangoapp.py index b7d636ee..3fe64869 100644 --- a/gunicorn/app/djangoapp.py +++ b/gunicorn/app/djangoapp.py @@ -51,6 +51,8 @@ class DjangoApplicationCommand(Application): def __init__(self, options, admin_media_path): self.cfg = Config() + self.callable = None + for k, v in list(options.items()): if k.lower() in self.cfg.settings and v is not None: self.cfg.set(k.lower(), v) diff --git a/gunicorn/app/pasterapp.py b/gunicorn/app/pasterapp.py index 066d16a0..67d71365 100644 --- a/gunicorn/app/pasterapp.py +++ b/gunicorn/app/pasterapp.py @@ -63,6 +63,7 @@ class PasterServerApplication(Application): def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs): self.cfg = Config() self.app = app + self.callable = None cfg = kwargs.copy() diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 5f2d7d6f..6848248d 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -45,12 +45,11 @@ class Arbiter(object): ) def __init__(self, app): + self.app = app self.cfg = app.cfg if self.cfg.preload_app: - self.app = app.load() - else: - self.app = app + self.app.wsgi() self.log = logging.getLogger(__name__) diff --git a/gunicorn/config.py b/gunicorn/config.py index ccaa89c7..0bca5979 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -349,6 +349,21 @@ with Setting("spew") as s: This is the nuclear option. """) +with Setting("preload_app") as s: + s.section = "Server Mechanics" + s.cli = ["--preload"] + s.validator = validate_bool + s.action = "store_true" + s.default = False + s.fmt_desc("""\ + Load application code before the worker processes are forked. + + By preloading an application you can save some RAM resources as well as + speed up server boot times. Although, if you defer application loading + to each worker process, you can reload your application code easily by + restarting workers. + """) + with Setting("daemon") as s: s.section = "Server Mechanics" s.cli = ["-D", "--daemon"] @@ -522,13 +537,3 @@ with Setting("pre_exec") as s: The callable needs to accept a single instance variable for the Arbiter. """) - -with Setting("preload_app") as s: - s.section = "Server Mechanic" - s.cli = ["--preload"] - s.validator = validate_bool - s.action = "store_true" - s.default = False - s.fmt_desc("""\ - Enabling this preloads an application before forking worker processes. - """) \ No newline at end of file diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py index 3fff7dd9..95e03db7 100644 --- a/gunicorn/workers/async.py +++ b/gunicorn/workers/async.py @@ -57,7 +57,7 @@ class AsyncWorker(Worker): environ = req.read() if not environ or not req.parser.headers: return False - respiter = self.app(environ, req.start_response) + respiter = self.wsgi(environ, req.start_response) if respiter == ALREADY_HANDLED: return False for item in respiter: diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py index 12e90ec9..5bd31ea9 100644 --- a/gunicorn/workers/base.py +++ b/gunicorn/workers/base.py @@ -91,9 +91,7 @@ class Worker(object): util.close_on_exec(self.fd) self.init_signals() - # do we need to load the app - if not self.cfg.preload_app: - self.app = self.app.load() + self.wsgi = self.app.wsgi() # Enter main run loop self.run() diff --git a/gunicorn/workers/gtornado.py b/gunicorn/workers/gtornado.py index a419a1a0..f2e5eb33 100644 --- a/gunicorn/workers/gtornado.py +++ b/gunicorn/workers/gtornado.py @@ -50,9 +50,9 @@ class TornadoWorker(Worker): # Assume the app is a WSGI callable if its not an # instance of tornardo.web.Application if not isinstance(self.app, tornado.web.Application): - self.app = WSGIContainer(self.app) + self.app = WSGIContainer(self.wsgi) - server = HTTPServer(self.app, io_loop=self.ioloop) + server = HTTPServer(self.wsgi, io_loop=self.ioloop) server._socket = self.socket server.start(num_processes=1) diff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py index 7597234d..1ac3474e 100644 --- a/gunicorn/workers/sync.py +++ b/gunicorn/workers/sync.py @@ -94,7 +94,7 @@ class SyncWorker(Worker): environ = req.read() if not environ or not req.parser.status_line: return - respiter = self.app(environ, req.start_response) + respiter = self.wsgi(environ, req.start_response) for item in respiter: req.response.write(item) req.response.close()