aboutsummaryrefslogtreecommitdiffstats
path: root/policyhandler/step_timer.py
diff options
context:
space:
mode:
Diffstat (limited to 'policyhandler/step_timer.py')
-rw-r--r--policyhandler/step_timer.py105
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)