From a02b89cf7a02ed0cf42148ca11422b0361d4a8d5 Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Wed, 19 Aug 2009 14:44:48 +0200 Subject: [PATCH] Reinsert simple timers in Mainloop This time we use the standard python sched module, rather than doing it all by ourselves. The scheduler in mainloop can be manipulated directly by callers, to enter new events. Signed-off-by: Guido Trotter <ultrotter@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- lib/daemon.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/daemon.py b/lib/daemon.py index e0ab16cb4..860e36406 100644 --- a/lib/daemon.py +++ b/lib/daemon.py @@ -28,9 +28,47 @@ import select import signal import errno import logging +import sched +import time from ganeti import utils from ganeti import constants +from ganeti import errors + + +class SchedulerBreakout(Exception): + """Exception used to get out of the scheduler loop + + """ + + +def AsyncoreDelayFunction(timeout): + """Asyncore-compatible scheduler delay function. + + This is a delay function for sched that, rather than actually sleeping, + executes asyncore events happening in the meantime. + + After an event has occurred, rather than returning, it raises a + SchedulerBreakout exception, which will force the current scheduler.run() + invocation to terminate, so that we can also check for signals. The main loop + will then call the scheduler run again, which will allow it to actually + process any due events. + + This is needed because scheduler.run() doesn't support a count=..., as + asyncore loop, and the scheduler module documents throwing exceptions from + inside the delay function as an allowed usage model. + + """ + asyncore.loop(timeout=timeout, count=1, use_poll=True) + raise SchedulerBreakout() + + +class AsyncoreScheduler(sched.scheduler): + """Event scheduler integrated with asyncore + + """ + def __init__(self, timefunc): + sched.scheduler.__init__(self, timefunc, AsyncoreDelayFunction) class Mainloop(object): @@ -40,8 +78,12 @@ class Mainloop(object): def __init__(self): """Constructs a new Mainloop instance. + @ivar scheduler: A L{sched.scheduler} object, which can be used to register + timed events + """ self._signal_wait = [] + self.scheduler = AsyncoreScheduler(time.time) @utils.SignalHandled([signal.SIGCHLD]) @utils.SignalHandled([signal.SIGTERM]) @@ -65,7 +107,13 @@ class Mainloop(object): if stop_on_empty and not (self._io_wait): break - asyncore.loop(timeout=5, count=1, use_poll=True) + if not self.scheduler.empty(): + try: + self.scheduler.run() + except SchedulerBreakout: + pass + else: + asyncore.loop(count=1, use_poll=True) # Check whether a signal was raised for sig in signal_handlers: -- GitLab