From 0c2bec9fbac53808c02746ff519a2b3f73512da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Aug 2018 23:27:35 +0300 Subject: [PATCH] MXS-1929: Add config dump helper functions The functions dump of parameters only if they differ from the defaults. The check for equality is rather coarse but it should work as long as all core objects use C++ types correctly e.g. integer are not used to store boolean values (I'm looking at you, enable_root and localhost_match_wildcard_host). The boolean type has a specialization to convert the value to the string format used for all defaults in the core. This also adds the missing return value checks to the dprintf calls and reports errors if any are encountered. --- server/core/config.cc | 28 ++++++++++++++++++ server/core/internal/config.hh | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/server/core/config.cc b/server/core/config.cc index 1723ab401..051740a1a 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -4666,4 +4666,32 @@ MXS_CONFIG_PARAMETER* ParamList::params() return m_ctx.parameters; } + +void dump_if_changed(const MXS_MODULE_PARAM* params, int file, + const std::string& key, const std::string& value) +{ + for (int i = 0; params[i].name; i++) + { + if (params[i].name == key) + { + /** + * This detects only exact matches, not ones that are logically equivalent + * but lexicographically different e.g. 1 and true. This might not + * be a bad thing: it'll distinct user defined values from defaults. + */ + + if (!params[i].default_value || value != params[i].default_value) + { + if (dprintf(file, "%s=%s\n", key.c_str(), value.c_str()) == -1) + { + MXS_ERROR("Failed to serialize service value: %d, %s", + errno, mxs_strerror(errno)); + } + } + + break; + } + } +} + } diff --git a/server/core/internal/config.hh b/server/core/internal/config.hh index 9a89bb185..d59961a00 100644 --- a/server/core/internal/config.hh +++ b/server/core/internal/config.hh @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -214,3 +216,55 @@ bool is_normal_server_parameter(const char *param); * `dest` are left in an undefined state */ bool get_suffixed_size(const char* value, uint64_t* dest); + +namespace maxscale +{ + +// Internal function +void dump_if_changed(const MXS_MODULE_PARAM* params, int file, + const std::string& key, const std::string& value); + + +/** + * Dump a parameter into a file descriptor + * + * The function detects only literal matches to the string format default values. + * If the string conversion results in an empty string, the value will not be + * dumped. This can only happen if an empty string is passed as the value. + * + * The function writes a single key-value pair into the file and terminates + * the line with a newline. This is intended to be used with configuration + * dumping code in the core. + * + * Note: Does not work with enum type parameters, they'll get converted into + * integers. Convert them to string format at the call site. + * + * @param params Module parameter to use + * @param file File descriptor where the line is written + * @param key Name of the parameter + * @param value The parameter value + */ +template +inline void dump_param(const MXS_MODULE_PARAM* params, int file, const std::string& key, const T value) +{ + std::stringstream ss; + ss << value; + auto strval = ss.str(); + + if (!strval.empty()) + { + // Don't dump empty values + dump_if_changed(params, file, key, strval); + } +} + +// Specialization required to dump booleans in the same format as they used in +// the defaults. This requires that all defaults use either "true" or "false" +// for the values. +template <> +inline void dump_param(const MXS_MODULE_PARAM* params, int file, const std::string& key, bool value) +{ + dump_if_changed(params, file, key, value ? "true" : "false"); +} + +}