diff options
author | Kevin Butler <haqkrs@gmail.com> | 2015-11-02 09:48:18 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-11-13 16:24:44 -0500 |
commit | fbeff307f7780b26c9645ec7dbd685807add6581 (patch) | |
tree | daaf4b9c1cfc2d3a98af4dac873c514ba100acc3 /src/or/periodic.c | |
parent | faba114a3484a7b85649a6892b2296cf9ac8a41e (diff) | |
download | tor-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.c | 118 |
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); + } +} |