123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /* 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);
- }
- }
|