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"); +} + +}