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: 2024-11-16
 | |
|  *
 | |
|  * 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];
 | |
| }
 | |
| }
 | 
