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)
}
#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)
{
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);
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);
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);
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);
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);
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);
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;
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: */
#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 {
/* 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 */
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);
/*
* 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