[tor-commits] [tor/master] Add subsys functions for receiving/flushing states and options.

nickm at torproject.org nickm at torproject.org
Thu Nov 7 13:59:49 UTC 2019


commit 52c0ab4af3ec152c4b78669acf8877ca27d66097
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Oct 30 10:29:43 2019 -0400

    Add subsys functions for receiving/flushing states and options.
    
    These functions are in the subsystem, not in the config_format_t,
    since they are about how the format is _used_, not about _what it
    is_.
---
 src/app/config/config.c    |  3 +-
 src/app/config/statefile.c |  4 +++
 src/app/main/subsysmgr.c   | 76 ++++++++++++++++++++++++++++++++++++++++++++++
 src/app/main/subsysmgr.h   |  8 +++++
 src/lib/subsys/subsys.h    | 29 ++++++++++++++++++
 5 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/src/app/config/config.c b/src/app/config/config.c
index 7317a5d2f..892934970 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -987,7 +987,8 @@ set_options(or_options_t *new_val, char **msg)
     global_options = old_options;
     return -1;
   }
-  if (options_act(old_options) < 0) { /* acting on the options failed. die. */
+  if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
+      options_act(old_options) < 0) { /* acting on the options failed. die. */
     if (! tor_event_loop_shutdown_is_pending()) {
       log_err(LD_BUG,
               "Acting on config options left us in a broken state. Dying.");
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index f6b0915da..5fdb15ace 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -316,6 +316,9 @@ or_state_set(or_state_t *new_state)
   tor_assert(new_state);
   config_free(get_state_mgr(), global_state);
   global_state = new_state;
+  if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
+    ret = -1;
+  }
   if (entry_guards_parse_state(global_state, 1, &err)<0) {
     log_warn(LD_GENERAL,"%s",err);
     tor_free(err);
@@ -519,6 +522,7 @@ or_state_save(time_t now)
 
   /* Call everything else that might dirty the state even more, in order
    * to avoid redundant writes. */
+  (void) subsystems_flush_state(get_state_mgr(), global_state);
   entry_guards_update_state(global_state);
   rep_hist_update_state(global_state);
   circuit_build_times_update_state(get_circuit_build_times(), global_state);
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index e5c76b8e5..bd9af1144 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -334,3 +334,79 @@ subsystems_register_state_formats(config_mgr_t *mgr)
   }
   return 0;
 }
+
+/**
+ * Call all appropriate set_options() methods to tell the various subsystems
+ * about a new set of torrc options.  Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_options(const config_mgr_t *mgr, struct or_options_t *options)
+{
+  /* XXXX This does not yet handle reversible option assignment; I'll
+   * do that later in this branch. */
+
+  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (sys_status[i].options_idx >= 0 && sys->set_options) {
+      void *obj = config_mgr_get_obj_mutable(mgr, options,
+                                             sys_status[i].options_idx);
+      int rv = sys->set_options(obj);
+      if (rv < 0) {
+        log_err(LD_CONFIG, "Error when handling option for %s; "
+                "cannot proceed.", sys->name);
+        return -1;
+      }
+    }
+  }
+  return 0;
+}
+
+/**
+ * Call all appropriate set_state() methods to tell the various subsystems
+ * about an initial DataDir/state file.  Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (sys_status[i].state_idx >= 0 && sys->set_state) {
+      void *obj = config_mgr_get_obj_mutable(mgr, state,
+                                             sys_status[i].state_idx);
+      int rv = sys->set_state(obj);
+      if (rv < 0) {
+        log_err(LD_CONFIG, "Error when handling state for %s; "
+                "cannot proceed.", sys->name);
+        return -1;
+      }
+    }
+  }
+  return 0;
+}
+
+/**
+ * Call all appropriate flush_state() methods to tell the various subsystems
+ * to update the state objects in <b>state</b>.  Return 0 on success,
+ * -1 on failure.
+ **/
+int
+subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+  int result = 0;
+  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (sys_status[i].state_idx >= 0 && sys->flush_state) {
+      void *obj = config_mgr_get_obj_mutable(mgr, state,
+                                             sys_status[i].state_idx);
+      int rv = sys->flush_state(obj);
+      if (rv < 0) {
+        log_warn(LD_CONFIG, "Error when flushing state to state object for %s",
+                sys->name);
+        result = -1;
+      }
+    }
+  }
+  return result;
+}
diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h
index 54193f964..7e5fe7636 100644
--- a/src/app/main/subsysmgr.h
+++ b/src/app/main/subsysmgr.h
@@ -34,5 +34,13 @@ void subsystems_thread_cleanup(void);
 struct config_mgr_t;
 int subsystems_register_options_formats(struct config_mgr_t *mgr);
 int subsystems_register_state_formats(struct config_mgr_t *mgr);
+struct or_options_t;
+struct or_state_t;
+int subsystems_set_options(const struct config_mgr_t *mgr,
+                           struct or_options_t *options);
+int subsystems_set_state(const struct config_mgr_t *mgr,
+                         struct or_state_t *state);
+int subsystems_flush_state(const struct config_mgr_t *mgr,
+                           struct or_state_t *state);
 
 #endif /* !defined(TOR_SUBSYSMGR_T) */
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 1cb3fe94a..29a90c049 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -101,6 +101,35 @@ typedef struct subsys_fns_t {
    **/
   const struct config_format_t *state_format;
 
+  /**
+   * Receive an options object as defined by options_format. Return 0
+   * on success, -1 on failure.
+   *
+   * It is safe to store the pointer to the object until set_options()
+   * is called again. */
+  int (*set_options)(void *);
+
+  /* XXXX Add an implementation for options_act_reversible() later in this
+   * branch. */
+
+  /**
+   * Receive a state object as defined by state_format. Return 0 on success,
+   * -1 on failure.
+   *
+   * It is safe to store the pointer to the object; set_state() is only
+   * called on startup.
+   **/
+  int (*set_state)(void *);
+
+  /**
+   * Update any information that needs to be stored in the provided state
+   * object (as defined by state_format).  Return 0 on success, -1 on failure.
+   *
+   * The object provided here will be the same one as provided earlier to
+   * set_state().  This method is called when we are about to save the state
+   * to disk.
+   **/
+  int (*flush_state)(void *);
 } subsys_fns_t;
 
 /**





More information about the tor-commits mailing list