]> mj.ucw.cz Git - libucw.git/blobdiff - ucw/conf-input.c
Conf: Decoupled cf_stack_done() from committing
[libucw.git] / ucw / conf-input.c
index fff753ce01743606735983ca6ec7bcabef7272c5..ddfef9bd621fa954e6e41e88454b7b8682a84d3f 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <ucw/lib.h>
 #include <ucw/conf.h>
-#include <ucw/getopt.h>
 #include <ucw/conf-internal.h>
 #include <ucw/clists.h>
 #include <ucw/mempool.h>
@@ -203,6 +202,16 @@ split_command(struct cf_parser_state *p)
 
 /* Parsing multiple files */
 
+static int
+maybe_commit(struct cf_context *cc)
+{
+  if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
+    return 1;
+  if (!cc->postpone_commit)
+    cc->everything_committed = 1;
+  return 0;
+}
+
 static char *
 parse_fastbuf(struct cf_context *cc, const char *name_fb, struct fastbuf *fb, uns depth)
 {
@@ -215,14 +224,17 @@ parse_fastbuf(struct cf_context *cc, const char *name_fb, struct fastbuf *fb, un
   p->line = p->line_buf;
   *p->line = 0;
 
-  char *err;
+  if (!depth)
+    cf_init_stack(cc);
+
+  char *err = NULL;
   while (1)
   {
     err = split_command(p);
     if (err)
       goto error;
     if (!p->words)
-      return NULL;
+      break;
     char *name = p->copy_buf.ptr + p->word_buf.ptr[0];
     char *pars[p->words-1];
     for (uns i=1; i<p->words; i++)
@@ -282,6 +294,17 @@ parse_fastbuf(struct cf_context *cc, const char *name_fb, struct fastbuf *fb, un
     if (err)
       goto error;
   }
+
+  if (!depth)
+    {
+      if (cf_done_stack(cc))
+       err = "Unterminated block";
+      else if (maybe_commit(cc))
+       err = "Commit failed";
+    }
+  if (!err)
+    return NULL;
+
 error:
   if (name_fb)
     msg(L_ERROR, "File %s, line %d: %s", name_fb, p->line_num, err);
@@ -292,40 +315,26 @@ error:
   return "included from here";
 }
 
-static int
-done_stack(struct cf_context *cc)
-{
-  if (cf_check_stack(cc))
-    return 1;
-  if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
-    return 1;
-  if (!cc->postpone_commit)
-    cc->everything_committed = 1;
-  return 0;
-}
-
 static int
 load_file(struct cf_context *cc, const char *file)
 {
-  cf_init_stack(cc);
   struct fastbuf *fb = bopen_try(file, O_RDONLY, 1<<14);
   if (!fb) {
-    msg(L_ERROR, "Cannot open %s: %m", file);
+    msg(L_ERROR, "Cannot open configuration file %s: %m", file);
     return 1;
   }
   char *err_msg = parse_fastbuf(cc, file, fb, 0);
   bclose(fb);
-  return !!err_msg || done_stack(cc);
+  return !!err_msg;
 }
 
 static int
 load_string(struct cf_context *cc, const char *string)
 {
-  cf_init_stack(cc);
   struct fastbuf fb;
   fbbuf_init_read(&fb, (byte *)string, strlen(string), 0);
   char *msg = parse_fastbuf(cc, NULL, &fb, 0);
-  return !!msg || done_stack(cc);
+  return !!msg;
 }
 
 /* Safe loading and reloading */
@@ -342,9 +351,7 @@ struct conf_entry { /* We remember a list of actions to apply upon reload */
 static void
 cf_remember_entry(struct cf_context *cc, uns type, const char *arg)
 {
-  if (!cc->need_journal)
-    return;
-  if (!cc->postpone_commit)
+  if (!cc->enable_journal)
     return;
   struct conf_entry *ce = cf_malloc(sizeof(*ce));
   ce->type = type;
@@ -356,6 +363,7 @@ int
 cf_reload(const char *file)
 {
   struct cf_context *cc = cf_get_context();
+  ASSERT(cc->enable_journal);
   cf_journal_swap();
   struct cf_journal_item *oldj = cf_journal_new_transaction(1);
   uns ec = cc->everything_committed;
@@ -363,7 +371,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)
@@ -379,9 +387,7 @@ cf_reload(const char *file)
       cf_remember_entry(cc, ce->type, ce->arg);
     }
 
-  cc->postpone_commit = 0;
-  if (!err)
-    err |= done_stack(cc);
+  err |= cf_close_group();
 
   if (!err) {
     cf_journal_delete();
@@ -404,7 +410,7 @@ cf_load(const char *file)
   if (!err) {
     cf_journal_commit_transaction(1, oldj);
     cf_remember_entry(cc, CE_FILE, file);
-    cc->def_loaded = 1;
+    cc->config_loaded = 1;
   } else
     cf_journal_rollback_transaction(1, oldj);
   return err;
@@ -424,82 +430,27 @@ cf_set(const char *string)
   return err;
 }
 
-/* Command-line parser */
-
-static void
-load_default(struct cf_context *cc)
+void
+cf_revert(void)
 {
-  if (cc->def_loaded++)
-    return;
-  if (cc->def_file)
-    {
-      char *env;
-      if (cc->env_file && (env = getenv(cc->env_file)))
-        {
-         if (cf_load(env))
-           die("Cannot load config file %s", env);
-       }
-      else if (cf_load(cc->def_file))
-        die("Cannot load default config %s", cc->def_file);
-    }
-  else
-    {
-      // We need to create an empty pool and initialize all configuration items
-      struct cf_journal_item *oldj = cf_journal_new_transaction(1);
-      cf_init_stack(cc);
-      done_stack(cc);
-      cf_journal_commit_transaction(1, oldj);
-    }
+  cf_journal_swap();
+  cf_journal_delete();
 }
 
-static void
-final_commit(struct cf_context *cc)
+void
+cf_open_group(void)
 {
-  if (cc->postpone_commit) {
-    cc->postpone_commit = 0;
-    if (done_stack(cc))
-      die("Cannot commit after the initialization");
-  }
+  struct cf_context *cc = cf_get_context();
+  cc->postpone_commit++;
 }
 
 int
-cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
+cf_close_group(void)
 {
-  struct cf_context *cc = cf_obtain_context();
-  cc->postpone_commit = 1;
-
-  while (1) {
-    int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
-    if (res == 'S' || res == 'C' || res == 0x64436667)
-    {
-      if (cc->other_options)
-       die("The -S and -C options must precede all other arguments");
-      if (res == 'S') {
-       load_default(cc);
-       if (cf_set(optarg))
-         die("Cannot set %s", optarg);
-      } else if (res == 'C') {
-       if (cf_load(optarg))
-         die("Cannot load config file %s", optarg);
-      }
-#ifdef CONFIG_UCW_DEBUG
-      else {   /* --dumpconfig */
-       load_default(cc);
-       final_commit(cc);
-       struct fastbuf *b = bfdopen(1, 4096);
-       cf_dump_sections(b);
-       bclose(b);
-       exit(0);
-      }
-#endif
-    } else {
-      /* unhandled option or end of options */
-      if (res != ':' && res != '?') {
-       load_default(cc);
-       final_commit(cc);
-      }
-      cc->other_options++;
-      return res;
-    }
-  }
+  struct cf_context *cc = cf_get_context();
+  ASSERT(cc->postpone_commit);
+  if (!--cc->postpone_commit)
+    return maybe_commit(cc);
+  else
+    return 0;
 }