minor updates on upcoming changelog
[tor.git] / src / or / periodic.c
blob6896b41c86f27d7395cd59a00811d7ac7c76c5b1
1 /* Copyright (c) 2015-2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file periodic.c
7 * \brief Generic backend for handling periodic events.
9 * The events in this module are used by main.c to track items that need
10 * to fire once every N seconds, possibly picking a new interval each time
11 * that they fire. See periodic_events[] in main.c for examples.
14 #include "or.h"
15 #include "compat_libevent.h"
16 #include "config.h"
17 #include "periodic.h"
19 #include <event2/event.h>
21 /** We disable any interval greater than this number of seconds, on the
22 * grounds that it is probably an absolute time mistakenly passed in as a
23 * relative time.
25 static const int MAX_INTERVAL = 10 * 365 * 86400;
27 /** Set the event <b>event</b> to run in <b>next_interval</b> seconds from
28 * now. */
29 static void
30 periodic_event_set_interval(periodic_event_item_t *event,
31 time_t next_interval)
33 tor_assert(next_interval < MAX_INTERVAL);
34 struct timeval tv;
35 tv.tv_sec = next_interval;
36 tv.tv_usec = 0;
37 event_add(event->ev, &tv);
40 /** Wraps dispatches for periodic events, <b>data</b> will be a pointer to the
41 * event that needs to be called */
42 static void
43 periodic_event_dispatch(evutil_socket_t fd, short what, void *data)
45 (void)fd;
46 (void)what;
47 periodic_event_item_t *event = data;
49 time_t now = time(NULL);
50 const or_options_t *options = get_options();
51 // log_debug(LD_GENERAL, "Dispatching %s", event->name);
52 int r = event->fn(now, options);
53 int next_interval = 0;
55 /* update the last run time if action was taken */
56 if (r==0) {
57 log_err(LD_BUG, "Invalid return value for periodic event from %s.",
58 event->name);
59 tor_assert(r != 0);
60 } else if (r > 0) {
61 event->last_action_time = now;
62 /* If the event is meant to happen after ten years, that's likely
63 * a bug, and somebody gave an absolute time rather than an interval.
65 tor_assert(r < MAX_INTERVAL);
66 next_interval = r;
67 } else {
68 /* no action was taken, it is likely a precondition failed,
69 * we should reschedule for next second incase the precondition
70 * passes then */
71 next_interval = 1;
74 // log_debug(LD_GENERAL, "Scheduling %s for %d seconds", event->name,
75 // next_interval);
76 struct timeval tv = { next_interval , 0 };
77 event_add(event->ev, &tv);
80 /** Schedules <b>event</b> to run as soon as possible from now. */
81 void
82 periodic_event_reschedule(periodic_event_item_t *event)
84 periodic_event_set_interval(event, 1);
87 /** Initializes the libevent backend for a periodic event. */
88 void
89 periodic_event_setup(periodic_event_item_t *event)
91 if (event->ev) { /* Already setup? This is a bug */
92 log_err(LD_BUG, "Initial dispatch should only be done once.");
93 tor_assert(0);
96 event->ev = tor_event_new(tor_libevent_get_base(),
97 -1, 0,
98 periodic_event_dispatch,
99 event);
100 tor_assert(event->ev);
103 /** Handles initial dispatch for periodic events. It should happen 1 second
104 * after the events are created to mimic behaviour before #3199's refactor */
105 void
106 periodic_event_launch(periodic_event_item_t *event)
108 if (! event->ev) { /* Not setup? This is a bug */
109 log_err(LD_BUG, "periodic_event_launch without periodic_event_setup");
110 tor_assert(0);
113 // Initial dispatch
114 periodic_event_dispatch(-1, EV_TIMEOUT, event);
117 /** Release all storage associated with <b>event</b> */
118 void
119 periodic_event_destroy(periodic_event_item_t *event)
121 if (!event)
122 return;
123 tor_event_free(event->ev);
124 event->last_action_time = 0;