1592 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1592 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2018 MariaDB Corporation Ab
 | 
						|
 *
 | 
						|
 * Use of this software is governed by the Business Source License included
 | 
						|
 * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | 
						|
 *
 | 
						|
 * Change Date: 2025-10-29
 | 
						|
 *
 | 
						|
 * On the date above, in accordance with the Business Source License, use
 | 
						|
 * of this software will be governed by version 2 or later of the General
 | 
						|
 * Public License.
 | 
						|
 */
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include <maxscale/ccdefs.hh>
 | 
						|
 | 
						|
#include <chrono>
 | 
						|
#include <iostream>
 | 
						|
#include <map>
 | 
						|
#include <set>
 | 
						|
#include <sstream>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
#include <maxbase/alloc.h>
 | 
						|
#include <maxbase/assert.h>
 | 
						|
#include <maxbase/log.hh>
 | 
						|
#include <maxscale/config.hh>
 | 
						|
#include <maxscale/modinfo.h>
 | 
						|
 | 
						|
namespace config
 | 
						|
{
 | 
						|
 | 
						|
class Configuration;
 | 
						|
class Param;
 | 
						|
class Type;
 | 
						|
 | 
						|
// An instance of Specification specifies what parameters a particular module expects
 | 
						|
// and of what type they are.
 | 
						|
class Specification
 | 
						|
{
 | 
						|
public:
 | 
						|
    enum Kind
 | 
						|
    {
 | 
						|
        FILTER,
 | 
						|
        MONITOR,
 | 
						|
        ROUTER
 | 
						|
    };
 | 
						|
 | 
						|
    using ParamsByName = std::map<std::string, Param*>;
 | 
						|
    using const_iterator = ParamsByName::const_iterator;
 | 
						|
    using value_type = ParamsByName::value_type;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor
 | 
						|
     *
 | 
						|
     * @param zModule The the name of the module, e.g. "cachefilter".
 | 
						|
     */
 | 
						|
    Specification(const char* zModule, Kind kind);
 | 
						|
    ~Specification();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return What kind of specification.
 | 
						|
     */
 | 
						|
    Kind kind() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The module name of this specification.
 | 
						|
     */
 | 
						|
    const std::string& module() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     *  Validate parameters
 | 
						|
     *
 | 
						|
     * @param params  Parameters as found in the configuration file.
 | 
						|
     *
 | 
						|
     * @return True, if they represent valid parameters - all mandatory are present,
 | 
						|
     *         all present ones are of corrent type - for this configuration.
 | 
						|
     */
 | 
						|
    bool validate(const MXS_CONFIG_PARAMETER& params) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Configure configuration
 | 
						|
     *
 | 
						|
     * @param configuration  The configuration that should be configured.
 | 
						|
     * @param params         The parameters that should be used, will be validated.
 | 
						|
     *
 | 
						|
     * @return True if could be configured.
 | 
						|
     */
 | 
						|
    bool configure(Configuration& configuration, const MXS_CONFIG_PARAMETER& params) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Find given parameter of the specification.
 | 
						|
     *
 | 
						|
     * @param name  The name of the parameter.
 | 
						|
     *
 | 
						|
     * @return The corresponding parameter object or NULL if the name is not a
 | 
						|
     *         parameter of the specification.
 | 
						|
     */
 | 
						|
    const Param* find_param(const std::string& name) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Document this specification.
 | 
						|
     *
 | 
						|
     * @param out  The stream the documentation should be written to.
 | 
						|
     *
 | 
						|
     * @return @c out
 | 
						|
     */
 | 
						|
    std::ostream& document(std::ostream& out) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Populate legacy parameter definition.
 | 
						|
     *
 | 
						|
     * @note Only for a transitionary period.
 | 
						|
     *
 | 
						|
     * @param module  The module description to be populated with parameters.
 | 
						|
     */
 | 
						|
    void populate(MXS_MODULE& module) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The number of parameters in the specification.
 | 
						|
     */
 | 
						|
    size_t size() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Const iterator to first parameter.
 | 
						|
     */
 | 
						|
    const_iterator cbegin() const
 | 
						|
    {
 | 
						|
        return m_params.cbegin();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Const iterator to one past last parameter.
 | 
						|
     */
 | 
						|
    const_iterator cend() const
 | 
						|
    {
 | 
						|
        return m_params.cend();
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    friend Param;
 | 
						|
 | 
						|
    void insert(Param* pParam);
 | 
						|
    void remove(Param* pParam);
 | 
						|
 | 
						|
private:
 | 
						|
    std::string  m_module;
 | 
						|
    Kind         m_kind;
 | 
						|
    ParamsByName m_params;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * A instance of Param specifies a parameter of a module, that is, its name,
 | 
						|
 * type, default value and whether it is mandatory or optional.
 | 
						|
 */
 | 
						|
class Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    enum Kind
 | 
						|
    {
 | 
						|
        MANDATORY,
 | 
						|
        OPTIONAL
 | 
						|
    };
 | 
						|
 | 
						|
    ~Param();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The name of the parameter.
 | 
						|
     */
 | 
						|
    const std::string& name() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The type of the parameter (human readable).
 | 
						|
     */
 | 
						|
    virtual std::string type() const = 0;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The description of the parameter.
 | 
						|
     */
 | 
						|
    const std::string& description() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Document the parameter.
 | 
						|
     *
 | 
						|
     * The documentation of a parameters consists of its name, its type,
 | 
						|
     * whether it is mandatory or optional (default value documented in
 | 
						|
     * that case), and its description.
 | 
						|
     *
 | 
						|
     * @return The documentation.
 | 
						|
     */
 | 
						|
    std::string documentation() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The kind - mandatory or optional - of the parameter.
 | 
						|
     */
 | 
						|
    Kind kind() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return True, if the parameter is mandatory.
 | 
						|
     */
 | 
						|
    bool is_mandatory() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return True, if the parameter is optional.
 | 
						|
     */
 | 
						|
    bool is_optional() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Synonym for @c is_optional.
 | 
						|
     *
 | 
						|
     * @return True, if the parameter has a default value.
 | 
						|
     */
 | 
						|
    bool has_default_value() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Default value as string.
 | 
						|
     *
 | 
						|
     * @note Meaningful only if @c has_default_value returns true.
 | 
						|
     */
 | 
						|
    virtual std::string default_to_string() const = 0;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Validate a string.
 | 
						|
     *
 | 
						|
     * @param value_as_string  The string to validate.
 | 
						|
     *
 | 
						|
     * @return True, if @c value_as_string can be converted into a value of this type.
 | 
						|
     */
 | 
						|
    virtual bool validate(const std::string& value_as_string, std::string* pMessage) const = 0;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set setting value with value from configuration file.
 | 
						|
     *
 | 
						|
     * @param value            The @c Type to configure.
 | 
						|
     * @param value_as_string  The string value to configure it with.
 | 
						|
     *
 | 
						|
     * @return True, if it could be configured, false otherwise. The
 | 
						|
     *         function will fail only if @c value_as_string is invalid.
 | 
						|
     */
 | 
						|
    virtual bool set(Type& value, const std::string& value_as_string) const = 0;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Populate a legacy parameter specification with data.
 | 
						|
     *
 | 
						|
     * @param param  The legacy parameter specification to be populated.
 | 
						|
     */
 | 
						|
    virtual void populate(MXS_MODULE_PARAM& param) const;
 | 
						|
 | 
						|
protected:
 | 
						|
    Param(Specification* pSpecification,
 | 
						|
          const char* zName,
 | 
						|
          const char* zDescription,
 | 
						|
          Kind kind,
 | 
						|
          mxs_module_param_type legacy_type);
 | 
						|
 | 
						|
private:
 | 
						|
    Specification&        m_specification;
 | 
						|
    std::string           m_name;
 | 
						|
    std::string           m_description;
 | 
						|
    Kind                  m_kind;
 | 
						|
    mxs_module_param_type m_legacy_type;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamBool
 | 
						|
 */
 | 
						|
class ParamBool : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = bool;
 | 
						|
 | 
						|
    ParamBool(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription)
 | 
						|
        : ParamBool(pSpecification, zName, zDescription, Param::MANDATORY, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamBool(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              value_type default_value)
 | 
						|
        : ParamBool(pSpecification, zName, zDescription, Param::OPTIONAL, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamBool(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              Kind kind,
 | 
						|
              value_type default_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_BOOL)
 | 
						|
        , m_default_value(default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    value_type m_default_value;
 | 
						|
};
 | 
						|
 | 
						|
class ParamNumber : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = int64_t;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
 | 
						|
protected:
 | 
						|
    ParamNumber(Specification* pSpecification,
 | 
						|
                const char* zName,
 | 
						|
                const char* zDescription,
 | 
						|
                Kind kind,
 | 
						|
                mxs_module_param_type legacy_type,
 | 
						|
                value_type default_value,
 | 
						|
                value_type min_value,
 | 
						|
                value_type max_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, legacy_type)
 | 
						|
        , m_default_value(default_value)
 | 
						|
        , m_min_value(min_value <= max_value ? min_value : max_value)
 | 
						|
        , m_max_value(max_value)
 | 
						|
    {
 | 
						|
        mxb_assert(min_value <= max_value);
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    value_type m_default_value;
 | 
						|
    value_type m_min_value;
 | 
						|
    value_type m_max_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamCount
 | 
						|
 */
 | 
						|
class ParamCount : public ParamNumber
 | 
						|
{
 | 
						|
public:
 | 
						|
    ParamCount(Specification* pSpecification,
 | 
						|
               const char* zName,
 | 
						|
               const char* zDescription)
 | 
						|
        : ParamCount(pSpecification, zName, zDescription, Param::MANDATORY,
 | 
						|
                     value_type(), 0, std::numeric_limits<uint32_t>::max())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamCount(Specification* pSpecification,
 | 
						|
               const char* zName,
 | 
						|
               const char* zDescription,
 | 
						|
               value_type min_value,
 | 
						|
               value_type max_value)
 | 
						|
        : ParamCount(pSpecification, zName, zDescription, Param::MANDATORY,
 | 
						|
                     value_type(), min_value, max_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamCount(Specification* pSpecification,
 | 
						|
               const char* zName,
 | 
						|
               const char* zDescription,
 | 
						|
               value_type default_value)
 | 
						|
        : ParamCount(pSpecification, zName, zDescription, Param::OPTIONAL,
 | 
						|
                     default_value, 0, std::numeric_limits<uint32_t>::max())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamCount(Specification* pSpecification,
 | 
						|
               const char* zName,
 | 
						|
               const char* zDescription,
 | 
						|
               value_type default_value,
 | 
						|
               value_type min_value,
 | 
						|
               value_type max_value)
 | 
						|
        : ParamCount(pSpecification, zName, zDescription, Param::OPTIONAL,
 | 
						|
                     default_value, min_value, max_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamCount(Specification* pSpecification,
 | 
						|
               const char* zName,
 | 
						|
               const char* zDescription,
 | 
						|
               Kind kind,
 | 
						|
               value_type default_value,
 | 
						|
               value_type min_value,
 | 
						|
               value_type max_value)
 | 
						|
        : ParamNumber(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_COUNT,
 | 
						|
                      default_value,
 | 
						|
                      min_value >= 0 ? min_value : 0,
 | 
						|
                      max_value <= std::numeric_limits<uint32_t>::max() ?
 | 
						|
                      max_value : std::numeric_limits<uint32_t>::max())
 | 
						|
    {
 | 
						|
        mxb_assert(min_value >= 0);
 | 
						|
        mxb_assert(max_value <= std::numeric_limits<uint32_t>::max());
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
using ParamNatural = ParamCount;
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamInteger
 | 
						|
 */
 | 
						|
class ParamInteger : public ParamNumber
 | 
						|
{
 | 
						|
public:
 | 
						|
    ParamInteger(Specification* pSpecification,
 | 
						|
                 const char* zName,
 | 
						|
                 const char* zDescription)
 | 
						|
        : ParamInteger(pSpecification, zName, zDescription, Param::MANDATORY,
 | 
						|
                       value_type(),
 | 
						|
                       std::numeric_limits<int32_t>::min(),
 | 
						|
                       std::numeric_limits<int32_t>::max())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamInteger(Specification* pSpecification,
 | 
						|
                 const char* zName,
 | 
						|
                 const char* zDescription,
 | 
						|
                 value_type min_value,
 | 
						|
                 value_type max_value)
 | 
						|
        : ParamInteger(pSpecification, zName, zDescription, Param::MANDATORY,
 | 
						|
                       value_type(), min_value, max_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamInteger(Specification* pSpecification,
 | 
						|
                 const char* zName,
 | 
						|
                 const char* zDescription,
 | 
						|
                 value_type default_value)
 | 
						|
        : ParamInteger(pSpecification, zName, zDescription, Param::OPTIONAL,
 | 
						|
                       default_value,
 | 
						|
                       std::numeric_limits<int32_t>::min(),
 | 
						|
                       std::numeric_limits<int32_t>::max())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamInteger(Specification* pSpecification,
 | 
						|
                 const char* zName,
 | 
						|
                 const char* zDescription,
 | 
						|
                 value_type default_value,
 | 
						|
                 value_type min_value,
 | 
						|
                 value_type max_value)
 | 
						|
        : ParamInteger(pSpecification, zName, zDescription, Param::OPTIONAL,
 | 
						|
                       default_value, min_value, max_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamInteger(Specification* pSpecification,
 | 
						|
                 const char* zName,
 | 
						|
                 const char* zDescription,
 | 
						|
                 Kind kind,
 | 
						|
                 value_type default_value,
 | 
						|
                 value_type min_value,
 | 
						|
                 value_type max_value)
 | 
						|
        : ParamNumber(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_INT,
 | 
						|
                      default_value,
 | 
						|
                      min_value >= std::numeric_limits<int32_t>::min() ?
 | 
						|
                      min_value : std::numeric_limits<int32_t>::min(),
 | 
						|
                      max_value <= std::numeric_limits<int32_t>::max() ?
 | 
						|
                      max_value : std::numeric_limits<int32_t>::max())
 | 
						|
    {
 | 
						|
        mxb_assert(min_value >= std::numeric_limits<int32_t>::min());
 | 
						|
        mxb_assert(max_value <= std::numeric_limits<int32_t>::max());
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamDuration
 | 
						|
 */
 | 
						|
template<class T>
 | 
						|
class ParamDuration : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = T;
 | 
						|
 | 
						|
    ParamDuration(Specification* pSpecification,
 | 
						|
                  const char* zName,
 | 
						|
                  const char* zDescription,
 | 
						|
                  mxs::config::DurationInterpretation interpretation)
 | 
						|
        : ParamDuration(pSpecification, zName, zDescription, Param::MANDATORY, interpretation, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamDuration(Specification* pSpecification,
 | 
						|
                  const char* zName,
 | 
						|
                  const char* zDescription,
 | 
						|
                  mxs::config::DurationInterpretation interpretation,
 | 
						|
                  value_type default_value)
 | 
						|
        : ParamDuration(pSpecification, zName, zDescription, Param::OPTIONAL, interpretation, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(const value_type& value) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamDuration(Specification* pSpecification,
 | 
						|
                  const char* zName,
 | 
						|
                  const char* zDescription,
 | 
						|
                  Kind kind,
 | 
						|
                  mxs::config::DurationInterpretation interpretation,
 | 
						|
                  value_type default_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_DURATION)
 | 
						|
        , m_interpretation(interpretation)
 | 
						|
        , m_default_value(default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    mxs::config::DurationInterpretation m_interpretation;
 | 
						|
    value_type                          m_default_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamEnum
 | 
						|
 */
 | 
						|
template<class T>
 | 
						|
class ParamEnum : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = T;
 | 
						|
 | 
						|
    ParamEnum(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              const std::vector<std::pair<T, const char*>>& enumeration)
 | 
						|
        : ParamEnum(pSpecification, zName, zDescription, Param::MANDATORY, enumeration, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamEnum(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              const std::vector<std::pair<T, const char*>>& enumeration,
 | 
						|
              value_type default_value)
 | 
						|
        : ParamEnum(pSpecification, zName, zDescription, Param::OPTIONAL, enumeration, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
 | 
						|
    void populate(MXS_MODULE_PARAM& param) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamEnum(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              Kind kind,
 | 
						|
              const std::vector<std::pair<T, const char*>>& enumeration,
 | 
						|
              value_type default_value);
 | 
						|
 | 
						|
private:
 | 
						|
    std::vector<std::pair<T, const char*>> m_enumeration;
 | 
						|
    value_type                             m_default_value;
 | 
						|
    std::vector<MXS_ENUM_VALUE>            m_enum_values;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamPath
 | 
						|
 */
 | 
						|
class ParamPath : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = std::string;
 | 
						|
 | 
						|
    enum Options
 | 
						|
    {
 | 
						|
        X = MXS_MODULE_OPT_PATH_X_OK,   // Execute permission required.
 | 
						|
        R = MXS_MODULE_OPT_PATH_R_OK,   // Read permission required.
 | 
						|
        W = MXS_MODULE_OPT_PATH_W_OK,   // Write permission required.
 | 
						|
        F = MXS_MODULE_OPT_PATH_F_OK,   // File existence required.
 | 
						|
        C = MXS_MODULE_OPT_PATH_CREAT   // Create path if does not exist.
 | 
						|
    };
 | 
						|
 | 
						|
    const uint32_t MASK = X | R | W | F | C;
 | 
						|
 | 
						|
 | 
						|
    ParamPath(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              uint32_t options)
 | 
						|
        : ParamPath(pSpecification, zName, zDescription, Param::MANDATORY, options, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamPath(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              uint32_t options,
 | 
						|
              value_type default_value)
 | 
						|
        : ParamPath(pSpecification, zName, zDescription, Param::OPTIONAL, options, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(const value_type& value) const;
 | 
						|
 | 
						|
    void populate(MXS_MODULE_PARAM& param) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamPath(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              Kind kind,
 | 
						|
              uint32_t options,
 | 
						|
              value_type default_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_PATH)
 | 
						|
        , m_options(options)
 | 
						|
        , m_default_value(default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    uint32_t   m_options;
 | 
						|
    value_type m_default_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamServer
 | 
						|
 */
 | 
						|
class ParamServer : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = SERVER*;
 | 
						|
 | 
						|
    ParamServer(Specification* pSpecification,
 | 
						|
                const char* zName,
 | 
						|
                const char* zDescription)
 | 
						|
        : Param(pSpecification, zName, zDescription, Param::MANDATORY, MXS_MODULE_PARAM_SERVER)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamSize
 | 
						|
 */
 | 
						|
class ParamSize : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = uint64_t;
 | 
						|
 | 
						|
    ParamSize(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription)
 | 
						|
        : ParamSize(pSpecification, zName, zDescription, Param::MANDATORY, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamSize(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              value_type default_value)
 | 
						|
        : ParamSize(pSpecification, zName, zDescription, Param::OPTIONAL, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamSize(Specification* pSpecification,
 | 
						|
              const char* zName,
 | 
						|
              const char* zDescription,
 | 
						|
              Kind kind,
 | 
						|
              value_type default_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_SIZE)
 | 
						|
        , m_default_value(default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    value_type m_default_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamString
 | 
						|
 */
 | 
						|
class ParamString : public Param
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = std::string;
 | 
						|
 | 
						|
    ParamString(Specification* pSpecification,
 | 
						|
                const char* zName,
 | 
						|
                const char* zDescription)
 | 
						|
        : ParamString(pSpecification, zName, zDescription, Param::MANDATORY, value_type())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ParamString(Specification* pSpecification,
 | 
						|
                const char* zName,
 | 
						|
                const char* zDescription,
 | 
						|
                value_type default_value)
 | 
						|
        : ParamString(pSpecification, zName, zDescription, Param::OPTIONAL, default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    std::string type() const override;
 | 
						|
 | 
						|
    std::string default_to_string() const override;
 | 
						|
 | 
						|
    bool validate(const std::string& value_as_string, std::string* pMessage) const override;
 | 
						|
 | 
						|
    bool set(Type& value, const std::string& value_as_string) const override;
 | 
						|
 | 
						|
    bool from_string(const std::string& value, value_type* pValue,
 | 
						|
                     std::string* pMessage = nullptr) const;
 | 
						|
    std::string to_string(value_type value) const;
 | 
						|
 | 
						|
private:
 | 
						|
    ParamString(Specification* pSpecification,
 | 
						|
                const char* zName,
 | 
						|
                const char* zDescription,
 | 
						|
                Kind kind,
 | 
						|
                value_type default_value)
 | 
						|
        : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_STRING)
 | 
						|
        , m_default_value(default_value)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    value_type m_default_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ParamBitMask
 | 
						|
 */
 | 
						|
using ParamBitMask = ParamCount;
 | 
						|
 | 
						|
/**
 | 
						|
 * An instance of the class Configuration specifies the configuration of a particular
 | 
						|
 * instance of a module.
 | 
						|
 *
 | 
						|
 * Walks hand in hand with Specification.
 | 
						|
 */
 | 
						|
class Configuration
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ValuesByName = std::map<std::string, Type*>;
 | 
						|
    using const_iterator = ValuesByName::const_iterator;
 | 
						|
    using value_type = ValuesByName::value_type;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor
 | 
						|
     *
 | 
						|
     * @param name            The object (i.e. section name) of this configuration.
 | 
						|
     * @param pSpecification  The specification this instance is a configuration of.
 | 
						|
     */
 | 
						|
    Configuration(const std::string& name, const Specification* pSpecification);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The The object (i.e. section name) of this configuration.
 | 
						|
     */
 | 
						|
    const std::string& name() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The specification of this configuration.
 | 
						|
     */
 | 
						|
    const Specification& specification() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param name  The name of the parameter to look up.
 | 
						|
     *
 | 
						|
     * @return The corresponding @c Value or NULL if @c name is unknown.
 | 
						|
     */
 | 
						|
    Type*       find_value(const std::string& name);
 | 
						|
    const Type* find_value(const std::string& name) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Persist the configuration to a stream.
 | 
						|
     *
 | 
						|
     * @param out  The stream to persist to.
 | 
						|
     */
 | 
						|
    std::ostream& persist(std::ostream& out) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Called when configuration has initially been configured, to allow a
 | 
						|
     * Configuration to check any interdependencies between values or to calculate
 | 
						|
     * derived ones.
 | 
						|
     *
 | 
						|
     * @param params  The parameters the configuration was configured with.
 | 
						|
     *
 | 
						|
     * @return True, if everything is ok.
 | 
						|
     *
 | 
						|
     * @note The default implementation returns true.
 | 
						|
     */
 | 
						|
    virtual bool post_configure(const MXS_CONFIG_PARAMETER& params);
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return The number of values in the configuration.
 | 
						|
     */
 | 
						|
    size_t size() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Const iterator to first parameter.
 | 
						|
     */
 | 
						|
    const_iterator cbegin() const
 | 
						|
    {
 | 
						|
        return m_values.cbegin();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Const iterator to one past last parameter.
 | 
						|
     */
 | 
						|
    const_iterator cend() const
 | 
						|
    {
 | 
						|
        return m_values.cend();
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    friend Type;
 | 
						|
 | 
						|
    void insert(Type* pValue);
 | 
						|
    void remove(Type* pValue, const std::string& name);
 | 
						|
 | 
						|
private:
 | 
						|
    std::string          m_name;
 | 
						|
    const Specification& m_specification;
 | 
						|
    ValuesByName         m_values;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Base-class of all configuration value types.
 | 
						|
 *
 | 
						|
 * In the description of this class, "value" should be read as
 | 
						|
 * "an instance of this type".
 | 
						|
 */
 | 
						|
class Type
 | 
						|
{
 | 
						|
public:
 | 
						|
    Type(const Type& rhs) = delete;
 | 
						|
    Type& operator=(const Type&) = delete;
 | 
						|
 | 
						|
    ~Type();
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get parameter describing this value.
 | 
						|
     *
 | 
						|
     * @return Param of the value.
 | 
						|
     */
 | 
						|
    const Param& parameter() const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Persist this value to a stream. It will be written as
 | 
						|
     *
 | 
						|
     *    name=value
 | 
						|
     *
 | 
						|
     * where @c value will be formatted in the correct way.
 | 
						|
     *
 | 
						|
     * @param out  The stream to write to.
 | 
						|
     *
 | 
						|
     * @return @c out.
 | 
						|
     */
 | 
						|
    std::ostream& persist(std::ostream& out) const;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Convert this value into its string representation.
 | 
						|
     *
 | 
						|
     * @return The value as it should appear in a configuration file.
 | 
						|
     */
 | 
						|
    virtual std::string to_string() const = 0;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set value.
 | 
						|
     *
 | 
						|
     * @param value_as_string  The new value expressed as a string.
 | 
						|
     *
 | 
						|
     * @return True, if the value could be set, false otherwise.
 | 
						|
     */
 | 
						|
    bool set(const std::string& value_as_string);
 | 
						|
 | 
						|
protected:
 | 
						|
    Type(Configuration* pConfiguration, const Param* pParam);
 | 
						|
 | 
						|
private:
 | 
						|
    Configuration&    m_configuration;
 | 
						|
    const Param&      m_param;
 | 
						|
    const std::string m_name;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * A concrete Value. Instantiated with a derived class and the
 | 
						|
 * corresponding param type.
 | 
						|
 */
 | 
						|
template<class This, class ParamType>
 | 
						|
class ConcreteType : public Type
 | 
						|
{
 | 
						|
public:
 | 
						|
    using value_type = typename ParamType::value_type;
 | 
						|
 | 
						|
    ConcreteType(const ConcreteType&) = delete;
 | 
						|
 | 
						|
    ConcreteType(Configuration* pConfiguration, const ParamType* pParam)
 | 
						|
        : Type(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    This& operator=(const value_type& value)
 | 
						|
    {
 | 
						|
        m_value = value;
 | 
						|
        return static_cast<This&>(*this);
 | 
						|
    }
 | 
						|
 | 
						|
    This& operator=(const ConcreteType<This, ParamType>& rhs)
 | 
						|
    {
 | 
						|
        // Only the value is copied, the parameter and the configuration
 | 
						|
        // remains the same.
 | 
						|
        m_value = rhs.m_value;
 | 
						|
        return static_cast<This&>(*this);
 | 
						|
    }
 | 
						|
 | 
						|
    value_type get() const
 | 
						|
    {
 | 
						|
        return m_value;
 | 
						|
    }
 | 
						|
 | 
						|
    void set(const value_type& value)
 | 
						|
    {
 | 
						|
        m_value = value;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string to_string() const override
 | 
						|
    {
 | 
						|
        return static_cast<const ParamType&>(parameter()).to_string(m_value);
 | 
						|
    }
 | 
						|
 | 
						|
protected:
 | 
						|
    value_type m_value;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Comparison operators:
 | 
						|
 *
 | 
						|
 *   ConcreteType  <-> ConcreteType
 | 
						|
 */
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator==(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() == rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator!=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() != rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                      const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() < rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                      const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() > rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return (lhs.get() < rhs.get()) || (lhs == rhs);
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return (lhs.get() > rhs.get()) || (lhs == rhs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Comparison operators:
 | 
						|
 *
 | 
						|
 *   ConcreteType  <-> ParamType::value_type
 | 
						|
 */
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator==(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() == rhs;
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator!=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() != rhs;
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                      const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() < rhs;
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                      const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return lhs.get() > rhs;
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return (lhs.get() < rhs) || (lhs.get() == rhs);
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>=(const ConcreteType<This, ParamType>& lhs,
 | 
						|
                       const typename ParamType::value_type& rhs)
 | 
						|
{
 | 
						|
    return (lhs.get() > rhs) || (lhs.get() == rhs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Comparison operators:
 | 
						|
 *
 | 
						|
 *   ParamType::value_type <-> ConcreteType
 | 
						|
 */
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator==(const typename ParamType::value_type& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs == rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator!=(const typename ParamType::value_type& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs != rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<(const typename ParamType::value_type& lhs,
 | 
						|
                      const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs < rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>(const typename ParamType::value_type& lhs,
 | 
						|
                      const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return lhs > rhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator<=(const typename ParamType::value_type& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return (lhs < rhs.get()) || (lhs == rhs.get());
 | 
						|
}
 | 
						|
 | 
						|
template<class This, class ParamType>
 | 
						|
inline bool operator>=(const typename ParamType::value_type& lhs,
 | 
						|
                       const ConcreteType<This, ParamType>& rhs)
 | 
						|
{
 | 
						|
    return (lhs > rhs.get()) || (lhs == rhs.get());
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class Number : public ConcreteType<Number, ParamNumber>
 | 
						|
{
 | 
						|
protected:
 | 
						|
    using ConcreteType<Number, ParamNumber>::operator =;
 | 
						|
 | 
						|
    Number(Configuration* pConfiguration, const ParamNumber* pParam)
 | 
						|
        : ConcreteType(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Count
 | 
						|
 */
 | 
						|
class Count : public Number
 | 
						|
{
 | 
						|
public:
 | 
						|
    using Number::operator =;
 | 
						|
 | 
						|
    Count(Configuration* pConfiguration, const ParamCount* pParam)
 | 
						|
        : Number(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Integer
 | 
						|
 */
 | 
						|
class Integer : public Number
 | 
						|
{
 | 
						|
public:
 | 
						|
    using Number::operator =;
 | 
						|
 | 
						|
    Integer(Configuration* pConfiguration, const ParamInteger* pParam)
 | 
						|
        : Number(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * BitMask
 | 
						|
 */
 | 
						|
class BitMask : public Count
 | 
						|
{
 | 
						|
public:
 | 
						|
    using Count::operator =;
 | 
						|
 | 
						|
    BitMask(Configuration* pConfiguration, const ParamCount* pParam)
 | 
						|
        : Count(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    bool is_set(value_type bit) const
 | 
						|
    {
 | 
						|
        return (m_value & bit) == bit;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Bool
 | 
						|
 */
 | 
						|
class Bool : public ConcreteType<Bool, ParamBool>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Bool, ParamBool>::operator =;
 | 
						|
 | 
						|
    Bool(Configuration* pConfiguration, const ParamBool* pParam)
 | 
						|
        : ConcreteType<Bool, ParamBool>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    explicit operator bool() const
 | 
						|
    {
 | 
						|
        return m_value;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Duration
 | 
						|
 */
 | 
						|
template<class T>
 | 
						|
class Duration : public ConcreteType<Duration<T>, ParamDuration<T>>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Duration<T>, ParamDuration<T>>::operator =;
 | 
						|
 | 
						|
    Duration(Configuration* pConfiguration, const ParamDuration<T>* pParam)
 | 
						|
        : ConcreteType<Duration<T>, ParamDuration<T>>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    typename T::rep count() const
 | 
						|
    {
 | 
						|
        return ConcreteType<Duration<T>, ParamDuration<T>>::m_value.count();
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 *  template<class T>
 | 
						|
 *  inline bool operator < (const Duration<T>& lhs, const Duration<T>& rhs)
 | 
						|
 *  {
 | 
						|
 *   return lhs.get() < rhs.get();
 | 
						|
 *  }
 | 
						|
 *
 | 
						|
 *  template<class T>
 | 
						|
 *  inline bool operator > (const Duration<T>& lhs, const Duration<T>& rhs)
 | 
						|
 *  {
 | 
						|
 *   return lhs.get() > rhs.get();
 | 
						|
 *  }
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * Enum
 | 
						|
 */
 | 
						|
template<class T>
 | 
						|
class Enum : public ConcreteType<Enum<T>, ParamEnum<T>>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Enum<T>, ParamEnum<T>>::operator =;
 | 
						|
 | 
						|
    Enum(Configuration* pConfiguration, const ParamEnum<T>* pParam)
 | 
						|
        : ConcreteType<Enum<T>, ParamEnum<T>>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Path
 | 
						|
 */
 | 
						|
class Path : public ConcreteType<Path, ParamPath>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Path, ParamPath>::operator =;
 | 
						|
 | 
						|
    Path(Configuration* pConfiguration, const ParamPath* pParam)
 | 
						|
        : ConcreteType<Path, ParamPath>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    const char* c_str() const
 | 
						|
    {
 | 
						|
        return m_value.c_str();
 | 
						|
    }
 | 
						|
 | 
						|
    bool empty() const
 | 
						|
    {
 | 
						|
        return m_value.empty();
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Size
 | 
						|
 */
 | 
						|
class Size : public ConcreteType<Size, ParamSize>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Size, ParamSize>::operator =;
 | 
						|
 | 
						|
    Size(Configuration* pConfiguration, const ParamSize* pParam)
 | 
						|
        : ConcreteType(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
inline Size::value_type operator/(const Size& lhs, Size::value_type rhs)
 | 
						|
{
 | 
						|
    return lhs.get() / rhs;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Server
 | 
						|
 */
 | 
						|
class Server : public ConcreteType<Server, ParamServer>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<Server, ParamServer>::operator =;
 | 
						|
 | 
						|
    Server(Configuration* pConfiguration, const ParamServer* pParam)
 | 
						|
        : ConcreteType<Server, ParamServer>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * String
 | 
						|
 */
 | 
						|
class String : public ConcreteType<String, ParamString>
 | 
						|
{
 | 
						|
public:
 | 
						|
    using ConcreteType<String, ParamString>::operator =;
 | 
						|
 | 
						|
    String(Configuration* pConfiguration, const ParamString* pParam)
 | 
						|
        : ConcreteType<String, ParamString>(pConfiguration, pParam)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    const char* c_str() const
 | 
						|
    {
 | 
						|
        return m_value.c_str();
 | 
						|
    }
 | 
						|
 | 
						|
    bool empty() const
 | 
						|
    {
 | 
						|
        return m_value.empty();
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * IMPLEMENTATION DETAILS
 | 
						|
 */
 | 
						|
struct DurationSuffix
 | 
						|
{
 | 
						|
    static const char* of(const std::chrono::seconds&)
 | 
						|
    {
 | 
						|
        return "s";
 | 
						|
    }
 | 
						|
 | 
						|
    static const char* of(const std::chrono::milliseconds&)
 | 
						|
    {
 | 
						|
        return "ms";
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamDuration<T>::type() const
 | 
						|
{
 | 
						|
    return "duration";
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamDuration<T>::default_to_string() const
 | 
						|
{
 | 
						|
    return to_string(m_default_value);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamDuration<T>::validate(const std::string& value_as_string, std::string* pMessage) const
 | 
						|
{
 | 
						|
    value_type value;
 | 
						|
    return from_string(value_as_string, &value, pMessage);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamDuration<T>::set(Type& value, const std::string& value_as_string) const
 | 
						|
{
 | 
						|
    mxb_assert(&value.parameter() == this);
 | 
						|
 | 
						|
    Duration<T>& duration_value = static_cast<Duration<T>&>(value);
 | 
						|
 | 
						|
    value_type x;
 | 
						|
    bool valid = from_string(value_as_string, &x);
 | 
						|
 | 
						|
    if (valid)
 | 
						|
    {
 | 
						|
        duration_value.set(x);
 | 
						|
    }
 | 
						|
 | 
						|
    return valid;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamDuration<T>::from_string(const std::string& value_as_string,
 | 
						|
                                   value_type* pValue,
 | 
						|
                                   std::string* pMessage) const
 | 
						|
{
 | 
						|
    mxs::config::DurationUnit unit;
 | 
						|
 | 
						|
    std::chrono::milliseconds duration;
 | 
						|
    bool valid = get_suffixed_duration(value_as_string.c_str(), m_interpretation, &duration, &unit);
 | 
						|
 | 
						|
    if (valid)
 | 
						|
    {
 | 
						|
        if (unit == mxs::config::DURATION_IN_DEFAULT)
 | 
						|
        {
 | 
						|
            if (pMessage)
 | 
						|
            {
 | 
						|
                *pMessage = "Specifying durations without a suffix denoting the unit has been deprecated: ";
 | 
						|
                *pMessage += value_as_string;
 | 
						|
                *pMessage += ". Use the suffixes 'h' (hour), 'm' (minute) 's' (second) or ";
 | 
						|
                *pMessage += "'ms' (milliseconds).";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        *pValue = std::chrono::duration_cast<value_type>(duration);
 | 
						|
    }
 | 
						|
    else if (pMessage)
 | 
						|
    {
 | 
						|
        *pMessage = "Invalid duration: ";
 | 
						|
        *pMessage += value_as_string;
 | 
						|
    }
 | 
						|
 | 
						|
    return valid;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamDuration<T>::to_string(const value_type& value) const
 | 
						|
{
 | 
						|
    std::stringstream ss;
 | 
						|
    ss << value.count() << DurationSuffix::of(value);
 | 
						|
    return ss.str();
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
ParamEnum<T>::ParamEnum(Specification* pSpecification,
 | 
						|
                        const char* zName,
 | 
						|
                        const char* zDescription,
 | 
						|
                        Kind kind,
 | 
						|
                        const std::vector<std::pair<T, const char*>>& enumeration,
 | 
						|
                        value_type default_value)
 | 
						|
    : Param(pSpecification, zName, zDescription, kind, MXS_MODULE_PARAM_ENUM)
 | 
						|
    , m_enumeration(enumeration)
 | 
						|
    , m_default_value(default_value)
 | 
						|
{
 | 
						|
    m_enum_values.reserve(m_enumeration.size() + 1);
 | 
						|
 | 
						|
    for (const auto& entry : enumeration)
 | 
						|
    {
 | 
						|
        MXS_ENUM_VALUE x {};
 | 
						|
        x.name = entry.second;
 | 
						|
        x.enum_value = entry.first;
 | 
						|
 | 
						|
        m_enum_values.emplace_back(x);
 | 
						|
    }
 | 
						|
 | 
						|
    MXS_ENUM_VALUE end {NULL};
 | 
						|
    m_enum_values.emplace_back(end);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamEnum<T>::type() const
 | 
						|
{
 | 
						|
    std::string s("enumeration:[");
 | 
						|
 | 
						|
    bool first = true;
 | 
						|
    for (const auto& p : m_enumeration)
 | 
						|
    {
 | 
						|
        if (first)
 | 
						|
        {
 | 
						|
            first = false;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            s += ", ";
 | 
						|
        }
 | 
						|
 | 
						|
        s += p.second;
 | 
						|
    }
 | 
						|
 | 
						|
    s += "]";
 | 
						|
 | 
						|
    return s;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamEnum<T>::default_to_string() const
 | 
						|
{
 | 
						|
    return to_string(m_default_value);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamEnum<T>::validate(const std::string& value_as_string, std::string* pMessage) const
 | 
						|
{
 | 
						|
    value_type value;
 | 
						|
    return from_string(value_as_string, &value, pMessage);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamEnum<T>::set(Type& value, const std::string& value_as_string) const
 | 
						|
{
 | 
						|
    mxb_assert(&value.parameter() == this);
 | 
						|
 | 
						|
    Enum<T>& enum_value = static_cast<Enum<T>&>(value);
 | 
						|
 | 
						|
    value_type x;
 | 
						|
    bool valid = from_string(value_as_string, &x);
 | 
						|
 | 
						|
    if (valid)
 | 
						|
    {
 | 
						|
        enum_value.set(x);
 | 
						|
    }
 | 
						|
 | 
						|
    return valid;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool ParamEnum<T>::from_string(const std::string& value_as_string,
 | 
						|
                               value_type* pValue,
 | 
						|
                               std::string* pMessage) const
 | 
						|
{
 | 
						|
    auto it = std::find_if(m_enumeration.begin(), m_enumeration.end(),
 | 
						|
                           [value_as_string](const std::pair<T, const char*>& elem) {
 | 
						|
                               return value_as_string == elem.second;
 | 
						|
                           });
 | 
						|
 | 
						|
    if (it != m_enumeration.end())
 | 
						|
    {
 | 
						|
        *pValue = it->first;
 | 
						|
    }
 | 
						|
    else if (pMessage)
 | 
						|
    {
 | 
						|
        std::string s;
 | 
						|
        for (size_t i = 0; i < m_enumeration.size(); ++i)
 | 
						|
        {
 | 
						|
            s += "'";
 | 
						|
            s += m_enumeration[i].second;
 | 
						|
            s += "'";
 | 
						|
 | 
						|
            if (i == m_enumeration.size() - 2)
 | 
						|
            {
 | 
						|
                s += " and ";
 | 
						|
            }
 | 
						|
            else if (i != m_enumeration.size() - 1)
 | 
						|
            {
 | 
						|
                s += ", ";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        *pMessage = "Invalid enumeration value: ";
 | 
						|
        *pMessage += value_as_string;
 | 
						|
        *pMessage += ", valid values are: ";
 | 
						|
        *pMessage += s;
 | 
						|
        *pMessage += ".";
 | 
						|
    }
 | 
						|
 | 
						|
    return it != m_enumeration.end();
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
std::string ParamEnum<T>::to_string(value_type value) const
 | 
						|
{
 | 
						|
    auto it = std::find_if(m_enumeration.begin(), m_enumeration.end(),
 | 
						|
                           [value](const std::pair<T, const char*>& entry) {
 | 
						|
                               return entry.first == value;
 | 
						|
                           });
 | 
						|
 | 
						|
    return it != m_enumeration.end() ? it->second : "unknown";
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
void ParamEnum<T>::populate(MXS_MODULE_PARAM& param) const
 | 
						|
{
 | 
						|
    Param::populate(param);
 | 
						|
 | 
						|
    param.accepted_values = &m_enum_values[0];
 | 
						|
}
 | 
						|
}
 |