diff options
Diffstat (limited to 'policyhandler/step_timer.py')
-rw-r--r-- | policyhandler/step_timer.py | 105 |
1 files changed, 95 insertions, 10 deletions
diff --git a/policyhandler/step_timer.py b/policyhandler/step_timer.py index 6e2b3f6..ad77c85 100644 --- a/policyhandler/step_timer.py +++ b/policyhandler/step_timer.py @@ -18,46 +18,131 @@ """periodically callback""" -from threading import Event, Thread +from datetime import datetime +from threading import Event, Lock, Thread class StepTimer(Thread): """call on_time after interval number of seconds, then wait to continue""" - def __init__(self, name, interval, on_time, *args, **kwargs): + INIT = "init" + NEXT = "next" + STARTED = "started" + PAUSED = "paused" + STOPPING = "stopping" + STOPPED = "stopped" + + def __init__(self, name, interval, on_time, logger, *args, **kwargs): + """create step timer with controlled start. next step and pause""" Thread.__init__(self, name=name) self._interval = interval self._on_time = on_time + self._logger = logger self._args = args self._kwargs = kwargs + self._lock = Lock() + self._timeout = Event() self._paused = Event() - self._continue = Event() + self._next = Event() self._finished = Event() + self._event = StepTimer.INIT + self._event_counter = 0 + self._event_time = 0 + self._event_ts = datetime.now() + + self._substep = None + self._substep_time = 0 + self._substep_ts = datetime.now() + + def get_status(self): + """returns status of events""" + with self._lock: + return "{0}[{1}] {2}: timeout({3}), paused({4}), next({5}), finished({6})".format( + self._event, + self._event_counter, + self._substep, + self._timeout.is_set(), + self._paused.is_set(), + self._next.is_set(), + self._finished.is_set(), + ) + def next(self): """continue with the next timeout""" self._paused.clear() - self._continue.set() + self._next.set() + self._timeout.set() + self._set_timer_event(StepTimer.NEXT) def pause(self): """pause the timer""" self._paused.set() + self._next.clear() + self._set_timer_event(StepTimer.PAUSED) def stop(self): """stop the timer if it hasn't finished yet""" self._finished.set() self._timeout.set() - self._continue.set() + self._next.set() + self._set_timer_event(StepTimer.STOPPING) + + def _set_timer_event(self, event): + """set the event on the timer""" + with self._lock: + if event in [StepTimer.NEXT, StepTimer.STARTED]: + self._event_counter += 1 + + self._event = event + now = datetime.now() + self._event_time = (now - self._event_ts).total_seconds() + self._event_ts = now + self._logger.info("[{0}] {1} {2}".format( + self._event_time, self.name, self.get_status())) + + def _timer_substep(self, substep): + """log exe step""" + with self._lock: + self._substep = substep + now = datetime.now() + self._substep_time = (now - self._substep_ts).total_seconds() + self._substep_ts = now + self._logger.info("[{0}] {1}".format(self._substep_time, self.get_status())) def run(self): - """loop until stopped=finished""" + """loop one step a time until stopped=finished""" + self._set_timer_event(StepTimer.STARTED) while True: + self._timer_substep("waiting for timeout {0}...".format(self._interval)) self._timeout.wait(self._interval) + self._timer_substep("woke up after timeout") + if self._finished.is_set(): + self._timer_substep("finished") break - self._timeout.clear() - self._continue.clear() - if not self._paused.is_set(): + + if self._next.is_set(): + self._next.clear() + self._timeout.clear() + self._timer_substep("restart timer") + continue + + if self._paused.is_set(): + self._timer_substep("paused - skip on_time event") + else: + self._timer_substep("on_time event") self._on_time(*self._args, **self._kwargs) - self._continue.wait() + + self._timer_substep("waiting for next...") + self._next.wait() + self._next.clear() + self._timeout.clear() + self._timer_substep("woke up on next") + + if self._finished.is_set(): + self._timer_substep("finished") + break + + self._set_timer_event(StepTimer.STOPPED) |