periodic.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* Copyright (c) 2015, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "or.h"
  4. #include "config.h"
  5. #include "periodic.h"
  6. static const int MAX_INTERVAL = 10 * 365 * 86400;
  7. /** DOCDOC */
  8. static void
  9. periodic_event_set_interval(periodic_event_item_t *event,
  10. time_t next_interval)
  11. {
  12. /** update the interval time if it's changed */
  13. if (next_interval != event->interval) {
  14. tor_assert(next_interval < MAX_INTERVAL);
  15. struct timeval tv;
  16. tv.tv_sec = next_interval;
  17. tv.tv_usec = 0;
  18. event->interval = (int)next_interval;
  19. periodic_timer_update_interval(event->timer, &tv);
  20. }
  21. }
  22. /** Wraps dispatches for periodic events, <b>data</b> will be a pointer to the
  23. * event that needs to be called */
  24. static void
  25. periodic_event_dispatch(periodic_timer_t *timer, void *data)
  26. {
  27. periodic_event_item_t *event = data;
  28. tor_assert(timer == event->timer);
  29. time_t now = time(NULL);
  30. const or_options_t *options = get_options();
  31. int r = event->fn(now, options);
  32. int next_interval = 0;
  33. /* update the last run time if action was taken */
  34. if (r==0) {
  35. log_err(LD_BUG, "Invalid return value for periodic event from %s.",
  36. event->name);
  37. tor_assert(r != 0);
  38. } else if (r > 0) {
  39. event->last_action_time = now;
  40. /* If the event is meant to happen after ten years, that's likely
  41. * a bug, and somebody gave an absolute time rather than an interval.
  42. */
  43. tor_assert(r < MAX_INTERVAL);
  44. next_interval = r;
  45. } else {
  46. /* no action was taken, it is likely a precondition failed,
  47. * we should reschedule for next second incase the precondition
  48. * passes then */
  49. next_interval = 1;
  50. }
  51. periodic_event_set_interval(event, next_interval);
  52. log_info(LD_GENERAL, "Dispatching %s", event->name);
  53. }
  54. /** DOCDOC */
  55. void
  56. periodic_event_reschedule(periodic_event_item_t *event)
  57. {
  58. periodic_event_set_interval(event, 1);
  59. }
  60. /** Handles initial dispatch for periodic events. It should happen 1 second
  61. * after the events are created to mimic behaviour before #3199's refactor */
  62. void
  63. periodic_event_launch(periodic_event_item_t *event)
  64. {
  65. if (event->timer) { /** Already setup? This is a bug */
  66. log_err(LD_BUG, "Initial dispatch should only be done once.");
  67. tor_assert(0);
  68. }
  69. struct timeval interval;
  70. interval.tv_sec = event->interval;
  71. interval.tv_usec = 0;
  72. periodic_timer_t *timer = periodic_timer_new(tor_libevent_get_base(),
  73. &interval,
  74. periodic_event_dispatch,
  75. event);
  76. tor_assert(timer);
  77. event->timer = timer;
  78. // Initial dispatch
  79. periodic_event_dispatch(timer, event);
  80. }
  81. /** DOCDOC */
  82. void
  83. periodic_event_destroy(periodic_event_item_t *event)
  84. {
  85. if (!event)
  86. return;
  87. periodic_timer_free(event->timer);
  88. event->timer = 0;
  89. event->interval = 0;
  90. event->last_action_time = 0;
  91. }
  92. /** DOCDOC */
  93. void
  94. periodic_event_assert_in_range(periodic_event_item_t *ev,
  95. time_t start, time_t end)
  96. {
  97. if (ev->last_action_time < start-1 || ev->last_action_time > end) {
  98. log_err(LD_BUG, "[Refactor Bug] Missed an interval in a range,"
  99. "Got %lu, wanted %lu <= x <= %lu.", ev->last_action_time,
  100. start, end);
  101. tor_assert(0);
  102. }
  103. }