diff options
Diffstat (limited to 'nova/utils.py')
-rw-r--r-- | nova/utils.py | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/nova/utils.py b/nova/utils.py index 26468868a..1056a6e2d 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -556,12 +556,23 @@ class LoopingCallDone(Exception): self.retvalue = retvalue -class LoopingCall(object): +class LoopingCallBase(object): def __init__(self, f=None, *args, **kw): self.args = args self.kw = kw self.f = f self._running = False + self.done = None + + def stop(self): + self._running = False + + def wait(self): + return self.done.wait() + + +class FixedIntervalLoopingCall(LoopingCallBase): + """A looping call which happens at a fixed interval.""" def start(self, interval, initial_delay=None): self._running = True @@ -581,7 +592,7 @@ class LoopingCall(object): self.stop() done.send(e.retvalue) except Exception: - LOG.exception(_('in looping call')) + LOG.exception(_('in fixed duration looping call')) done.send_exception(*sys.exc_info()) return else: @@ -592,11 +603,47 @@ class LoopingCall(object): greenthread.spawn(_inner) return self.done - def stop(self): - self._running = False - def wait(self): - return self.done.wait() +class DynamicLoopingCall(LoopingCallBase): + """A looping call which happens sleeps until the next known event. + + The function called should return how long to sleep for before being + called again. + """ + + def start(self, initial_delay=None, periodic_interval_max=None): + self._running = True + done = event.Event() + + def _inner(): + if initial_delay: + greenthread.sleep(initial_delay) + + try: + while self._running: + idle = self.f(*self.args, **self.kw) + if not self._running: + break + + if not periodic_interval_max is None: + idle = min(idle, periodic_interval_max) + LOG.debug(_('Periodic task processor sleeping for %.02f ' + 'seconds'), idle) + greenthread.sleep(idle) + except LoopingCallDone, e: + self.stop() + done.send(e.retvalue) + except Exception: + LOG.exception(_('in dynamic looping call')) + done.send_exception(*sys.exc_info()) + return + else: + done.send(True) + + self.done = done + + greenthread.spawn(_inner) + return self.done def xhtml_escape(value): |