MXS-2346 Provide new configuration mechanism

The configuration mechanism consists of the following concepts:

Specification
  Specifies the available configuration parameters of a module,
  their names and their types.
Param
  Specifies a parameter, its name and its type.
Type
  Specifies the type of a configuration parameters; Bool, Size,
  Count, etc.
Configuration
  Specifies the configuration values of a particular instance of
  the module. Configuration walks hand in hand with Specification,
  the latter specifies what the former should contain.

A Specification is capable of configuring a Configuration from a
MXS_CONFIG_PARAMETER, checking in the process that all parameters
are of the correct type and that the required parameters are present.

A Specification is capable of persisting itself so that it later
can be read back.

The mechanism is closed for modification but open for extension in
the sense that if a module requires a custom parameter, all it needs
to do is to derive one class from Param and another from Type.

The canonical way for using this mechanism is as follows. Consider
a module xyx that has three parameters; a parameter called
"enabled" that is of boolean type, a parameter called "period"
that is of duration type, and a parameter "cache" that is of
size type. That would be declared as follows:

    // xyz.hh
    class XYZSession;

    class XYZ : public maxscale::Filter<XYZ, XYZSession>
    {
    public:
        static XYZ* create(const char* zName, MXS_CONFIG_PARAMETER* pParams);

    private:
        XYZ();

        static config::Specification                       s_specification;
        static config::ParamBool                           s_enabled;
        static config::ParamDuration<std::chrono::seconds> s_period;
        static config::ParamSize                           s_cache;

        config::Configuration                              m_configuration;
        config::Bool                                       m_enabled;
        config::Duration<std::chrono::seconds>             m_period;
        config::Size                                       m_cache;
    };

    // xyz.cc

    config::Specification XYZ::s_specification(MXS_MODULE_NAME);

    config::ParamBool XYZ::s_enabled(
        &s_specification,
        "enabled",
        "Specifies whether ... should be enabled or not."
        );
    config::ParamDuration<std::chrono::seconds> XYZ::s_period(
        &s_specification,
        "period",
        "Specifies the period. Rounded to the nearest second."
        );
    config::ParamSize XYZ::s_cache(
        &s_specification,
        "cache",
        "Specifies the size of the internal cache."
        );

    XYZ::XYZ()
        : m_configuration(&s_specification)
        , m_enabled(&m_configuration, &s_enabled)
        , m_period(&m_configuration, &s_period)
        , m_cache(&m_configuration, &s_cache)
    {
    }

    XYZ* XYZ::create(const char* zName, MXS_CONFIG_PARAMETER* pParams)
    {
        XYZ* pXyz = new XYZ;

        if (!s_specification.configure(pXyz->m_configuration, pParams))
        {
            delete pXyz;
            pXyz = nullptr;
        }

        return pXyz;
    }
This commit is contained in:
Johan Wikman
2019-02-20 13:53:20 +02:00
parent d2c71472b0
commit 09702ab0a0
8 changed files with 2413 additions and 20 deletions

View File

@ -665,3 +665,25 @@ inline bool config_is_valid_name(const std::string& name, std::string* reason =
{
return config_is_valid_name(name.c_str());
}
// TEMPORARILY EXPOSED.
bool check_path_parameter(const MXS_MODULE_PARAM* params, const char* value);
/**
* Converts a string into a duration, intepreting in a case-insensitive manner
* an 'h'-suffix to indicate hours, an 'm'-suffix to indicate minutes, an
* 's'-suffix to indicate seconds and an 'ms'-suffix to indicate milliseconds.
*
* @param zValue A numerical string, possibly suffixed by 'h', 'm',
* 's' or 'ms'.
* @param interpretation How a value lacking a specific suffix should be interpreted.
* @param pDuration Pointer, if non-NULL, where the result is stored.
* @param pUnit Pointer, if non-NULL, where the detected unit is stored.
*
* @return True on success, false on invalid input in which case @c pUnit and
* @c pDuration will not be modified.
*/
bool get_suffixed_duration(const char* zValue,
mxs::config::DurationInterpretation interpretation,
std::chrono::milliseconds* pDuration,
mxs::config::DurationUnit* pUnit = nullptr);

1349
include/maxscale/config2.hh Normal file

File diff suppressed because it is too large Load Diff