summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorMichael Still <mikal@stillhq.com>2013-04-08 11:58:07 +1000
committerMichael Still <mikal@stillhq.com>2013-04-08 17:01:12 +1000
commit2920449a03988f5e268b9c51147ba723e6924cb8 (patch)
treefde4dbb8988fd95e2b803b1d8054f4dfa06c9db7 /openstack
parent25c8dd56a5fd3b2874c61220d7c451c4c9346689 (diff)
downloadoslo-2920449a03988f5e268b9c51147ba723e6924cb8.tar.gz
oslo-2920449a03988f5e268b9c51147ba723e6924cb8.tar.xz
oslo-2920449a03988f5e268b9c51147ba723e6924cb8.zip
Import nova's looping call.
The looping call implementation had drifted in nova away from what was in oslo. Update olso. I will move nova over to this code in a later review. Change-Id: I0e9214a150223dcd4fb1d695db36961bba794166
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/loopingcall.py64
-rw-r--r--openstack/common/threadgroup.py2
2 files changed, 59 insertions, 7 deletions
diff --git a/openstack/common/loopingcall.py b/openstack/common/loopingcall.py
index be044d8..3704e8e 100644
--- a/openstack/common/loopingcall.py
+++ b/openstack/common/loopingcall.py
@@ -46,12 +46,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 fixed interval looping call."""
def start(self, interval, initial_delay=None):
self._running = True
@@ -77,7 +88,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:
@@ -88,8 +99,49 @@ class LoopingCall(object):
greenthread.spawn_n(_inner)
return self.done
- def stop(self):
- self._running = False
- def wait(self):
- return self.done.wait()
+# TODO(mikal): this class name is deprecated in Havana and should be removed
+# in the I release
+LoopingCall = FixedIntervalLoopingCall
+
+
+class DynamicLoopingCall(LoopingCallBase):
+ """A looping call which 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 periodic_interval_max is not None:
+ idle = min(idle, periodic_interval_max)
+ LOG.debug(_('Dynamic looping call 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
diff --git a/openstack/common/threadgroup.py b/openstack/common/threadgroup.py
index a87497f..3558b73 100644
--- a/openstack/common/threadgroup.py
+++ b/openstack/common/threadgroup.py
@@ -63,7 +63,7 @@ class ThreadGroup(object):
def add_timer(self, interval, callback, initial_delay=None,
*args, **kwargs):
- pulse = loopingcall.LoopingCall(callback, *args, **kwargs)
+ pulse = loopingcall.FixedIntervalLoopingCall(callback, *args, **kwargs)
pulse.start(interval=interval,
initial_delay=initial_delay)
self.timers.append(pulse)