commit 638e58379a4c5347dd4952f12dd3b1054e7bb19f Author: Nick Mathewson nickm@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))
tor-commits@lists.torproject.org