aboutsummaryrefslogtreecommitdiff
path: root/src/or/periodic.c
diff options
context:
space:
mode:
authorKevin Butler <haqkrs@gmail.com>2015-11-02 09:48:18 -0500
committerNick Mathewson <nickm@torproject.org>2015-11-13 16:24:44 -0500
commitfbeff307f7780b26c9645ec7dbd685807add6581 (patch)
treedaaf4b9c1cfc2d3a98af4dac873c514ba100acc3 /src/or/periodic.c
parentfaba114a3484a7b85649a6892b2296cf9ac8a41e (diff)
downloadtor-fbeff307f7780b26c9645ec7dbd685807add6581.tar.gz
tor-fbeff307f7780b26c9645ec7dbd685807add6581.zip
Infrastructure for replacing global periodic events in main.c
(This is from Kevin's bug3199 patch series; nick extracted it into a new file and changed the interface a little, then did some API tweaks on it.)
Diffstat (limited to 'src/or/periodic.c')
-rw-r--r--src/or/periodic.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/or/periodic.c b/src/or/periodic.c
new file mode 100644
index 0000000000..6fa1d8a2b5
--- /dev/null
+++ b/src/or/periodic.c
@@ -0,0 +1,118 @@
+/* Copyright (c) 2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+#include "config.h"
+#include "periodic.h"
+
+static const int MAX_INTERVAL = 10 * 365 * 86400;
+
+/** DOCDOC */
+static void
+periodic_event_set_interval(periodic_event_item_t *event,
+ time_t next_interval)
+{
+ /** update the interval time if it's changed */
+ if (next_interval != event->interval) {
+ tor_assert(next_interval < MAX_INTERVAL);
+ struct timeval tv;
+ tv.tv_sec = next_interval;
+ tv.tv_usec = 0;
+ event->interval = (int)next_interval;
+ periodic_timer_update_interval(event->timer, &tv);
+ }
+}
+
+/** Wraps dispatches for periodic events, <b>data</b> will be a pointer to the
+ * event that needs to be called */
+static void
+periodic_event_dispatch(periodic_timer_t *timer, void *data)
+{
+ periodic_event_item_t *event = data;
+ tor_assert(timer == event->timer);
+
+ time_t now = time(NULL);
+ const or_options_t *options = get_options();
+ int r = event->fn(now, options);
+ int next_interval = 0;
+
+ /* update the last run time if action was taken */
+ if (r==0) {
+ log_err(LD_BUG, "Invalid return value for periodic event from %s.",
+ event->name);
+ tor_assert(r != 0);
+ } else if (r > 0) {
+ event->last_action_time = now;
+ /* If the event is meant to happen after ten years, that's likely
+ * a bug, and somebody gave an absolute time rather than an interval.
+ */
+ tor_assert(r < MAX_INTERVAL);
+ next_interval = r;
+ } else {
+ /* no action was taken, it is likely a precondition failed,
+ * we should reschedule for next second incase the precondition
+ * passes then */
+ next_interval = 1;
+ }
+
+ periodic_event_set_interval(event, next_interval);
+
+ log_info(LD_GENERAL, "Dispatching %s", event->name);
+}
+
+/** DOCDOC */
+void
+periodic_event_reschedule(periodic_event_item_t *event)
+{
+ periodic_event_set_interval(event, 1);
+}
+
+/** Handles initial dispatch for periodic events. It should happen 1 second
+ * after the events are created to mimic behaviour before #3199's refactor */
+void
+periodic_event_launch(periodic_event_item_t *event)
+{
+ if (event->timer) { /** Already setup? This is a bug */
+ log_err(LD_BUG, "Initial dispatch should only be done once.");
+ tor_assert(0);
+ }
+
+ struct timeval interval;
+ interval.tv_sec = event->interval;
+ interval.tv_usec = 0;
+
+ periodic_timer_t *timer = periodic_timer_new(tor_libevent_get_base(),
+ &interval,
+ periodic_event_dispatch,
+ event);
+ tor_assert(timer);
+ event->timer = timer;
+
+ // Initial dispatch
+ periodic_event_dispatch(timer, event);
+}
+
+/** DOCDOC */
+void
+periodic_event_destroy(periodic_event_item_t *event)
+{
+ if (!event)
+ return;
+ periodic_timer_free(event->timer);
+ event->timer = 0;
+ event->interval = 0;
+ event->last_action_time = 0;
+}
+
+/** DOCDOC */
+void
+periodic_event_assert_in_range(periodic_event_item_t *ev,
+ time_t start, time_t end)
+{
+ if (ev->last_action_time < start-1 || ev->last_action_time > end) {
+ log_err(LD_BUG, "[Refactor Bug] Missed an interval in a range,"
+ "Got %lu, wanted %lu <= x <= %lu.", ev->last_action_time,
+ start, end);
+ tor_assert(0);
+ }
+}