From: Martin Mares Date: Sat, 28 Apr 2012 23:32:05 +0000 (+0200) Subject: Conf: Introduced cf_open_group() and cf_close_group() X-Git-Tag: v5.99~172 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=b3d3d2847cb34363c5e7a5a6bf8155b710d7afcd;p=libucw.git Conf: Introduced cf_open_group() and cf_close_group() All grouping inside cf_getopt() uses it, too. --- diff --git a/ucw/conf-getopt.c b/ucw/conf-getopt.c index 507c5102..66f98f20 100644 --- a/ucw/conf-getopt.c +++ b/ucw/conf-getopt.c @@ -53,21 +53,19 @@ load_default(struct cf_context *cc) } static void -final_commit(struct cf_context *cc) +end_of_options(struct cf_context *cc) { - if (cc->postpone_commit) - { - cc->postpone_commit = 0; - if (cf_done_stack(cc)) - die("Cannot commit after the initialization"); - } + load_default(cc); + if (cc->postpone_commit && cf_close_group()) + die("Cannot commit after the initialization"); } int cf_getopt(int argc, char *const argv[], const char *short_opts, const struct option *long_opts, int *long_index) { struct cf_context *cc = cf_get_context(); - cc->postpone_commit = 1; + if (!cc->postpone_commit) + cf_open_group(); while (1) { @@ -90,8 +88,7 @@ cf_getopt(int argc, char *const argv[], const char *short_opts, const struct opt #ifdef CONFIG_UCW_DEBUG else { /* --dumpconfig */ - load_default(cc); - final_commit(cc); + end_of_options(cc); struct fastbuf *b = bfdopen(1, 4096); cf_dump_sections(b); bclose(b); @@ -103,10 +100,7 @@ cf_getopt(int argc, char *const argv[], const char *short_opts, const struct opt { /* unhandled option or end of options */ if (res != ':' && res != '?') - { - load_default(cc); - final_commit(cc); - } + end_of_options(cc); cc->other_options++; return res; } diff --git a/ucw/conf-input.c b/ucw/conf-input.c index 5a782bf0..3dc5db1d 100644 --- a/ucw/conf-input.c +++ b/ucw/conf-input.c @@ -331,8 +331,6 @@ cf_remember_entry(struct cf_context *cc, uns type, const char *arg) { if (!cc->need_journal) return; - if (!cc->postpone_commit) - return; struct conf_entry *ce = cf_malloc(sizeof(*ce)); ce->type = type; ce->arg = cf_strdup(arg); @@ -350,7 +348,7 @@ cf_reload(const char *file) clist old_entries; clist_move(&old_entries, &cc->conf_entries); - cc->postpone_commit = 1; + cf_open_group(); int err = 0; if (file) @@ -366,9 +364,7 @@ cf_reload(const char *file) cf_remember_entry(cc, ce->type, ce->arg); } - cc->postpone_commit = 0; - if (!err) - err |= cf_done_stack(cc); + err |= cf_close_group(); if (!err) { cf_journal_delete(); diff --git a/ucw/conf-internal.h b/ucw/conf-internal.h index ee6d08d4..95ef6e6f 100644 --- a/ucw/conf-internal.h +++ b/ucw/conf-internal.h @@ -44,13 +44,13 @@ struct cf_context { int is_active; int config_loaded; // at least one config file was loaded struct cf_parser_state *parser; - uns everything_committed; // after the 1st load, this flag is set on - uns postpone_commit; // used internally by cf_getopt() - uns other_options; + uns everything_committed; // did we already commit each section? + uns postpone_commit; // counter of calls to cf_open_group() + uns other_options; // used internally by cf_getopt() clist conf_entries; // files/strings to reload - struct old_pools *pools; - struct cf_journal_item *journal; + struct cf_journal_item *journal; // journalling int need_journal; + struct old_pools *pools; struct item_stack stack[MAX_STACK_SIZE]; // interpreter stack uns stack_level; struct cf_section sections; // root section diff --git a/ucw/conf-intr.c b/ucw/conf-intr.c index 0b5d5407..3e9445f2 100644 --- a/ucw/conf-intr.c +++ b/ucw/conf-intr.c @@ -655,7 +655,7 @@ int cf_done_stack(struct cf_context *cc) { if (cc->stack_level > 0) { - msg(L_ERROR, "Unterminated block"); + msg(L_ERROR, "Unterminated block"); // FIXME: Where? return 1; } if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL)) @@ -664,3 +664,21 @@ cf_done_stack(struct cf_context *cc) cc->everything_committed = 1; return 0; } + +void +cf_open_group(void) +{ + struct cf_context *cc = cf_get_context(); + cc->postpone_commit++; +} + +int +cf_close_group(void) +{ + struct cf_context *cc = cf_get_context(); + ASSERT(cc->postpone_commit); + if (!--cc->postpone_commit) + return cf_done_stack(cc); + else + return 0; +} diff --git a/ucw/conf.h b/ucw/conf.h index bef4553e..a387f274 100644 --- a/ucw/conf.h +++ b/ucw/conf.h @@ -57,14 +57,46 @@ struct cf_context *cf_switch_context(struct cf_context *cc); * These functions can be used to to safely load or reload configuration. */ -int cf_reload(const char *file); /** Reload configuration from @file, replace the old one. **/ -int cf_load(const char *file); /** Load configuration from @file. If @file is NULL, reload all loaded configuration files. **/ +/** + * Load configuration from @file. + * Returns a non-zero value upon error. In that case, all changes to the + * configuration specified in the file are undone. + **/ +int cf_load(const char *file); +/** + * Reload configuration from @file, replace the old one. + * If @file is NULL, reload all loaded configuration files and re-apply + * bits of configuration passed to cf_set(). + * Returns a non-zero value upon error. In that case, all configuration + * settings are rolled back to the state before calling this function. + **/ +int cf_reload(const char *file); /** * Parse some part of configuration passed in @string. * The syntax is the same as in the <>. + * Returns a non-zero value upon error. In that case, all changes to the + * configuration specified by the already executed parts of the string + * are undone. **/ int cf_set(const char *string); +/** + * Sometimes, the configuration is split to multiple files and when only + * some of the are loaded, the settings are not consistent -- for example, + * they might have been rejected by a commit hook, because a mandatory setting + * is missing. + * + * This function opens a configuration group, in which multiple files can be + * loaded and all commit hooks are deferred until the group is closed. + **/ +void cf_open_group(void); + +/** + * Close a group opened by cf_open_group(). Returns a non-zero value upon error, + * which usually means that a commit hook has failed. + **/ +int cf_close_group(void); + /*** === Data types [[conf_types]] ***/ enum cf_class { /** Class of the configuration item. **/