]> sourceware.org Git - lvm2.git/commitdiff
config: add CFG_DEFAULT_RUN_TIME for config options with runtime defaults
authorPeter Rajnoha <prajnoha@redhat.com>
Mon, 3 Mar 2014 11:34:11 +0000 (12:34 +0100)
committerPeter Rajnoha <prajnoha@redhat.com>
Thu, 6 Mar 2014 09:54:17 +0000 (10:54 +0100)
Previously, we declared a default value as undefined ("NULL") for
settings which require runtime context to be set first (e.g. settings
for paths that rely on SYSTEM_DIR environment variable or they depend
on any other setting in some way).

If we want to output default values as they are really used in runtime,
we should make it possible to define a default value as function which
is evaluated, not just providing a firm constant value as it was before.

This patch defines simple prototypes for such functions. Also, there's
new helper macros "cfg_runtime" and "cfg_array_runtime" - they provide
exactly the same functionality as the original "cfg" and "cfg_array"
macros when defining the configuration settings in config_settings.h,
but they don't set the constant default value. Instead, they automatically
link the configuration setting definition with one of these functions:

  typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
  typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
  typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
  typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
  typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);

(The new macros actually set the CFG_DEFAULT_RUNTIME flag properly and
set the default value link to the function accordingly).

Then such configuration setting requires a function of selected type to
be defined. This function has a predefined name:

  get_default_<id>

...where the <id> is the id of the setting as defined in
config_settings.h. For example "backup_archive_dir_CFG" if defined
as a setting with default value evaluated in runtime with "cfg_runtime"
will automatically have "get_default_backup_archive_dir_CFG" function
linked to this setting to get the default value.

lib/config/config.c
lib/config/config.h
lib/config/config_settings.h
tools/dumpconfig.c

index cef00a0708d5218da34c3a68f112383cd812d755..5c6b5baa69bef296199a35faea9fbb7b0e5169f8 100644 (file)
@@ -62,11 +62,15 @@ struct config_source {
 static struct cfg_def_item _cfg_def_items[CFG_COUNT + 1] = {
 #define cfg_section(id, name, parent, flags, since_version, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, flags, since_version, comment},
 #define cfg(id, name, parent, flags, type, default_value, since_version, comment) {id, parent, name, type, {.v_##type = default_value}, flags, since_version, comment},
+#define cfg_runtime(id, name, parent, flags, type, since_version, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
 #define cfg_array(id, name, parent, flags, types, default_value, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.v_CFG_TYPE_STRING = default_value}, flags, since_version, comment},
+#define cfg_array_runtime(id, name, parent, flags, types, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.fn_CFG_TYPE_STRING = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
 #include "config_settings.h"
 #undef cfg_section
 #undef cfg
+#undef cfg_runtime
 #undef cfg_array
+#undef cfg_array_runtime
 };
 
 config_source_t config_get_source_type(struct dm_config_tree *cft)
@@ -474,7 +478,8 @@ time_t config_file_timestamp(struct dm_config_tree *cft)
 }
 
 #define cfg_def_get_item_p(id) (&_cfg_def_items[id])
-#define cfg_def_get_default_value(item,type) item->default_value.v_##type
+#define cfg_def_get_default_value(cmd,item,type,profile) ((item->flags & CFG_DEFAULT_RUN_TIME) ? item->default_value.fn_##type(cmd,profile) : item->default_value.v_##type)
+
 
 static int _cfg_def_make_path(char *buf, size_t buf_size, int id, cfg_def_item_t *item, int xlate)
 {
@@ -844,7 +849,7 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile
        if (item->type != CFG_TYPE_STRING)
                log_error(INTERNAL_ERROR "%s cfg tree element not declared as string.", path);
 
-       str = dm_config_tree_find_str(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_STRING));
+       str = dm_config_tree_find_str(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -870,7 +875,7 @@ const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, st
        if (!(item->flags & CFG_ALLOW_EMPTY))
                log_error(INTERNAL_ERROR "%s cfg tree element not declared to allow empty values.", path);
 
-       str = dm_config_tree_find_str_allow_empty(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_STRING));
+       str = dm_config_tree_find_str_allow_empty(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -894,7 +899,7 @@ int find_config_tree_int(struct cmd_context *cmd, int id, struct profile *profil
        if (item->type != CFG_TYPE_INT)
                log_error(INTERNAL_ERROR "%s cfg tree element not declared as integer.", path);
 
-       i = dm_config_tree_find_int(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_INT));
+       i = dm_config_tree_find_int(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -918,7 +923,7 @@ int64_t find_config_tree_int64(struct cmd_context *cmd, int id, struct profile *
        if (item->type != CFG_TYPE_INT)
                log_error(INTERNAL_ERROR "%s cfg tree element not declared as integer.", path);
 
-       i64 = dm_config_tree_find_int64(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_INT));
+       i64 = dm_config_tree_find_int64(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -942,7 +947,7 @@ float find_config_tree_float(struct cmd_context *cmd, int id, struct profile *pr
        if (item->type != CFG_TYPE_FLOAT)
                log_error(INTERNAL_ERROR "%s cfg tree element not declared as float.", path);
 
-       f = dm_config_tree_find_float(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_FLOAT));
+       f = dm_config_tree_find_float(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_FLOAT, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -966,7 +971,7 @@ int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profi
        if (item->type != CFG_TYPE_BOOL)
                log_error(INTERNAL_ERROR "%s cfg tree element not declared as boolean.", path);
 
-       b = dm_config_tree_find_bool(cmd->cft, path, cfg_def_get_default_value(item, CFG_TYPE_BOOL));
+       b = dm_config_tree_find_bool(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, profile));
 
        if (profile_applied)
                remove_config_tree_by_source(cmd, CONFIG_PROFILE);
@@ -1353,19 +1358,19 @@ static struct dm_config_node *_add_def_node(struct dm_config_tree *cft,
                                break;
                        case CFG_TYPE_BOOL:
                                cn->v->type = DM_CFG_INT;
-                               cn->v->v.i = cfg_def_get_default_value(def, CFG_TYPE_BOOL);
+                               cn->v->v.i = cfg_def_get_default_value(spec->cmd, def, CFG_TYPE_BOOL, NULL);
                                break;
                        case CFG_TYPE_INT:
                                cn->v->type = DM_CFG_INT;
-                               cn->v->v.i = cfg_def_get_default_value(def, CFG_TYPE_INT);
+                               cn->v->v.i = cfg_def_get_default_value(spec->cmd, def, CFG_TYPE_INT, NULL);
                                break;
                        case CFG_TYPE_FLOAT:
                                cn->v->type = DM_CFG_FLOAT;
-                               cn->v->v.f = cfg_def_get_default_value(def, CFG_TYPE_FLOAT);
+                               cn->v->v.f = cfg_def_get_default_value(spec->cmd, def, CFG_TYPE_FLOAT, NULL);
                                break;
                        case CFG_TYPE_STRING:
                                cn->v->type = DM_CFG_STRING;
-                               if (!(str = cfg_def_get_default_value(def, CFG_TYPE_STRING)))
+                               if (!(str = cfg_def_get_default_value(spec->cmd, def, CFG_TYPE_STRING, NULL)))
                                        str = "";
                                cn->v->v.str = str;
                                break;
index f716efb6cbcb94ab636675aee0c7edb8d01fa3e4..aec72a008dd8555baf0ee513122188e95b83e7ad 100644 (file)
@@ -63,11 +63,28 @@ typedef enum {
        CFG_TYPE_STRING =       1 << 5, /* setting */
 } cfg_def_type_t;
 
+typedef struct cfg_def_item cfg_def_item_t;
+
+/* function types to evaluate default value at runtime */
+typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
+typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
+typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
+typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
+typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);
+
 /* configuration definition item value (for item's default value) */
 typedef union {
+       /* static value - returns a variable */
        const int v_CFG_TYPE_BOOL, v_CFG_TYPE_INT;
        const float v_CFG_TYPE_FLOAT;
        const char *v_CFG_TYPE_STRING, *v_CFG_TYPE_ARRAY;
+
+       /* run-time value - evaluates a function */
+       t_fn_CFG_TYPE_BOOL fn_CFG_TYPE_BOOL;
+       t_fn_CFG_TYPE_INT fn_CFG_TYPE_INT;
+       t_fn_CFG_TYPE_FLOAT fn_CFG_TYPE_FLOAT;
+       t_fn_CFG_TYPE_STRING fn_CFG_TYPE_STRING;
+       t_fn_CFG_TYPE_ARRAY fn_CFG_TYPE_ARRAY;
 } cfg_def_value_t;
 
 /* configuration definition item flags: */
@@ -84,6 +101,8 @@ typedef union {
 #define CFG_PROFILABLE         0x10
 /* whether the default value is undefned */
 #define CFG_DEFAULT_UNDEFINED  0x20
+/* whether the defualt value is calculated during run time */
+#define CFG_DEFAULT_RUN_TIME   0x40
 
 /* configuration definition item structure */
 typedef struct cfg_def_item {
@@ -109,6 +128,7 @@ typedef enum {
 
 /* configuration definition tree specification */
 struct config_def_tree_spec {
+       struct cmd_context *cmd;        /* command context (for run-time defaults */
        cfg_def_tree_t type;            /* tree type */
        uint16_t version;               /* tree at this LVM2 version */
        int ignoreadvanced:1;           /* do not include advanced configs */
@@ -130,11 +150,15 @@ struct config_def_tree_spec {
 enum {
 #define cfg_section(id, name, parent, flags, since_version, comment) id,
 #define cfg(id, name, parent, flags, type, default_value, since_version, comment) id,
+#define cfg_runtime(id, name, parent, flags, type, since_version, comment) id,
 #define cfg_array(id, name, parent, flags, types, default_value, since_version, comment) id,
+#define cfg_array_runtime(id, name, parent, flags, types, since_version, comment) id,
 #include "config_settings.h"
 #undef cfg_section
 #undef cfg
+#undef cfg_runtime
 #undef cfg_array
+#undef cfg_array_runtime
 };
 
 struct profile *add_profile(struct cmd_context *cmd, const char *profile_name);
index eb89e873750dd3327cdcd07c665f06e2c21f96ff..8d3d304eb13a2154961fb3f61d0808210db67942 100644 (file)
 
 /*
  * MACROS:
- * cfg_section(id, name, parent, flags, since_version, comment)
- * cfg(id, name, parent, flags, type, default_value, since_version, comment)
- * cfg_array(id, name, parent, flags, types, default_value, since_version, comment)
+ * - define a configuration section:
+ *   cfg_section(id, name, parent, flags, since_version, comment)
  *
- * VARIABLES:
- * cfg_section:                define a new configuration section
- * cfg:                        define a new configuration setting of a simple type
- * cfg_array:          define a new configuration setting of array type
+ * - define a configuration setting of simple type:
+ *   cfg(id, name, parent, flags, type, default_value, since_version, comment)
+ *
+ * - define a configuration array of one or more types:
+ *   cfg_array(id, name, parent, flags, types, default_value, since_version, comment)
+ *
+ * If default value can't be assigned statically because it depends on some
+ * run-time checks or if it depends on other settings already defined,
+ * the configuration setting  or array can be defined with the
+ * "{cfg|cfg_array}_runtime" macro. In this case the  default value
+ * is evaluated by automatically calling "get_default_<id>" function.
+ * See config.h and "function types to evaluate default value at runtime".
  *
+ *
+ * VARIABLES:
  * id:                 unique identifier
  * name:               configuration node name
  * parent:             id of parent configuration node
index cb88bc6460ca9b827361714beb9b8ada15ecb9bd..dd86733896345ada154e5d80df14ca10ca53a00b 100644 (file)
@@ -97,6 +97,8 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
        struct cft_check_handle *cft_check_handle = NULL;
        int r = ECMD_PROCESSED;
 
+       tree_spec.cmd = cmd;
+
        if (arg_count(cmd, configtype_ARG) && arg_count(cmd, validate_ARG)) {
                log_error("Only one of --type and --validate permitted.");
                return EINVALID_CMD_LINE;
This page took 0.045268 seconds and 5 git commands to generate.