]> sourceware.org Git - lvm2.git/commitdiff
config: add support for enhanced config node output
authorPeter Rajnoha <prajnoha@redhat.com>
Tue, 5 Mar 2013 17:02:13 +0000 (18:02 +0100)
committerPeter Rajnoha <prajnoha@redhat.com>
Wed, 6 Mar 2013 09:46:36 +0000 (10:46 +0100)
There's a possibility to interconnect the dm_config_node with an
ID, which in our case is used to reference the configuration
definition ID from config_settings.h. So simply interconnecting
struct dm_config_node with struct cfg_def_item.

This patch also adds support for enhanced config node output besides
existing "output line by line". This patch adds a possibility to
register a callback that gets called *before* the config node is
processed line by line (for example to include any headers on output)
and *after* the config node is processed line by line (to include any
footers on output). Also, it adds the config node reference itself
as the callback arg in addition to have a possibility to extract more
information from the config node itself if needed when processing the
output callback (e.g. the key name, the id, or whether this is a
section or a value etc...).

If the config node from lvm.conf/--config tree is recognized and valid,
it's always coupled with the config node definition ID from
config_settings.h:

 struct dm_config_node {
   int id;
   const char *key;
   struct dm_config_node *parent, *sib, *child;
   struct dm_config_value *v;
 }

For example if the dm_config_node *cn holds "devices/dev" configuration,
then the cn->id holds "devices_dev_CFG" ID from config_settings.h, -1 if
not found in config_settings.h and 0 if matching has not yet been done.

To support the enhanced config node output, a new structure has been
defined in libdevmapper to register it:

  struct dm_config_node_out_spec {
    dm_config_node_out_fn prefix_fn; /* called before processing config node lines */
    dm_config_node_out_fn line_fn; /* called for each config node line */
    dm_config_node_out_fn suffix_fn; /* called after processing config node lines */
  };

Where dm_config_node_out_fn is:

  typedef int (*dm_config_node_out_fn)(const struct dm_config_node *cn, const char *line, void *baton);

(so in comparison to existing callbacks for config node output, it has
an extra dm_config_node *cn arg in addition)

This patch also adds these functions to libdevmapper:
  - dm_config_write_node_out
  - dm_config_write_one_node_out

...which have exactly the same functionality as their counterparts
without the "out" suffix. The "*_out" functions adds the extra hooks
for enhanced config output (prefix_fn and suffix_fn mentioned above).

One can still use the old interface for config node output, this is
just an enhancement for those who'd like to modify the output more
extensively.

lib/config/config.c
libdm/libdevmapper.h
libdm/libdm-config.c

index a02f478953b1a75170d1c503ecf9b9e1cca83ef9..5a51a2966043523314220277fbae5c37e00be0ae 100644 (file)
@@ -472,6 +472,7 @@ static int _config_def_check_node(const char *vp, char *pvp, char *rp, char *prp
                if (cn->v) {
                        log_warn_suppress(suppress_messages,
                                "Configuration setting \"%s\" unknown.", rp);
+                       cn->id = -1;
                        return 0;
                }
 
@@ -482,11 +483,14 @@ static int _config_def_check_node(const char *vp, char *pvp, char *rp, char *prp
                if (!(def = (cfg_def_item_t *) dm_hash_lookup(ht, vp))) {
                        log_warn_suppress(suppress_messages,
                                "Configuration section \"%s\" unknown.", rp);
+                       cn->id = -1;
                        return 0;
                }
        }
 
        def->flags |= CFG_USED;
+       cn->id = def->id;
+
        if (!_config_def_check_node_value(rp, cn->v, def, suppress_messages))
        return 0;
 
@@ -962,6 +966,8 @@ static struct dm_config_node *_add_def_node(struct dm_config_tree *cft,
                return NULL;
        }
 
+       cn->id = def->id;
+
        if (!(def->type & CFG_TYPE_ARRAY)) {
                switch (def->type) {
                        case CFG_TYPE_SECTION:
index 8c349c507a1e582f57f11d4e1921155edb29334c..0460afab3647de2083670579f10b0b8804eb2025 100644 (file)
@@ -1496,6 +1496,7 @@ struct dm_config_value {
 };
 
 struct dm_config_node {
+       int id;
        const char *key;
        struct dm_config_node *parent, *sib, *child;
        struct dm_config_value *v;
@@ -1528,11 +1529,27 @@ struct dm_config_tree *dm_config_remove_cascaded_tree(struct dm_config_tree *cft
 
 void dm_config_destroy(struct dm_config_tree *cft);
 
+/* Simple output line by line. */
 typedef int (*dm_putline_fn)(const char *line, void *baton);
+/* More advaced output with config node reference. */
+typedef int (*dm_config_node_out_fn)(const struct dm_config_node *cn, const char *line, void *baton);
+
+/*
+ * Specification for advanced config node output.
+ */
+struct dm_config_node_out_spec {
+       dm_config_node_out_fn prefix_fn; /* called before processing config node lines */
+       dm_config_node_out_fn line_fn; /* called for each config node line */
+       dm_config_node_out_fn suffix_fn; /* called after processing config node lines */
+};
+
 /* Write the node and any subsequent siblings it has. */
 int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton);
+int dm_config_write_node_out(const struct dm_config_node *cn, const struct dm_config_node_out_spec *out_spec, void *baton);
+
 /* Write given node only without subsequent siblings. */
 int dm_config_write_one_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton);
+int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct dm_config_node_out_spec *out_spec, void *baton);
 
 struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path);
 int dm_config_has_node(const struct dm_config_node *cn, const char *path);
index 4705a1cceaac1d53425d05bc46d4154f7ad413ba..368f9e33866a0a8049c26c196cb373dca8e18ec0 100644 (file)
@@ -50,10 +50,11 @@ struct parser {
        struct dm_pool *mem;
 };
 
-struct output_line {
+struct config_output {
        struct dm_pool *mem;
        dm_putline_fn putline;
-       void *putline_baton;
+       const struct dm_config_node_out_spec *spec;
+       void *baton;
 };
 
 static void _get_token(struct parser *p, int tok_prev);
@@ -189,9 +190,9 @@ struct dm_config_tree *dm_config_from_string(const char *config_settings)
        return cft;
 }
 
-static int _line_start(struct output_line *outline)
+static int _line_start(struct config_output *out)
 {
-       if (!dm_pool_begin_object(outline->mem, 128)) {
+       if (!dm_pool_begin_object(out->mem, 128)) {
                log_error("dm_pool_begin_object failed for config line");
                return 0;
        }
@@ -200,7 +201,7 @@ static int _line_start(struct output_line *outline)
 }
 
 __attribute__ ((format(printf, 2, 3)))
-static int _line_append(struct output_line *outline, const char *fmt, ...)
+static int _line_append(struct config_output *out, const char *fmt, ...)
 {
        char buf[4096];
        va_list ap;
@@ -215,7 +216,7 @@ static int _line_append(struct output_line *outline, const char *fmt, ...)
                return 0;
        }
 
-       if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
+       if (!dm_pool_grow_object(out->mem, &buf[0], strlen(buf))) {
                log_error("dm_pool_grow_object failed for config line");
                return 0;
        }
@@ -223,28 +224,32 @@ static int _line_append(struct output_line *outline, const char *fmt, ...)
        return 1;
 }
 
-#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
+#define line_append(args...) do {if (!_line_append(out, args)) {return_0;}} while (0)
 
-static int _line_end(struct output_line *outline)
+static int _line_end(const struct dm_config_node *cn, struct config_output *out)
 {
        const char *line;
 
-       if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
+       if (!dm_pool_grow_object(out->mem, "\0", 1)) {
                log_error("dm_pool_grow_object failed for config line");
                return 0;
        }
 
-       line = dm_pool_end_object(outline->mem);
+       line = dm_pool_end_object(out->mem);
 
-       if (!outline->putline)
+       if (!out->putline && !out->spec)
                return 0;
 
-       outline->putline(line, outline->putline_baton);
+       if (out->putline)
+               out->putline(line, out->baton);
+
+       if (out->spec && out->spec->line_fn)
+               out->spec->line_fn(cn, line, out->baton);
 
        return 1;
 }
 
-static int _write_value(struct output_line *outline, const struct dm_config_value *v)
+static int _write_value(struct config_output *out, const struct dm_config_value *v)
 {
        char *buf;
 
@@ -279,7 +284,7 @@ static int _write_value(struct output_line *outline, const struct dm_config_valu
 }
 
 static int _write_config(const struct dm_config_node *n, int only_one,
-                        struct output_line *outline, int level)
+                        struct config_output *out, int level)
 {
        char space[MAX_INDENT + 1];
        int l = (level < MAX_INDENT) ? level : MAX_INDENT;
@@ -293,16 +298,19 @@ static int _write_config(const struct dm_config_node *n, int only_one,
        space[i] = '\0';
 
        do {
-               if (!_line_start(outline))
+               if (out->spec && out->spec->prefix_fn)
+                       out->spec->prefix_fn(n, space, out->baton);
+
+               if (!_line_start(out))
                        return_0;
                line_append("%s%s", space, n->key);
                if (!n->v) {
                        /* it's a sub section */
                        line_append(" {");
-                       if (!_line_end(outline))
+                       if (!_line_end(n, out))
                                return_0;
-                       _write_config(n->child, 0, outline, level + 1);
-                       if (!_line_start(outline))
+                       _write_config(n->child, 0, out, level + 1);
+                       if (!_line_start(out))
                                return_0;
                        line_append("%s}", space);
                } else {
@@ -312,7 +320,7 @@ static int _write_config(const struct dm_config_node *n, int only_one,
                        if (v->next) {
                                line_append("[");
                                while (v && v->type != DM_CFG_EMPTY_ARRAY) {
-                                       if (!_write_value(outline, v))
+                                       if (!_write_value(out, v))
                                                return_0;
                                        v = v->next;
                                        if (v && v->type != DM_CFG_EMPTY_ARRAY)
@@ -320,11 +328,15 @@ static int _write_config(const struct dm_config_node *n, int only_one,
                                }
                                line_append("]");
                        } else
-                               if (!_write_value(outline, v))
+                               if (!_write_value(out, v))
                                        return_0;
                }
-               if (!_line_end(outline))
+               if (!_line_end(n, out))
                        return_0;
+
+               if (out->spec && out->spec->suffix_fn)
+                       out->spec->suffix_fn(n, space, out->baton);
+
                n = n->sib;
        } while (n && !only_one);
        /* FIXME: add error checking */
@@ -332,29 +344,46 @@ static int _write_config(const struct dm_config_node *n, int only_one,
 }
 
 static int _write_node(const struct dm_config_node *cn, int only_one,
-                      dm_putline_fn putline, void *baton)
+                      dm_putline_fn putline,
+                      const struct dm_config_node_out_spec *out_spec,
+                      void *baton)
 {
-       struct output_line outline;
-       if (!(outline.mem = dm_pool_create("config_line", 1024)))
+       struct config_output out;
+       if (!(out.mem = dm_pool_create("config_output", 1024)))
                return_0;
-       outline.putline = putline;
-       outline.putline_baton = baton;
-       if (!_write_config(cn, only_one, &outline, 0)) {
-               dm_pool_destroy(outline.mem);
+       out.putline = putline;
+       out.spec = out_spec;
+       out.baton = baton;
+       if (!_write_config(cn, only_one, &out, 0)) {
+               dm_pool_destroy(out.mem);
                return_0;
        }
-       dm_pool_destroy(outline.mem);
+       dm_pool_destroy(out.mem);
        return 1;
 }
 
 int dm_config_write_one_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton)
 {
-       return _write_node(cn, 1, putline, baton);
+       return _write_node(cn, 1, putline, NULL, baton);
 }
 
 int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton)
 {
-       return _write_node(cn, 0, putline, baton);
+       return _write_node(cn, 0, putline, NULL, baton);
+}
+
+int dm_config_write_one_node_out(const struct dm_config_node *cn,
+                                const struct dm_config_node_out_spec *out_spec,
+                                void *baton)
+{
+       return _write_node(cn, 1, NULL, out_spec, baton);
+}
+
+int dm_config_write_node_out(const struct dm_config_node *cn,
+                            const struct dm_config_node_out_spec *out_spec,
+                            void *baton)
+{
+       return _write_node(cn, 0, NULL, out_spec, baton);
 }
 
 /*
This page took 0.050346 seconds and 5 git commands to generate.