TimerServer.py 3.54 KB
Newer Older
Kevin Deldycke's avatar
Kevin Deldycke committed
1 2 3 4 5 6 7 8
# -*- coding: UTF-8 -*-
# -*- Mode: Python; py-indent-offset: 4 -*-
# Authors: Nik Kim <fafhrd@legco.biz> 
__version__ = 'TimerServer for Zope 0.1'

import traceback

import thread
9 10 11 12

import sys, os, errno, time, socket

import ZPublisher.Client
Kevin Deldycke's avatar
Kevin Deldycke committed
13 14 15 16 17 18 19
from StringIO import StringIO
from zLOG import LOG, INFO

from ZServer.PubCore import handle
from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.BaseResponse import BaseResponse
from ZPublisher.HTTPRequest import HTTPRequest
20
from ZPublisher import Client
Kevin Deldycke's avatar
Kevin Deldycke committed
21 22

class TimerServer:
23
    def __init__(self, module, interval=5):
Kevin Deldycke's avatar
Kevin Deldycke committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
        self.module = module

        self.interval = interval

        sync = thread.allocate_lock()

        self._a = sync.acquire
        self._r = sync.release

        self._a()
        thread.start_new_thread(self.run, ())
        self._r()

        LOG('ZServer', INFO,
            'Timer server started at %s\n'
            '\tInterval: %s seconds.\n'%(time.ctime(time.time()), interval))

    def run(self):
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

        # wait until the zhttp_server exist in socket_map
        # because TimerService has to be started after the Zope HTTPServer
        from asyncore import socket_map
        while 1:
            time.sleep(5)
            for k, v in socket_map.items():
                if hasattr(v, 'port'):
                        # see Zope/lib/python/App/ApplicationManager.py: def getServers(self)
                        type = str(getattr(v, '__class__', 'unknown'))
                        if type == 'ZServer.HTTPServer.zhttp_server':
                            port = v.port
                            break
            if port:
                break

        ip = socket.gethostbyname(socket.gethostname())

        # To be very sure, try to connect to the HTTPServer
        # and only start after we are able to connect
        while 1:
            time.sleep(5)
            try:
                Client.call('http://%s:%s' %(ip, port))
            except ValueError:
                continue
            break

Kevin Deldycke's avatar
Kevin Deldycke committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
        module = self.module
        interval = self.interval

        # minutes = time.gmtime(time.time()[4], seconds = time.gmtime(time.time()[5]
        # max interval is therefore 59*60 + 59 = 208919 seconds

        wait = ((time.gmtime(time.time())[4] * 60) + time.gmtime(time.time())[5]) % interval
        sleep = interval - wait

        if sleep > 0:
            time.sleep(sleep)

        LOG('ZServer', INFO, 'Timerserver ready, starting timer services.')

        while 1:
            time.sleep(interval)
            # send message to zope
            try:
                out = StringIO()
                err = StringIO()
                response = TimerResponse(out, err)
                handle(module, TimerRequest(response, interval), response)
            except:
                pass


class TimerResponse(BaseResponse):
    def _finish(self):
        pass

    def unauthorized(self):
        pass
        

class TimerRequest(HTTPRequest):

    retry_max_count = 0

    def __init__(self, response, interval):
        stdin=StringIO()
        environ=self._get_env(stdin)
        HTTPRequest.__init__(self, stdin, environ, response, clean=1)

        self.other['interval'] = interval

    def _get_env(self, stdin):
        "Returns a CGI style environment"
        env={}
        env['REQUEST_METHOD']='GET'
        env['SERVER_SOFTWARE']= 'TimerServer for Zope'
        env['SERVER_NAME'] = ''
        env['SERVER_PORT'] = ''
        env['REMOTE_ADDR'] = ''
        env['GATEWAY_INTERFACE'] = 'CGI/1.1'

        env['PATH_INFO']= '/Control_Panel/timer_service/process_timer'
        return env