[tor-commits] [tor/master] Partial support for multiplicity in configuration objects

dgoulet at torproject.org dgoulet at torproject.org
Wed Sep 4 14:39:08 UTC 2019


commit 638e58379a4c5347dd4952f12dd3b1054e7bb19f
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Jul 24 11:20:55 2019 -0400

    Partial support for multiplicity in configuration objects
    
    A configuration manager, in addition to a top-level format object,
    may now also know about a suite of sub-formats.  Top-level
    configuration objects, in turn, may now have a suite of
    sub-objects.
---
 src/app/config/confparse.c | 105 +++++++++++++++++++++++++++++++++++++--------
 src/app/config/confparse.h |   2 +
 2 files changed, 90 insertions(+), 17 deletions(-)

diff --git a/src/app/config/confparse.c b/src/app/config/confparse.c
index d94a1d9ec..8018f6a6d 100644
--- a/src/app/config/confparse.c
+++ b/src/app/config/confparse.c
@@ -73,10 +73,10 @@ managed_var_free_(managed_var_t *mv)
   FREE_AND_NULL(managed_var_t, managed_var_free_, (mv))
 
 struct config_suite_t {
-  /* NOTE: This object isn't implemented yet; it's just a placeholder
-   * to make sure we have our memory menagement right.
-   */
-  int foo;
+  /** A list of configuration objects managed by a given configuration
+   * manager. They are stored in the same order as the config_format_t
+   * objects in the manager's list of subformats. */
+  smartlist_t *configs;
 };
 
 /**
@@ -86,6 +86,7 @@ static config_suite_t *
 config_suite_new(void)
 {
   config_suite_t *suite = tor_malloc_zero(sizeof(config_suite_t));
+  suite->configs = smartlist_new();
   return suite;
 }
 
@@ -96,6 +97,7 @@ config_suite_free_(config_suite_t *suite)
 {
   if (!suite)
     return;
+  smartlist_free(suite->configs);
   tor_free(suite);
 }
 
@@ -110,6 +112,11 @@ struct config_mgr_t {
    * contains.  A subsequent commit will add more. XXXX)
    */
   const config_format_t *toplevel;
+  /**
+   * List of second-level configuration format objects that this manager
+   * also knows about.
+   */
+  smartlist_t *subconfigs;
   /** A smartlist of managed_var_t objects for all configuration formats. */
   smartlist_t *all_vars;
   /** A smartlist of config_abbrev_t objects for all abbreviations. These
@@ -137,12 +144,14 @@ config_mgr_t *
 config_mgr_new(const config_format_t *toplevel_fmt)
 {
   config_mgr_t *mgr = tor_malloc_zero(sizeof(config_mgr_t));
-  mgr->toplevel = toplevel_fmt;
+  mgr->subconfigs = smartlist_new();
   mgr->all_vars = smartlist_new();
   mgr->all_abbrevs = smartlist_new();
   mgr->all_deprecations = smartlist_new();
 
   config_mgr_register_fmt(mgr, toplevel_fmt, IDX_TOPLEVEL);
+  mgr->toplevel = toplevel_fmt;
+
   return mgr;
 }
 
@@ -158,6 +167,14 @@ config_mgr_register_fmt(config_mgr_t *mgr,
               "Tried to add a format to a configuration manager after "
               "it had been frozen.");
 
+  if (object_idx != IDX_TOPLEVEL) {
+    tor_assertf(fmt->config_suite_offset < 0,
+          "Tried to register a toplevel format in a non-toplevel position");
+  }
+  tor_assertf(fmt != mgr->toplevel &&
+              ! smartlist_contains(mgr->subconfigs, fmt),
+              "Tried to register an already-registered format.");
+
   /* register variables */
   for (i = 0; fmt->vars[i].member.name; ++i) {
     managed_var_t *mv = tor_malloc_zero(sizeof(managed_var_t));
@@ -182,6 +199,21 @@ config_mgr_register_fmt(config_mgr_t *mgr,
   }
 }
 
+/**
+ * Add a new format to this configuration object.  Asserts on failure.
+ *
+ **/
+int
+config_mgr_add_format(config_mgr_t *mgr,
+                      const config_format_t *fmt)
+{
+  tor_assert(mgr);
+  int idx = smartlist_len(mgr->subconfigs);
+  config_mgr_register_fmt(mgr, fmt, idx);
+  smartlist_add(mgr->subconfigs, (void *)fmt);
+  return idx;
+}
+
 /** Return a pointer to the config_suite_t * pointer inside a
  * configuration object; returns NULL if there is no such member. */
 static inline config_suite_t **
@@ -204,10 +236,19 @@ config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
 static void *
 config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
 {
-  (void)mgr;
-  tor_assert(idx == IDX_TOPLEVEL); // nothing else is implemented yet XXXX
+  tor_assert(mgr);
   tor_assert(toplevel);
-  return toplevel;
+  if (idx == IDX_TOPLEVEL)
+    return toplevel;
+
+  tor_assertf(idx >= 0 && idx < smartlist_len(mgr->subconfigs),
+              "Index %d is out of range.", idx);
+  config_suite_t **suite = config_mgr_get_suite_ptr(mgr, toplevel);
+  tor_assert(suite);
+  tor_assert(smartlist_len(mgr->subconfigs) ==
+             smartlist_len((*suite)->configs));
+
+  return smartlist_get((*suite)->configs, idx);
 }
 
 /** As config_mgr_get_obj_mutable(), but return a const pointer. */
@@ -257,6 +298,7 @@ config_mgr_free_(config_mgr_t *mgr)
   smartlist_free(mgr->all_vars);
   smartlist_free(mgr->all_abbrevs);
   smartlist_free(mgr->all_deprecations);
+  smartlist_free(mgr->subconfigs);
   memset(mgr, 0, sizeof(*mgr));
   tor_free(mgr);
 }
@@ -296,6 +338,20 @@ config_mgr_assert_magic_ok(const config_mgr_t *mgr,
   tor_assert(options);
   tor_assert(mgr->frozen);
   struct_check_magic(options, &mgr->toplevel_magic);
+
+  config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, (void*)options);
+  if (suitep == NULL) {
+    tor_assert(smartlist_len(mgr->subconfigs) == 0);
+    return;
+  }
+
+  tor_assert(smartlist_len((*suitep)->configs) ==
+             smartlist_len(mgr->subconfigs));
+  SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+    void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
+    tor_assert(obj);
+    struct_check_magic(obj, &fmt->magic);
+  } SMARTLIST_FOREACH_END(fmt);
 }
 
 /** Macro: assert that <b>cfg</b> has the right magic field for
@@ -309,12 +365,16 @@ void *
 config_new(const config_mgr_t *mgr)
 {
   tor_assert(mgr->frozen);
-  const config_format_t *fmt = mgr->toplevel;
-  void *opts = tor_malloc_zero(fmt->size);
+  void *opts = tor_malloc_zero(mgr->toplevel->size);
   struct_set_magic(opts, &mgr->toplevel_magic);
   config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, opts);
   if (suitep) {
     *suitep = config_suite_new();
+    SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+      void *obj = tor_malloc_zero(fmt->size);
+      struct_set_magic(obj, &fmt->magic);
+      smartlist_add((*suitep)->configs, obj);
+    } SMARTLIST_FOREACH_END(fmt);
   }
   CONFIG_CHECK(mgr, opts);
   return opts;
@@ -826,30 +886,41 @@ config_reset(const config_mgr_t *mgr, void *options,
 void
 config_free_(const config_mgr_t *mgr, void *options)
 {
-  const config_format_t *fmt = mgr->toplevel;
-
   if (!options)
     return;
 
-  tor_assert(fmt);
+  tor_assert(mgr);
 
   if (mgr->toplevel->clear_fn) {
     mgr->toplevel->clear_fn(mgr, options);
   }
+  config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, options);
+  if (suitep) {
+    tor_assert(smartlist_len((*suitep)->configs) ==
+               smartlist_len(mgr->subconfigs));
+    SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+      void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
+      if (fmt->clear_fn) {
+        fmt->clear_fn(mgr, obj);
+      }
+    } SMARTLIST_FOREACH_END(fmt);
+  }
 
   SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) {
     config_clear(mgr, options, mv);
   } SMARTLIST_FOREACH_END(mv);
 
-  if (fmt->extra) {
-    config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->offset);
+  if (mgr->toplevel->extra) {
+    config_line_t **linep = STRUCT_VAR_P(options,
+                                         mgr->toplevel->extra->offset);
     config_free_lines(*linep);
     *linep = NULL;
   }
 
-  config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, options);
-  if (suitep)
+  if (suitep) {
+    SMARTLIST_FOREACH((*suitep)->configs, void *, obj, tor_free(obj));
     config_suite_free(*suitep);
+  }
 
   tor_free(options);
 }
diff --git a/src/app/config/confparse.h b/src/app/config/confparse.h
index c18e85423..9125c0be3 100644
--- a/src/app/config/confparse.h
+++ b/src/app/config/confparse.h
@@ -76,6 +76,8 @@ typedef struct config_mgr_t config_mgr_t;
 
 config_mgr_t *config_mgr_new(const config_format_t *toplevel_fmt);
 void config_mgr_free_(config_mgr_t *mgr);
+int config_mgr_add_format(config_mgr_t *mgr,
+                          const config_format_t *fmt);
 void config_mgr_freeze(config_mgr_t *mgr);
 #define config_mgr_free(mgr) \
   FREE_AND_NULL(config_mgr_t, config_mgr_free_, (mgr))





More information about the tor-commits mailing list