Add framework for declaration of module parameters

The MXS_MODULE structure now contains a member for parameters. This can be
used by the modules to declare accepted parameters, their types and the
default values. Currently only count, integer, boolean, string and enum
values are supported.
This commit is contained in:
Markus Mäkelä 2017-01-04 08:21:09 +02:00
parent 83957a503c
commit 241dbb464a
3 changed files with 184 additions and 3 deletions

View File

@ -33,6 +33,7 @@
#include <sys/utsname.h>
#include <openssl/sha.h>
#include <maxscale/gw_ssl.h>
#include <maxscale/modinfo.h>
MXS_BEGIN_DECLS
@ -211,6 +212,64 @@ bool config_is_ssl_parameter(const char *key);
*/
SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *error_count);
/**
* @brief Check if a configuration parameter is valid
*
* If a module has declared parameters and parameters were given to the module,
* the given parameters are compared to the expected ones. This function also
* does preliminary type checking for various basic values as well as enumerations.
*
* @param module Module name
* @param key Parameter key
* @param value Parameter value
*
* @return True if the configuration parameter is valid
*/
bool config_param_is_valid(const char *module, const char *key, const char *value);
/**
* @brief Get a boolean value
*
* @param params List of configuration parameters
* @param key Parameter name
*
* @return The value as a boolean
*/
bool config_get_bool(const CONFIG_PARAMETER *params, const char *key);
/**
* @brief Get an integer value
*
* This is used for both MXS_MODULE_PARAM_INT and MXS_MODULE_PARAM_COUNT.
*
* @param params List of configuration parameters
* @param key Parameter name
*
* @return The integer value of the parameter
*/
int config_get_integer(const CONFIG_PARAMETER *params, const char *key);
/**
* @brief Get a string value
*
* @param params List of configuration parameters
* @param key Parameter name
*
* @return The raw string value */
const char* config_get_string(const CONFIG_PARAMETER *params, const char *key);
/**
* @brief Get a enumeration value
*
* @param params List of configuration parameters
* @param key Parameter name
*
* @return The raw string value
*
* TODO: Allow multiple enumeration values
*/
const char* config_get_enum(const CONFIG_PARAMETER *params, const char *key);
char* config_clean_string_list(const char* str);
CONFIG_PARAMETER* config_clone_param(const CONFIG_PARAMETER* param);
void config_enable_feedback_task(void);

View File

@ -76,6 +76,24 @@ typedef struct
int patch;
} MXS_MODULE_VERSION;
enum mxs_module_param_type
{
MXS_MODULE_PARAM_COUNT, /**< Non-negative number */
MXS_MODULE_PARAM_INT, /**< Integer number */
MXS_MODULE_PARAM_BOOL, /**< Boolean value */
MXS_MODULE_PARAM_STRING, /**< String value */
MXS_MODULE_PARAM_ENUM /**< Enumeration of string values */
};
/** Module parameter declaration */
typedef struct mxs_module_param
{
const char *name; /**< Name of the parameter */
enum mxs_module_param_type type; /**< Type of the parameter */
const char *default_value;
const char **accepted_values; /**< Only for enum values */
} MXS_MODULE_PARAM;
/**
* The module information structure
*/
@ -87,8 +105,15 @@ typedef struct
const char *description; /**< Module description */
const char *version; /**< Module version */
void *module_object; /**< Module type specific API implementation */
MXS_MODULE_PARAM parameters[]; /**< Declared parameters */
} MXS_MODULE;
/**
* This should be the last value given to @c parameters. If the module has no
* parameters, it should be the only value.
*/
#define MXS_END_MODULE_PARAMS .name = NULL
/**
* Name of the module entry point
*

View File

@ -83,7 +83,7 @@ static bool process_config_context(CONFIG_CONTEXT *);
static bool process_config_update(CONFIG_CONTEXT *);
static char *config_get_value(CONFIG_PARAMETER *, const char *);
static char *config_get_password(CONFIG_PARAMETER *);
static const char *config_get_value_string(CONFIG_PARAMETER *, const char *);
static const char* config_get_value_string(const CONFIG_PARAMETER *params, const char *name);
static int handle_global_item(const char *, const char *);
static int handle_feedback_item(const char *, const char *);
static void global_defaults();
@ -916,8 +916,7 @@ config_get_password(CONFIG_PARAMETER *params)
* @param name The parameter to return
* @return the parameter value or null string if not found
*/
static const char *
config_get_value_string(CONFIG_PARAMETER *params, const char *name)
static const char* config_get_value_string(const CONFIG_PARAMETER *params, const char *name)
{
while (params)
{
@ -1055,6 +1054,34 @@ return_succp:
return succp;
}
bool config_get_bool(const CONFIG_PARAMETER *params, const char *key)
{
const char *value = config_get_value_string(params, key);
ss_dassert(*value);
return config_truth_value(value);
}
int config_get_integer(const CONFIG_PARAMETER *params, const char *key)
{
const char *value = config_get_value_string(params, key);
ss_dassert(*value);
return strtol(value, NULL, 10);
}
const char* config_get_string(const CONFIG_PARAMETER *params, const char *key)
{
const char *value = config_get_value_string(params, key);
ss_dassert(*value);
return value;
}
const char* config_get_enum(const CONFIG_PARAMETER *params, const char *key)
{
const char *value = config_get_value_string(params, key);
ss_dassert(*value);
return value;
}
CONFIG_PARAMETER* config_clone_param(const CONFIG_PARAMETER* param)
{
CONFIG_PARAMETER* p2;
@ -3268,3 +3295,73 @@ bool config_is_ssl_parameter(const char *key)
return false;
}
bool config_param_is_valid(const char *module, const char *key, const char *value)
{
bool valid = false;
const MXS_MODULE *mod = get_module(module);
if (mod)
{
for (int i = 0; mod->parameters[i].name && !valid; i++)
{
if (strcmp(mod->parameters[i].name, key) == 0)
{
char *endptr;
switch (mod->parameters[i].type)
{
case MXS_MODULE_PARAM_COUNT:
if ((strtol(value, &endptr, 10)) >= 0 && endptr != value && *endptr == '\0')
{
valid = true;
}
break;
case MXS_MODULE_PARAM_INT:
strtol(value, &endptr, 10);
if (endptr != value && *endptr == '\0')
{
valid = true;
}
break;
case MXS_MODULE_PARAM_BOOL:
if (config_truth_value(value) != -1)
{
valid = true;
}
break;
case MXS_MODULE_PARAM_STRING:
if (*value)
{
valid = true;
}
break;
case MXS_MODULE_PARAM_ENUM:
if (mod->parameters[i].accepted_values)
{
for (int j = 0; mod->parameters[i].accepted_values[j]; j++)
{
if (strcmp(mod->parameters[i].accepted_values[j], value) == 0)
{
valid = true;
break;
}
}
}
break;
default:
MXS_ERROR("Unexpected module parameter type: %d", mod->parameters[i].type);
ss_dassert(false);
break;
}
}
}
}
return valid;
}