[tor-commits] [tor/master] periodic: Add an enable and disable function

nickm at torproject.org nickm at torproject.org
Mon Apr 23 15:04:20 UTC 2018


commit 4e85f17eec06fc963c33cc3f637876e7f1627a57
Author: David Goulet <dgoulet at torproject.org>
Date:   Tue Apr 17 09:57:09 2018 -0400

    periodic: Add an enable and disable function
    
    Two helper functions to enable an event and disable an event which wraps the
    launch and destroy of an event but takes care of the enabled flag.
    
    They are also idempotent that is can be called multiple time on the same event
    without effect if the event was already enabled or disabled.
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/main.c     | 22 +++++++++-------------
 src/or/periodic.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 src/or/periodic.h |  2 ++
 3 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/src/or/main.c b/src/or/main.c
index eb8835198..1c5ac198b 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1484,8 +1484,9 @@ initialize_periodic_events_cb(evutil_socket_t fd, short events, void *data)
 
   for (int i = 0; periodic_events[i].name; ++i) {
     periodic_event_item_t *item = &periodic_events[i];
-    if (item->roles & roles && !periodic_event_is_enabled(item)) {
-      periodic_event_launch(item);
+    if (item->roles & roles) {
+      /* This is safe to be called on an already enabled event. */
+      periodic_event_enable(item);
       log_debug(LD_GENERAL, "Launching periodic event %s", item->name);
     }
   }
@@ -1541,18 +1542,13 @@ rescan_periodic_events(const or_options_t *options)
 
   for (int i = 0; periodic_events[i].name; ++i) {
     periodic_event_item_t *item = &periodic_events[i];
-    int is_enabled = periodic_event_is_enabled(item);
-    int need_item = (item->roles & roles);
 
-    /* We need this event but it is *not* enabled. */
-    if (need_item && !is_enabled) {
-      periodic_event_launch(item);
-      continue;
-    }
-    /* We do *not* need this event but it is enabled. */
-    if (!need_item && is_enabled) {
-      periodic_event_destroy(item);
-      continue;
+    /* Enable the event if needed. It is safe to enable an event that was
+     * already enabled. Same goes for disabling it. */
+    if (item->roles & roles) {
+      periodic_event_enable(item);
+    } else {
+      periodic_event_disable(item);
     }
   }
 }
diff --git a/src/or/periodic.c b/src/or/periodic.c
index 42bea3ae6..76aa418b3 100644
--- a/src/or/periodic.c
+++ b/src/or/periodic.c
@@ -43,12 +43,22 @@ periodic_event_dispatch(mainloop_event_t *ev, void *data)
   periodic_event_item_t *event = data;
   tor_assert(ev == event->ev);
 
+  if (BUG(!periodic_event_is_enabled(event))) {
+    return;
+  }
+
   time_t now = time(NULL);
   const or_options_t *options = get_options();
 //  log_debug(LD_GENERAL, "Dispatching %s", event->name);
   int r = event->fn(now, options);
   int next_interval = 0;
 
+  if (!periodic_event_is_enabled(event)) {
+    /* The event got disabled from inside its callback; no need to
+     * reschedule. */
+    return;
+  }
+
   /* update the last run time if action was taken */
   if (r==0) {
     log_err(LD_BUG, "Invalid return value for periodic event from %s.",
@@ -114,8 +124,8 @@ periodic_event_launch(periodic_event_item_t *event)
   }
 
   // Initial dispatch
-  periodic_event_dispatch(event->ev, event);
   event->enabled = 1;
+  periodic_event_dispatch(event->ev, event);
 }
 
 /** Release all storage associated with <b>event</b> */
@@ -126,6 +136,35 @@ periodic_event_destroy(periodic_event_item_t *event)
     return;
   mainloop_event_free(event->ev);
   event->last_action_time = 0;
+}
+
+/** Enable the given event which means the event is launched and then the
+ * event's enabled flag is set. This can be called for an event that is
+ * already enabled. */
+void
+periodic_event_enable(periodic_event_item_t *event)
+{
+  tor_assert(event);
+  /* Safely and silently ignore if this event is already enabled. */
+  if (periodic_event_is_enabled(event)) {
+    return;
+  }
+
+  periodic_event_launch(event);
+}
+
+/** Disable the given event which means the event is destroyed and then the
+ * event's enabled flag is unset. This can be called for an event that is
+ * already disabled. */
+void
+periodic_event_disable(periodic_event_item_t *event)
+{
+  tor_assert(event);
+  /* Safely and silently ignore if this event is already disabled. */
+  if (!periodic_event_is_enabled(event)) {
+    return;
+  }
+  mainloop_event_cancel(event->ev);
   event->enabled = 0;
 }
 
diff --git a/src/or/periodic.h b/src/or/periodic.h
index 1b346a1cc..dde27db5a 100644
--- a/src/or/periodic.h
+++ b/src/or/periodic.h
@@ -69,6 +69,8 @@ void periodic_event_launch(periodic_event_item_t *event);
 void periodic_event_setup(periodic_event_item_t *event);
 void periodic_event_destroy(periodic_event_item_t *event);
 void periodic_event_reschedule(periodic_event_item_t *event);
+void periodic_event_enable(periodic_event_item_t *event);
+void periodic_event_disable(periodic_event_item_t *event);
 
 #endif /* !defined(TOR_PERIODIC_H) */
 





More information about the tor-commits mailing list