]> mj.ucw.cz Git - libucw.git/commitdiff
Conf: Introduced cf_open_group() and cf_close_group()
authorMartin Mares <mj@ucw.cz>
Sat, 28 Apr 2012 23:32:05 +0000 (01:32 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 29 Apr 2012 11:57:30 +0000 (13:57 +0200)
All grouping inside cf_getopt() uses it, too.

ucw/conf-getopt.c
ucw/conf-input.c
ucw/conf-internal.h
ucw/conf-intr.c
ucw/conf.h

index 507c51024cac3226faa0a0f13fe195872cdb5932..66f98f20e49e1af94b21f5511df189ed8f66bbd1 100644 (file)
@@ -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;
        }
index 5a782bf0d638fce13882b31b9eaa5e917b629cb1..3dc5db1d385ef96baae70de29102988d9f8c0649 100644 (file)
@@ -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();
index ee6d08d4d80c35a0b7ffbaae664094574f6a86ba..95ef6e6ff2892918610e73cdd7a28c9ee0580f73 100644 (file)
@@ -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
index 0b5d5407397ac95d2e37cddeb5bdd533f940e780..3e9445f2240131511998beda66faa2ba6d038e17 100644 (file)
@@ -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;
+}
index bef4553e155a5477cb1abb664d27c1da62785be1..a387f274d57966818aa0c9e76d3bb6c36ae886ab 100644 (file)
@@ -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 <<config:,configuration file>>.
+ * 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. **/