MXS-2304 Clean up configuration serialization
The parameters are now written in the order they appear in the module parameter definitions. Also enabled a previously disabled part in server unit test.
This commit is contained in:
		| @ -4869,24 +4869,28 @@ bool config_parse_disk_space_threshold(SERVER::DiskSpaceLimits* pDisk_space_thre | |||||||
|     return success; |     return success; | ||||||
| } | } | ||||||
|  |  | ||||||
| void dump_param_list(int file, | std::string generate_config_string(const std::string& instance_name, const MXS_CONFIG_PARAMETER& parameters, | ||||||
|                      const MXS_CONFIG_PARAMETER* list, |                                    const MXS_MODULE_PARAM* common_param_defs, | ||||||
|                      const std::unordered_set<std::string>& ignored, |                                    const MXS_MODULE_PARAM* module_param_defs) | ||||||
|                      const MXS_MODULE_PARAM* common_params, |  | ||||||
|                      const MXS_MODULE_PARAM* module_params) |  | ||||||
| { | { | ||||||
|     for (const auto& p : *list) |     string output = "[" + instance_name + "]\n";; | ||||||
|  |     // Common params and module params are null-terminated arrays. Loop over both and print parameter | ||||||
|  |     // names and values. | ||||||
|  |     for (auto param_set : {common_param_defs, module_param_defs}) | ||||||
|     { |     { | ||||||
|         const string& name = p.first; |         for (int i = 0; param_set[i].name; i++) | ||||||
|         const string& value = p.second; |  | ||||||
|         if (ignored.count(name) == 0 && !value.empty()) |  | ||||||
|         { |         { | ||||||
|             if (dprintf(file, "%s=%s\n", name.c_str(), value.c_str()) == -1) |             auto param_info = param_set + i; | ||||||
|  |             string param_name = param_info->name; | ||||||
|  |             if (parameters.contains(param_name)) | ||||||
|             { |             { | ||||||
|                 MXS_ERROR("Failed to serialize service value: %d, %s", errno, mxs_strerror(errno)); |                 // Parameter value in the container can be an empty string and still be printed. | ||||||
|  |                 string param_value = parameters.get_string(param_name); | ||||||
|  |                 output += param_name + "=" + param_value + "\n"; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     return output; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -514,18 +514,17 @@ static bool create_filter_config(const SFilterDef& filter, const char* filename) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     Guard guard(filter->lock); |     Guard guard(filter->lock); | ||||||
|  |  | ||||||
|     dprintf(file, "[%s]\n", filter->name.c_str()); |  | ||||||
|     dprintf(file, "%s=%s\n", CN_TYPE, CN_FILTER); |  | ||||||
|     dprintf(file, "%s=%s\n", CN_MODULE, filter->module.c_str()); |  | ||||||
|  |  | ||||||
|     const MXS_MODULE* mod = get_module(filter->module.c_str(), NULL); |     const MXS_MODULE* mod = get_module(filter->module.c_str(), NULL); | ||||||
|     mxb_assert(mod); |     mxb_assert(mod); | ||||||
|  |  | ||||||
|     MXS_MODULE_PARAM no_common_params = {}; |     string config_str = generate_config_string(filter->name, *filter->parameters, | ||||||
|     dump_param_list(file, filter->parameters, {CN_TYPE, CN_MODULE}, &no_common_params, mod->parameters); |                                                config_filter_params, mod->parameters); | ||||||
|  |     if (dprintf(file, "%s", config_str.c_str()) == -1) | ||||||
|  |     { | ||||||
|  |         MXS_ERROR("Could not write serialized configuration to file '%s': %d, %s", | ||||||
|  |                   filename, errno, mxs_strerror(errno)); | ||||||
|  |     } | ||||||
|     close(file); |     close(file); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -233,12 +233,19 @@ bool get_suffixed_duration(const char* zValue, | |||||||
|                            std::chrono::milliseconds* pDuration, |                            std::chrono::milliseconds* pDuration, | ||||||
|                            mxs::config::DurationUnit* pUnit = nullptr); |                            mxs::config::DurationUnit* pUnit = nullptr); | ||||||
|  |  | ||||||
| // Dump a parameter list into a file as `key=value` pairs | /** | ||||||
| void dump_param_list(int file, |  * Generate configuration file contents out of module configuration parameters. Only parameters defined | ||||||
|                      const MXS_CONFIG_PARAMETER* list, |  * in the parameter definition arrays are printed. Printing is in the order the parameters are given in | ||||||
|                      const std::unordered_set<std::string>& ignored, |  * the definitions. | ||||||
|                      const MXS_MODULE_PARAM* common_params, |  * | ||||||
|                      const MXS_MODULE_PARAM* module_params); |  * @param instance_name The module instance name | ||||||
|  |  * @param parameters Configuration parameter values | ||||||
|  |  * @param common_param_defs Common module parameter definitions. These are printed first. | ||||||
|  |  * @param module_param_defs Module-specific parameter definitions. | ||||||
|  |  */ | ||||||
|  | std::string generate_config_string(const std::string& instance_name, const MXS_CONFIG_PARAMETER& parameters, | ||||||
|  |                                    const MXS_MODULE_PARAM* common_param_defs, | ||||||
|  |                                    const MXS_MODULE_PARAM* module_param_defs); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Check whether a parameter can be modified at runtime |  * Check whether a parameter can be modified at runtime | ||||||
|  | |||||||
| @ -1325,7 +1325,6 @@ Monitor* monitor_server_in_use(const SERVER* server) | |||||||
| static bool create_monitor_config(const Monitor* monitor, const char* filename) | static bool create_monitor_config(const Monitor* monitor, const char* filename) | ||||||
| { | { | ||||||
|     int file = open(filename, O_EXCL | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |     int file = open(filename, O_EXCL | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||||||
|  |  | ||||||
|     if (file == -1) |     if (file == -1) | ||||||
|     { |     { | ||||||
|         MXS_ERROR("Failed to open file '%s' when serializing monitor '%s': %d, %s", |         MXS_ERROR("Failed to open file '%s' when serializing monitor '%s': %d, %s", | ||||||
| @ -1338,31 +1337,18 @@ static bool create_monitor_config(const Monitor* monitor, const char* filename) | |||||||
|  |  | ||||||
|     { |     { | ||||||
|         Guard guard(monitor->m_lock); |         Guard guard(monitor->m_lock); | ||||||
|         dprintf(file, "[%s]\n", monitor->m_name); |  | ||||||
|         dprintf(file, "%s=monitor\n", CN_TYPE); |  | ||||||
|  |  | ||||||
|         if (!monitor->m_servers.empty()) |  | ||||||
|         { |  | ||||||
|             dprintf(file, "%s=", CN_SERVERS); |  | ||||||
|             for (MXS_MONITORED_SERVER* db : monitor->m_servers) |  | ||||||
|             { |  | ||||||
|                 if (db != monitor->m_servers[0]) |  | ||||||
|                 { |  | ||||||
|                     dprintf(file, ","); |  | ||||||
|                 } |  | ||||||
|                 dprintf(file, "%s", db->server->name()); |  | ||||||
|             } |  | ||||||
|             dprintf(file, "\n"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const MXS_MODULE* mod = get_module(monitor->m_module.c_str(), NULL); |         const MXS_MODULE* mod = get_module(monitor->m_module.c_str(), NULL); | ||||||
|         mxb_assert(mod); |         mxb_assert(mod); | ||||||
|  |  | ||||||
|         dump_param_list(file, |         string config = generate_config_string(monitor->m_name, monitor->parameters, | ||||||
|                         &monitor->parameters, |                                                config_monitor_params, mod->parameters); | ||||||
|                         {CN_TYPE, CN_SERVERS}, |  | ||||||
|                         config_monitor_params, |         if (dprintf(file, "%s", config.c_str()) == -1) | ||||||
|                         mod->parameters); |         { | ||||||
|  |             MXS_ERROR("Could not write serialized configuration to file '%s': %d, %s", | ||||||
|  |                       filename, errno, mxs_strerror(errno)); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     close(file); |     close(file); | ||||||
|  | |||||||
| @ -880,22 +880,23 @@ bool Server::create_server_config(const Server* server, const char* filename) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO: Check for return values on all of the dprintf calls |     // TODO: Check for return values on all of the dprintf calls | ||||||
|     dprintf(file, "[%s]\n", server->name()); |  | ||||||
|     dprintf(file, "%s=server\n", CN_TYPE); |  | ||||||
|  |  | ||||||
|     const MXS_MODULE* mod = get_module(server->m_settings.protocol.c_str(), MODULE_PROTOCOL); |     const MXS_MODULE* mod = get_module(server->m_settings.protocol.c_str(), MODULE_PROTOCOL); | ||||||
|     dump_param_list(file, |     string config = generate_config_string(server->name(), | ||||||
|                     ParamAdaptor(server->m_settings.all_parameters), |                                            *ParamAdaptor(server->m_settings.all_parameters), | ||||||
|                     {CN_TYPE}, |                                            config_server_params, | ||||||
|                     config_server_params, |                                            mod->parameters); | ||||||
|                     mod->parameters); |  | ||||||
|  |  | ||||||
|     // Print custom parameters |     // Print custom parameters | ||||||
|     for (const auto& elem : server->m_settings.custom_parameters) |     for (const auto& elem : server->m_settings.custom_parameters) | ||||||
|     { |     { | ||||||
|         dprintf(file, "%s=%s\n", elem.first.c_str(), elem.second.c_str()); |         config += elem.first + "=" + elem.second + "\n"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (dprintf(file, "%s", config.c_str()) == -1) | ||||||
|  |     { | ||||||
|  |         MXS_ERROR("Could not write serialized configuration to file '%s': %d, %s", | ||||||
|  |                   filename, errno, mxs_strerror(errno)); | ||||||
|  |     } | ||||||
|     close(file); |     close(file); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1417,12 +1417,23 @@ bool Service::dump_config(const char* filename) const | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     const MXS_MODULE* mod = get_module(router_name(), NULL); | ||||||
|  |     mxb_assert(mod); | ||||||
|  |  | ||||||
|  |     MXS_CONFIG_PARAMETER params_to_print = svc_config_param; | ||||||
|  |     // The next text-mode parameter may not be up-to-date, print them manually. TODO: Fix | ||||||
|  |     params_to_print.remove(CN_FILTERS); | ||||||
|  |     params_to_print.remove(CN_SERVERS); | ||||||
|  |  | ||||||
|  |     string config = generate_config_string(name(), params_to_print, config_service_params, mod->parameters); | ||||||
|  |     if (dprintf(file, "%s", config.c_str()) == -1) | ||||||
|  |     { | ||||||
|  |         MXS_ERROR("Could not write serialized configuration to file '%s': %d, %s", | ||||||
|  |                   filename, errno, mxs_strerror(errno)); | ||||||
|  |     } | ||||||
|     /** |     /** | ||||||
|      * TODO: Check for return values on all of the dprintf calls |      * TODO: Check for return values on all of the dprintf calls | ||||||
|      */ |      */ | ||||||
|     dprintf(file, "[%s]\n", name()); |  | ||||||
|     dprintf(file, "%s=service\n", CN_TYPE); |  | ||||||
|  |  | ||||||
|     if (!m_filters.empty()) |     if (!m_filters.empty()) | ||||||
|     { |     { | ||||||
|         dprintf(file, "%s=", CN_FILTERS); |         dprintf(file, "%s=", CN_FILTERS); | ||||||
| @ -1452,16 +1463,6 @@ bool Service::dump_config(const char* filename) const | |||||||
|         } |         } | ||||||
|         dprintf(file, "\n"); |         dprintf(file, "\n"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const MXS_MODULE* mod = get_module(router_name(), NULL); |  | ||||||
|     mxb_assert(mod); |  | ||||||
|  |  | ||||||
|     dump_param_list(file, |  | ||||||
|                     &svc_config_param, |  | ||||||
|                     {CN_TYPE, CN_FILTERS, CN_SERVERS}, |  | ||||||
|                     config_service_params, |  | ||||||
|                     mod->parameters); |  | ||||||
|  |  | ||||||
|     close(file); |     close(file); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
|  | |||||||
| @ -149,12 +149,9 @@ bool test_serialize() | |||||||
|     TEST(created->serialize(), "Failed to synchronize the copied server"); |     TEST(created->serialize(), "Failed to synchronize the copied server"); | ||||||
|  |  | ||||||
|     /** Check that they serialize to identical files */ |     /** Check that they serialize to identical files */ | ||||||
|     // TODO: Disabled for now. Enable once config parameters are kept in a well-defined order. |  | ||||||
|     /* |  | ||||||
|     char cmd[1024]; |     char cmd[1024]; | ||||||
|     sprintf(cmd, "diff ./%s ./%s", config_name, old_config_name); |     sprintf(cmd, "diff ./%s ./%s", config_name, old_config_name); | ||||||
|     TEST(system(cmd) == 0, "The files are not identical"); |     TEST(system(cmd) == 0, "The files are not identical"); | ||||||
|      */ |  | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Esa Korhonen
					Esa Korhonen