#!/usr/local/bin/python2.5 """Main wsgi interface for PyCon2008. This application interface does somethign a bit unconventional in that it will run the application with the newest file modification time. When this file's modification time is updated, mod_wsgi will reload it and first run the shutdown app which will terminate the deamon process. This will ensure that the application is running in a fresh process instance. touch pycon2008.wsgi - restart the current server touch static.py pycon2008.wsgi - restart with the '503 Server Unavailable' touch dynamic.py pycon2008.wsgi - restart with teh live django instance For all this to work the apache mod_wsgi settings MUST be set to run with a single deamon (external) process, and the reload mechinism must be set to reload the full interpreter so that the imports are properly reloaded. WSGIProcessGroup pycon2008 WSGIDaemonProcess pycon2008 user=w05pcon0912 group=w05pcon0912 threads=25 WSGIReloadMechanism Interpreter We are not setting the number of processes, as we only want one, and there is only this application in the process group. IF you have other processes in the supplied WSGIProcessGroup, you should set 'processes=1' for the WSGIDeamonProcess directive. We do this so we can shutdown just the 2008 django instance for updating the source and doing database maintainance. We want to return a 503 to keep upstream servers from caching the static 'server is down' message. We need to do a full process reload because some 3rd party python extensions do not reload properly as part of a intrepter reload (reportlib, matplotlib). We also need to do an intrepter reload on the .wsgi modification so that the __mtime__ variables get properly reset on the sub modules. Special thanks to Graham Dumpleton for creating mod_wsgi and anwsering my silly questions at 2am in the morning. """ import os, sys path = '/var/hostings/05pcon0912/us.pycon.org/cgi-bin' if path not in sys.path: sys.path.insert(0, path) import static import dynamic import shutdown import thread import datetime logdir = "/var/hostings/05pcon0912/us.pycon.org/logs/" event_log_file = logdir + "pycon2008-django-eventlog" error_log_file = logdir + "pycon2008-django-errorlog" class ThreadSafeWriter(file): def __init__(self, *args, **kwdargs): self.lock = thread.allocate() return super(ThreadSafeWriter, self).__init__(*args, **kwdargs) def write(self, *args, **kwdargs): self.lock.acquire() res = super(ThreadSafeWriter, self).write(*args, **kwdargs) super(ThreadSafeWriter, self).flush() self.lock.release() return res def writeline(self, *args, **kwdargs): self.lock.acquire() res = super(ThreadSafeWriter, self).writeline(*args, **kwdargs) super(ThreadSafeWriter, self).flush() self.lock.release() return res def writelines(self, *args, **kwdargs): self.lock.acquire() res = super(ThreadSafeWriter, self).writelines(*args, **kwdargs) super(ThreadSafeWriter, self).flush() self.lock.release() return res class NullStreamWriter(object): def write(*args, **kwdargs): pass writeline = write writelines = write sys.stdout = ThreadSafeWriter(event_log_file, 'a') sys.stderr = ThreadSafeWriter(error_log_file, 'a') if __mtime__ > shutdown.__mtime__: os.utime(shutdown.__file__, None) sys.stdout.write(str(datetime.datetime.now()) + ' ' + str(os.getpid()) + ': shuting down.\n') _application = shutdown.application elif static.__mtime__ > dynamic.__mtime__: sys.stdout.write(str(datetime.datetime.now()) + ' ' + str(os.getpid()) + ': starting static.\n') _application = static.application else: sys.stdout.write(str(datetime.datetime.now()) + ' ' + str(os.getpid()) + ': starting django.\n') _application = dynamic.application def application(environ, start_response): return _application(environ, start_response)