periodic.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* Copyright (c) 2015, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "or.h"
  4. #include "compat_libevent.h"
  5. #include "config.h"
  6. #include "periodic.h"
  7. #ifdef HAVE_EVENT2_EVENT_H
  8. #include <event2/event.h>
  9. #else
  10. #include <event.h>
  11. #endif
  12. /** We disable any interval greate than this number of seconds, on the ground
  13. * that it is probably an absolute time mistakenly passed in as a relative time.
  14. */
  15. static const int MAX_INTERVAL = 10 * 365 * 86400;
  16. /** Set the event <b>event</b> to run in <b>next_interval</b> seconds from
  17. * now. */
  18. static void
  19. periodic_event_set_interval(periodic_event_item_t *event,
  20. time_t next_interval)
  21. {
  22. tor_assert(next_interval < MAX_INTERVAL);
  23. struct timeval tv;
  24. tv.tv_sec = next_interval;
  25. tv.tv_usec = 0;
  26. event_add(event->ev, &tv);
  27. }
  28. /** Wraps dispatches for periodic events, <b>data</b> will be a pointer to the
  29. * event that needs to be called */
  30. static void
  31. periodic_event_dispatch(evutil_socket_t fd, short what, void *data)
  32. {
  33. (void)fd;
  34. (void)what;
  35. periodic_event_item_t *event = data;
  36. time_t now = time(NULL);
  37. const or_options_t *options = get_options();
  38. int r = event->fn(now, options);
  39. int next_interval = 0;
  40. /* update the last run time if action was taken */
  41. if (r==0) {
  42. log_err(LD_BUG, "Invalid return value for periodic event from %s.",
  43. event->name);
  44. tor_assert(r != 0);
  45. } else if (r > 0) {
  46. event->last_action_time = now;
  47. /* If the event is meant to happen after ten years, that's likely
  48. * a bug, and somebody gave an absolute time rather than an interval.
  49. */
  50. tor_assert(r < MAX_INTERVAL);
  51. next_interval = r;
  52. } else {
  53. /* no action was taken, it is likely a precondition failed,
  54. * we should reschedule for next second incase the precondition
  55. * passes then */
  56. next_interval = 1;
  57. }
  58. struct timeval tv = { next_interval , 0 };
  59. event_add(event->ev, &tv);
  60. log_info(LD_GENERAL, "Dispatching %s", event->name);
  61. }
  62. /** Schedules <b>event</b> to run as soon as possible from now. */
  63. void
  64. periodic_event_reschedule(periodic_event_item_t *event)
  65. {
  66. periodic_event_set_interval(event, 1);
  67. }
  68. /** Handles initial dispatch for periodic events. It should happen 1 second
  69. * after the events are created to mimic behaviour before #3199's refactor */
  70. void
  71. periodic_event_launch(periodic_event_item_t *event)
  72. {
  73. if (event->ev) { /** Already setup? This is a bug */
  74. log_err(LD_BUG, "Initial dispatch should only be done once.");
  75. tor_assert(0);
  76. }
  77. event->ev = tor_event_new(tor_libevent_get_base(),
  78. -1, 0,
  79. periodic_event_dispatch,
  80. event);
  81. tor_assert(event->ev);
  82. // Initial dispatch
  83. periodic_event_dispatch(-1, EV_TIMEOUT, event);
  84. }
  85. /** Release all storage associated with <b>event</b> */
  86. void
  87. periodic_event_destroy(periodic_event_item_t *event)
  88. {
  89. if (!event)
  90. return;
  91. tor_event_free(event->ev);
  92. event->last_action_time = 0;
  93. }