mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
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.
This commit is contained in:
parent
38b770bbbb
commit
638e58379a
@ -73,10 +73,10 @@ managed_var_free_(managed_var_t *mv)
|
|||||||
FREE_AND_NULL(managed_var_t, managed_var_free_, (mv))
|
FREE_AND_NULL(managed_var_t, managed_var_free_, (mv))
|
||||||
|
|
||||||
struct config_suite_t {
|
struct config_suite_t {
|
||||||
/* NOTE: This object isn't implemented yet; it's just a placeholder
|
/** A list of configuration objects managed by a given configuration
|
||||||
* to make sure we have our memory menagement right.
|
* manager. They are stored in the same order as the config_format_t
|
||||||
*/
|
* objects in the manager's list of subformats. */
|
||||||
int foo;
|
smartlist_t *configs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +86,7 @@ static config_suite_t *
|
|||||||
config_suite_new(void)
|
config_suite_new(void)
|
||||||
{
|
{
|
||||||
config_suite_t *suite = tor_malloc_zero(sizeof(config_suite_t));
|
config_suite_t *suite = tor_malloc_zero(sizeof(config_suite_t));
|
||||||
|
suite->configs = smartlist_new();
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +97,7 @@ config_suite_free_(config_suite_t *suite)
|
|||||||
{
|
{
|
||||||
if (!suite)
|
if (!suite)
|
||||||
return;
|
return;
|
||||||
|
smartlist_free(suite->configs);
|
||||||
tor_free(suite);
|
tor_free(suite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +112,11 @@ struct config_mgr_t {
|
|||||||
* contains. A subsequent commit will add more. XXXX)
|
* contains. A subsequent commit will add more. XXXX)
|
||||||
*/
|
*/
|
||||||
const config_format_t *toplevel;
|
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. */
|
/** A smartlist of managed_var_t objects for all configuration formats. */
|
||||||
smartlist_t *all_vars;
|
smartlist_t *all_vars;
|
||||||
/** A smartlist of config_abbrev_t objects for all abbreviations. These
|
/** 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_new(const config_format_t *toplevel_fmt)
|
||||||
{
|
{
|
||||||
config_mgr_t *mgr = tor_malloc_zero(sizeof(config_mgr_t));
|
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_vars = smartlist_new();
|
||||||
mgr->all_abbrevs = smartlist_new();
|
mgr->all_abbrevs = smartlist_new();
|
||||||
mgr->all_deprecations = smartlist_new();
|
mgr->all_deprecations = smartlist_new();
|
||||||
|
|
||||||
config_mgr_register_fmt(mgr, toplevel_fmt, IDX_TOPLEVEL);
|
config_mgr_register_fmt(mgr, toplevel_fmt, IDX_TOPLEVEL);
|
||||||
|
mgr->toplevel = toplevel_fmt;
|
||||||
|
|
||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +167,14 @@ config_mgr_register_fmt(config_mgr_t *mgr,
|
|||||||
"Tried to add a format to a configuration manager after "
|
"Tried to add a format to a configuration manager after "
|
||||||
"it had been frozen.");
|
"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 */
|
/* register variables */
|
||||||
for (i = 0; fmt->vars[i].member.name; ++i) {
|
for (i = 0; fmt->vars[i].member.name; ++i) {
|
||||||
managed_var_t *mv = tor_malloc_zero(sizeof(managed_var_t));
|
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
|
/** Return a pointer to the config_suite_t * pointer inside a
|
||||||
* configuration object; returns NULL if there is no such member. */
|
* configuration object; returns NULL if there is no such member. */
|
||||||
static inline config_suite_t **
|
static inline config_suite_t **
|
||||||
@ -204,10 +236,19 @@ config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
|
|||||||
static void *
|
static void *
|
||||||
config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
|
config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
|
||||||
{
|
{
|
||||||
(void)mgr;
|
tor_assert(mgr);
|
||||||
tor_assert(idx == IDX_TOPLEVEL); // nothing else is implemented yet XXXX
|
|
||||||
tor_assert(toplevel);
|
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. */
|
/** 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_vars);
|
||||||
smartlist_free(mgr->all_abbrevs);
|
smartlist_free(mgr->all_abbrevs);
|
||||||
smartlist_free(mgr->all_deprecations);
|
smartlist_free(mgr->all_deprecations);
|
||||||
|
smartlist_free(mgr->subconfigs);
|
||||||
memset(mgr, 0, sizeof(*mgr));
|
memset(mgr, 0, sizeof(*mgr));
|
||||||
tor_free(mgr);
|
tor_free(mgr);
|
||||||
}
|
}
|
||||||
@ -296,6 +338,20 @@ config_mgr_assert_magic_ok(const config_mgr_t *mgr,
|
|||||||
tor_assert(options);
|
tor_assert(options);
|
||||||
tor_assert(mgr->frozen);
|
tor_assert(mgr->frozen);
|
||||||
struct_check_magic(options, &mgr->toplevel_magic);
|
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
|
/** Macro: assert that <b>cfg</b> has the right magic field for
|
||||||
@ -309,12 +365,16 @@ void *
|
|||||||
config_new(const config_mgr_t *mgr)
|
config_new(const config_mgr_t *mgr)
|
||||||
{
|
{
|
||||||
tor_assert(mgr->frozen);
|
tor_assert(mgr->frozen);
|
||||||
const config_format_t *fmt = mgr->toplevel;
|
void *opts = tor_malloc_zero(mgr->toplevel->size);
|
||||||
void *opts = tor_malloc_zero(fmt->size);
|
|
||||||
struct_set_magic(opts, &mgr->toplevel_magic);
|
struct_set_magic(opts, &mgr->toplevel_magic);
|
||||||
config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, opts);
|
config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, opts);
|
||||||
if (suitep) {
|
if (suitep) {
|
||||||
*suitep = config_suite_new();
|
*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);
|
CONFIG_CHECK(mgr, opts);
|
||||||
return opts;
|
return opts;
|
||||||
@ -826,30 +886,41 @@ config_reset(const config_mgr_t *mgr, void *options,
|
|||||||
void
|
void
|
||||||
config_free_(const config_mgr_t *mgr, void *options)
|
config_free_(const config_mgr_t *mgr, void *options)
|
||||||
{
|
{
|
||||||
const config_format_t *fmt = mgr->toplevel;
|
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tor_assert(fmt);
|
tor_assert(mgr);
|
||||||
|
|
||||||
if (mgr->toplevel->clear_fn) {
|
if (mgr->toplevel->clear_fn) {
|
||||||
mgr->toplevel->clear_fn(mgr, options);
|
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) {
|
SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) {
|
||||||
config_clear(mgr, options, mv);
|
config_clear(mgr, options, mv);
|
||||||
} SMARTLIST_FOREACH_END(mv);
|
} SMARTLIST_FOREACH_END(mv);
|
||||||
|
|
||||||
if (fmt->extra) {
|
if (mgr->toplevel->extra) {
|
||||||
config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->offset);
|
config_line_t **linep = STRUCT_VAR_P(options,
|
||||||
|
mgr->toplevel->extra->offset);
|
||||||
config_free_lines(*linep);
|
config_free_lines(*linep);
|
||||||
*linep = NULL;
|
*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);
|
config_suite_free(*suitep);
|
||||||
|
}
|
||||||
|
|
||||||
tor_free(options);
|
tor_free(options);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,8 @@ typedef struct config_mgr_t config_mgr_t;
|
|||||||
|
|
||||||
config_mgr_t *config_mgr_new(const config_format_t *toplevel_fmt);
|
config_mgr_t *config_mgr_new(const config_format_t *toplevel_fmt);
|
||||||
void config_mgr_free_(config_mgr_t *mgr);
|
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);
|
void config_mgr_freeze(config_mgr_t *mgr);
|
||||||
#define config_mgr_free(mgr) \
|
#define config_mgr_free(mgr) \
|
||||||
FREE_AND_NULL(config_mgr_t, config_mgr_free_, (mgr))
|
FREE_AND_NULL(config_mgr_t, config_mgr_free_, (mgr))
|
||||||
|
Loading…
Reference in New Issue
Block a user