From 8a250a8b13d64adc6adb7d160e4d30d67acdb162 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Mon, 29 Apr 2019 10:00:44 +0300 Subject: [PATCH] MXS-2329 Make duration misuse harder Now the desired type must be specified when getting a duration. The type also dictates how durations without suffixes should be interpreted. That removes the need for remembering that to convert a returned millisecond duration to a second duration. --- include/maxscale/config.hh | 38 ++++++++++++++++++- server/core/config.cc | 5 ++- server/modules/filter/ccrfilter/ccrfilter.cc | 4 +- .../filter/throttlefilter/throttlefilter.cc | 6 +-- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/include/maxscale/config.hh b/include/maxscale/config.hh index 4f5b7e06b..1c78ad206 100644 --- a/include/maxscale/config.hh +++ b/include/maxscale/config.hh @@ -339,8 +339,26 @@ public: * * @return Duration in milliseconds; 0 if the parameter is not found. */ - std::chrono::milliseconds get_duration(const std::string& key, - mxs::config::DurationInterpretation interpretation) const; + std::chrono::milliseconds get_duration_in_ms(const std::string& key, + mxs::config::DurationInterpretation interpretation) const; + + /** + * @brief Get a duration in a specific unit. + * + * @param key Parameter name + * + * @return The duration in the desired unit. + * + * @note The type the function is specialized with dictates how values without a + * suffix should be interpreted; if @c std::chrono::seconds, they will be + * interpreted as seconds, if @c std::chrono::milliseconds, they will be + * interpreted as milliseconds. + * + * @note There is no default implementation, but only specializations for + * @c std::chrono::seconds and @c std::chrono::milliseconds. + */ + template + T get_duration(const std::string& key) const = delete; /** * @brief Get a service value @@ -441,6 +459,22 @@ private: ContainerType m_contents; }; +template<> +inline std::chrono::milliseconds +MXS_CONFIG_PARAMETER::get_duration(const std::string& key) const +{ + return get_duration_in_ms(key, mxs::config::INTERPRET_AS_MILLISECONDS); +} + +template<> +inline std::chrono::seconds +MXS_CONFIG_PARAMETER::get_duration(const std::string& key) const +{ + std::chrono::milliseconds ms = get_duration_in_ms(key, mxs::config::INTERPRET_AS_SECONDS); + return std::chrono::duration_cast(ms); +} + + /** * The config context structure, used to build the configuration * data during the parse process diff --git a/server/core/config.cc b/server/core/config.cc index 329dda1b9..ea9b3d24a 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -1947,8 +1947,9 @@ uint64_t MXS_CONFIG_PARAMETER::get_size(const std::string& key) const return intval; } -std::chrono::milliseconds MXS_CONFIG_PARAMETER::get_duration(const std::string& key, - mxs::config::DurationInterpretation interpretation) +std::chrono::milliseconds +MXS_CONFIG_PARAMETER::get_duration_in_ms(const std::string& key, + mxs::config::DurationInterpretation interpretation) const { string value = get_string(key); diff --git a/server/modules/filter/ccrfilter/ccrfilter.cc b/server/modules/filter/ccrfilter/ccrfilter.cc index 27017f765..c6af4eb82 100644 --- a/server/modules/filter/ccrfilter/ccrfilter.cc +++ b/server/modules/filter/ccrfilter/ccrfilter.cc @@ -90,9 +90,7 @@ public: if (new_instance) { new_instance->m_count = params->get_integer("count"); - new_instance->m_time = params->get_duration("time", mxs::config::INTERPRET_AS_SECONDS).count(); - // The window is in seconds. - new_instance->m_time = std::lround(new_instance->m_time / 1000.0); + new_instance->m_time = params->get_duration("time").count(); new_instance->m_match = params->get_string(PARAM_MATCH); new_instance->m_nomatch = params->get_string(PARAM_IGNORE); diff --git a/server/modules/filter/throttlefilter/throttlefilter.cc b/server/modules/filter/throttlefilter/throttlefilter.cc index 05059a4c2..546b45fd1 100644 --- a/server/modules/filter/throttlefilter/throttlefilter.cc +++ b/server/modules/filter/throttlefilter/throttlefilter.cc @@ -65,11 +65,11 @@ ThrottleFilter* ThrottleFilter::create(const char* zName, MXS_CONFIG_PARAMETER* { int max_qps = pParams->get_integer(MAX_QPS_CFG); int sample_msecs = - pParams->get_duration(SAMPLING_DURATION_CFG, mxs::config::INTERPRET_AS_MILLISECONDS).count(); + pParams->get_duration(SAMPLING_DURATION_CFG).count(); int throttle_msecs = - pParams->get_duration(THROTTLE_DURATION_CFG, mxs::config::INTERPRET_AS_MILLISECONDS).count(); + pParams->get_duration(THROTTLE_DURATION_CFG).count(); int cont_msecs = - pParams->get_duration(CONTINUOUS_DURATION_CFG, mxs::config::INTERPRET_AS_MILLISECONDS).count(); + pParams->get_duration(CONTINUOUS_DURATION_CFG).count(); bool config_ok = true; if (max_qps < 2)