From 94e6ef17a2746fbac365934fc3e67593b221ad6e Mon Sep 17 00:00:00 2001 From: Kargatum Date: Sun, 12 Jul 2020 22:47:12 +0700 Subject: [PATCH] feat(Core/Config): rework configs load system (#2566) --- src/common/Configuration/Config.cpp | 187 +++++++++++++++++----- src/common/Configuration/Config.h | 31 ++-- src/server/authserver/Main.cpp | 15 +- src/server/game/World/World.cpp | 45 +----- src/server/game/World/World.h | 6 - src/server/scripts/Commands/cs_reload.cpp | 1 - src/server/worldserver/Main.cpp | 22 +-- src/server/worldserver/Master.cpp | 4 +- 8 files changed, 175 insertions(+), 136 deletions(-) diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 050a0e730..6da120137 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -7,6 +7,7 @@ #include "Config.h" #include "Errors.h" #include "Log.h" +#include "Util.h" ConfigMgr* ConfigMgr::instance() { @@ -15,37 +16,40 @@ ConfigMgr* ConfigMgr::instance() } // Defined here as it must not be exposed to end-users. -bool ConfigMgr::GetValueHelper(const char* name, ACE_TString &result) +bool ConfigMgr::GetValueHelper(const char* name, ACE_TString& result) { GuardType guard(_configLock); - if (_config.get() == 0) + if (!_config.get()) return false; ACE_TString section_name; ACE_Configuration_Section_Key section_key; - const ACE_Configuration_Section_Key &root_key = _config->root_section(); + const ACE_Configuration_Section_Key& root_key = _config->root_section(); int i = 0; - while (_config->enumerate_sections(root_key, i, section_name) == 0) + + while (!_config->enumerate_sections(root_key, i, section_name)) { _config->open_section(root_key, section_name.c_str(), 0, section_key); - if (_config->get_string_value(section_key, name, result) == 0) + + if (!_config->get_string_value(section_key, name, result)) return true; + ++i; } return false; } -bool ConfigMgr::LoadInitial(char const* file) +bool ConfigMgr::LoadInitial(std::string const& file) { - ASSERT(file); + ASSERT(file.c_str()); GuardType guard(_configLock); _config.reset(new ACE_Configuration_Heap()); - if (_config->open() == 0) + if (!_config->open()) if (LoadData(file)) return true; @@ -53,9 +57,9 @@ bool ConfigMgr::LoadInitial(char const* file) return false; } -bool ConfigMgr::LoadMore(char const* file) +bool ConfigMgr::LoadMore(std::string const& file) { - ASSERT(file); + ASSERT(file.c_str()); ASSERT(_config); GuardType guard(_configLock); @@ -65,84 +69,79 @@ bool ConfigMgr::LoadMore(char const* file) bool ConfigMgr::Reload() { - for(std::vector::iterator it = _confFiles.begin(); it != _confFiles.end(); ++it) { - if (it==_confFiles.begin()) { - if (!LoadInitial((*it).c_str())) - return false; - } else { - LoadMore((*it).c_str()); - } - } + if (!LoadAppConfigs()) + return false; + + LoadModulesConfigs(); return true; } -bool ConfigMgr::LoadData(char const* file) +bool ConfigMgr::LoadData(std::string const& file) { - if(std::find(_confFiles.begin(), _confFiles.end(), file) == _confFiles.end()) { - _confFiles.push_back(file); - } - ACE_Ini_ImpExp config_importer(*_config.get()); - if (config_importer.import_config(file) == 0) + if (!config_importer.import_config(file.c_str())) return true; return false; } -std::string ConfigMgr::GetStringDefault(const char* name, const std::string &def, bool logUnused /*= true*/) +std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def, bool logUnused /*= true*/) { ACE_TString val; - if (GetValueHelper(name, val)) + if (GetValueHelper(name.c_str(), val)) return val.c_str(); else { if (logUnused) - sLog->outError("-> Not found option '%s'. The default value is used (%s)", name, def.c_str()); + sLog->outError("-> Not found option '%s'. The default value is used (%s)", name.c_str(), def.c_str()); + return def; } } -bool ConfigMgr::GetBoolDefault(const char* name, bool def, bool logUnused /*= true*/) +bool ConfigMgr::GetBoolDefault(std::string const& name, bool def, bool logUnused /*= true*/) { ACE_TString val; - if (!GetValueHelper(name, val)) + if (!GetValueHelper(name.c_str(), val)) { if (logUnused) - def ? sLog->outError("-> Not found option '%s'. The default value is used (Yes)", name) : sLog->outError("-> Not found option '%s'. The default value is used (No)", name); + def ? sLog->outError("-> Not found option '%s'. The default value is used (Yes)", name.c_str()) : sLog->outError("-> Not found option '%s'. The default value is used (No)", name.c_str()); + return def; } - return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || - val == "1"); + return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || val == "1"); } -int ConfigMgr::GetIntDefault(const char* name, int def, bool logUnused /*= true*/) +int ConfigMgr::GetIntDefault(std::string const& name, int def, bool logUnused /*= true*/) { ACE_TString val; - if (GetValueHelper(name, val)) + if (GetValueHelper(name.c_str(), val)) return atoi(val.c_str()); else { if (logUnused) - sLog->outError("-> Not found option '%s'. The default value is used (%i)", name, def); + sLog->outError("-> Not found option '%s'. The default value is used (%i)", name.c_str(), def); + return def; } } -float ConfigMgr::GetFloatDefault(const char* name, float def, bool logUnused /*= true*/) +float ConfigMgr::GetFloatDefault(std::string const& name, float def, bool logUnused /*= true*/) { ACE_TString val; - if (GetValueHelper(name, val)) + if (GetValueHelper(name.c_str(), val)) return (float)atof(val.c_str()); else { if (logUnused) - sLog->outError("-> Not found option '%s'. The default value is used (%f)", name, def); + sLog->outError("-> Not found option '%s'. The default value is used (%f)", name.c_str(), def); + return def; } } @@ -152,22 +151,25 @@ std::list ConfigMgr::GetKeysByString(std::string const& name) GuardType guard(_configLock); std::list keys; - if (_config.get() == 0) + if (!_config.get()) return keys; ACE_TString section_name; ACE_Configuration_Section_Key section_key; - const ACE_Configuration_Section_Key &root_key = _config->root_section(); + const ACE_Configuration_Section_Key& root_key = _config->root_section(); int i = 0; - while (_config->enumerate_sections(root_key, i++, section_name) == 0) + + while (!_config->enumerate_sections(root_key, i++, section_name)) { _config->open_section(root_key, section_name.c_str(), 0, section_key); ACE_TString key_name; ACE_Configuration::VALUETYPE type; + int j = 0; - while (_config->enumerate_values(section_key, j++, key_name, type) == 0) + + while (!_config->enumerate_values(section_key, j++, key_name, type)) { std::string temp = key_name.c_str(); @@ -178,3 +180,104 @@ std::list ConfigMgr::GetKeysByString(std::string const& name) return keys; } + +void ConfigMgr::SetConfigList(std::string const& fileName, std::string const& modulesConfigList /*= ""*/) +{ + _initConfigFile = fileName; + + if (modulesConfigList.empty()) + return; + + // Clean config list before load + _modulesConfigFiles.clear(); + + Tokenizer configFileList(modulesConfigList, ','); + for (auto const& itr : configFileList) + _modulesConfigFiles.push_back(itr); +} + +bool ConfigMgr::LoadAppConfigs(std::string const& applicationName /*= "worldserver"*/) +{ + // #1 - Load init config file .conf.dist + if (!sConfigMgr->LoadInitial(_initConfigFile + ".dist")) + { + printf("Load config error. Invalid or missing dist configuration file: %s", std::string(_initConfigFile + ".dist").c_str()); + printf("Verify that the file exists and has \'[%s]' written in the top of the file!", applicationName.c_str()); + return false; + } + + // #2 - Load .conf file + if (!sConfigMgr->LoadMore(_initConfigFile)) + { + sLog->outString(""); + sLog->outString("Load config error. Invalid or missing configuration file: %s", _initConfigFile.c_str()); + sLog->outString("Verify that the file exists and has \'[%s]' written in the top of the file!", applicationName.c_str()); + return false; + } + + return true; +} + +bool ConfigMgr::LoadModulesConfigs() +{ + // If not modules config - load failed + if (_modulesConfigFiles.empty()) + return false; + + // Start loading module configs + std::unordered_map moduleConfigFiles; + + moduleConfigFiles.clear(); + + std::string configPath = _CONF_DIR; + + for (auto const& itr : _modulesConfigFiles) + { + bool IsExistDefaultConfig = true; + bool IsExistDistConfig = true; + + std::string moduleName = itr; + std::string configFile = std::string(itr) + std::string(".conf"); + std::string defaultConfig = configPath + "/" + configFile; + +#if AC_PLATFORM == AC_PLATFORM_WINDOWS + defaultConfig = configFile; +#endif + + std::string ConfigFileDist = defaultConfig + std::string(".dist"); + + // Load .conf.dist config + if (!sConfigMgr->LoadMore(ConfigFileDist.c_str())) + { + sLog->outError("> Invalid or missing dist configuration file: %s", ConfigFileDist.c_str()); + IsExistDistConfig = false; + } + + // Load .conf config + if (!sConfigMgr->LoadMore(defaultConfig.c_str())) + IsExistDefaultConfig = false; + + // #1 - Not exist .conf and exist .conf.dist + if (!IsExistDefaultConfig && IsExistDistConfig) + moduleConfigFiles.insert(std::make_pair(moduleName, ConfigFileDist)); + else if (!IsExistDefaultConfig && !IsExistDistConfig) // #2 - Not exist .conf and not exist .conf.dist + moduleConfigFiles.insert(std::make_pair(moduleName, "default hardcoded settings")); + else if (IsExistDefaultConfig && IsExistDistConfig) + moduleConfigFiles.insert(std::make_pair(moduleName, defaultConfig)); + } + + // If module configs not exist - no load + if (moduleConfigFiles.empty()) + return false; + + // Print modules configurations + sLog->outString(); + sLog->outString("Using configuration for modules:"); + + for (auto const& itr : moduleConfigFiles) + sLog->outString("> Module (%s) using (%s)", itr.first.c_str(), itr.second.c_str()); + + sLog->outString(); + + return true; +} diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 58678b131..70afc1772 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -21,11 +21,10 @@ class ConfigMgr friend class ConfigLoader; public: - static ConfigMgr* instance(); - + /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) - bool LoadInitial(char const* file); + bool LoadInitial(std::string const& file); /** * This method loads additional configuration files @@ -33,30 +32,36 @@ public: * * @return true if loading was successful */ - bool LoadMore(char const* file); + bool LoadMore(std::string const& file); bool Reload(); - std::string GetStringDefault(const char* name, const std::string& def, bool logUnused = true); - bool GetBoolDefault(const char* name, bool def, bool logUnused = true); - int GetIntDefault(const char* name, int def, bool logUnused = true); - float GetFloatDefault(const char* name, float def, bool logUnused = true); + bool LoadAppConfigs(std::string const& applicationName = "worldserver"); + bool LoadModulesConfigs(); + + std::string GetStringDefault(std::string const& name, const std::string& def, bool logUnused = true); + bool GetBoolDefault(std::string const& name, bool def, bool logUnused = true); + int GetIntDefault(std::string const& name, int def, bool logUnused = true); + float GetFloatDefault(std::string const& name, float def, bool logUnused = true); std::list GetKeysByString(std::string const& name); - bool isDryRun() { return this->dryRun; } - void setDryRun(bool mode) { this->dryRun = mode; } + bool isDryRun() { return dryRun; } + void setDryRun(bool mode) { dryRun = mode; } + + void SetConfigList(std::string const& fileName, std::string const& modulesConfigList = ""); private: bool dryRun = false; - bool GetValueHelper(const char* name, ACE_TString &result); - bool LoadData(char const* file); + bool GetValueHelper(const char* name, ACE_TString& result); + bool LoadData(std::string const& file); typedef ACE_Thread_Mutex LockType; typedef ACE_Guard GuardType; - std::vector _confFiles; + std::vector _modulesConfigFiles; + std::string _initConfigFile; Config _config; LockType _configLock; diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 1ea2bd287..b1692ab45 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -36,7 +36,7 @@ #endif #ifndef _ACORE_REALM_CONFIG -# define _ACORE_REALM_CONFIG "authserver.conf" +#define _ACORE_REALM_CONFIG "authserver.conf" #endif bool StartDB(); @@ -92,19 +92,10 @@ extern int main(int argc, char** argv) ++count; } - std::string cfg_def_file=_ACORE_REALM_CONFIG; - cfg_def_file += ".dist"; + sConfigMgr->SetConfigList(std::string(configFile)); - if (!sConfigMgr->LoadInitial(cfg_def_file.c_str())) { - printf("ERROR: Invalid or missing default configuration file : %s\n", cfg_def_file.c_str()); + if (!sConfigMgr->LoadAppConfigs("authserver")) return 1; - } - - if (!sConfigMgr->LoadMore(configFile)) - { - printf("WARNING: Invalid or missing configuration file : %s\n", configFile); - printf("Verify that the file exists and has \'[authserver]\' written in the top of the file!\n"); - } sLog->outString("%s (authserver)", GitRevision::GetFullVersion()); sLog->outString(" to stop.\n"); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index e8f4484ed..201a1cf75 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -124,8 +124,6 @@ World::World() m_CleaningFlags = 0; - m_configFileList = ""; - memset(rate_values, 0, sizeof(rate_values)); memset(m_int_configs, 0, sizeof(m_int_configs)); memset(m_bool_configs, 0, sizeof(m_bool_configs)); @@ -414,46 +412,6 @@ bool World::RemoveQueuedPlayer(WorldSession* sess) return found; } -void World::LoadModuleConfigSettings() -{ - Tokenizer configFileList(GetConfigFileList(), ','); - for (auto i = configFileList.begin(); i != configFileList.end(); i++) - { - std::string configFile = (*i) + std::string(".conf"); - - std::string conf_path = _CONF_DIR; - std::string cfg_file = conf_path + "/" + configFile; - -#if AC_PLATFORM == AC_PLATFORM_WINDOWS - cfg_file = configFile; -#endif - std::string cfg_def_file = cfg_file + ".dist"; - - // Load .conf.dist config - if (!sConfigMgr->LoadMore(cfg_def_file.c_str())) - { - sLog->outString(); - sLog->outError("Module config: Invalid or missing configuration (*.conf.dist) file : %s", cfg_def_file.c_str()); - sLog->outError("Module config: Verify that this file exists and has \'[worldserver]' written at the top of the file!"); - - // If .conf exists, it will load it so it will NOT use the default hardcoded settings - if (!sConfigMgr->LoadMore(cfg_file.c_str())) - { - sLog->outError("Module config: Using default hardcoded settings."); - } - sLog->outString(); - } - - // Load .conf config - if (!sConfigMgr->LoadMore(cfg_file.c_str())) - { - sLog->outString(); - sLog->outString("Module config: %s not found (or invalid), using default settings from %s", cfg_file.c_str(), cfg_def_file.c_str()); - sLog->outString(); - } - } -} - /// Initialize config values void World::LoadConfigSettings(bool reload) { @@ -466,8 +424,6 @@ void World::LoadConfigSettings(bool reload) } } - LoadModuleConfigSettings(); - #ifdef ELUNA ///- Initialize Lua Engine if (!reload) @@ -487,6 +443,7 @@ void World::LoadConfigSettings(bool reload) ///- Read the player limit and the Message of the day from the config file if (!reload) SetPlayerAmountLimit(sConfigMgr->GetIntDefault("PlayerLimit", 100)); + Motd::SetMotd(sConfigMgr->GetStringDefault("Motd", "Welcome to an AzerothCore server")); ///- Read ticket system setting from the config file diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 35191b39f..e874d6fa8 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -703,7 +703,6 @@ class World void SetInitialWorldSettings(); void LoadConfigSettings(bool reload = false); - void LoadModuleConfigSettings(); void SendWorldText(uint32 string_id, ...); void SendGlobalText(const char* text, WorldSession* self); @@ -837,9 +836,6 @@ class World std::string const& GetRealmName() const { return _realmName; } // pussywizard void SetRealmName(std::string name) { _realmName = name; } // pussywizard - std::string GetConfigFileList() { return m_configFileList; } - void SetConfigFileList(std::string list) { m_configFileList = list; } - protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters @@ -939,8 +935,6 @@ class World void ProcessQueryCallbacks(); ACE_Future_Set m_realmCharCallbacks; - - std::string m_configFileList; }; #define sWorld World::instance() diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 5e0387240..e688845d1 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -319,7 +319,6 @@ public: { sLog->outString("Re-Loading config settings..."); sWorld->LoadConfigSettings(true); - sWorld->LoadModuleConfigSettings();//reload modules config setting sMapMgr->InitializeVisibilityDistanceInfo(); handler->SendGlobalGMSysMessage("World config settings reloaded."); return true; diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index b9a1a2160..95041e4a7 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -20,7 +20,7 @@ #include "Master.h" #ifndef _ACORE_CORE_CONFIG -# define _ACORE_CORE_CONFIG "worldserver.conf" +#define _ACORE_CORE_CONFIG "worldserver.conf" #endif #ifdef _WIN32 @@ -61,7 +61,7 @@ void usage(const char* prog) extern int main(int argc, char** argv) { ///- Command line parsing to get the configuration file name - char const* cfg_file = _ACORE_CORE_CONFIG; + char const* configFile = _ACORE_CORE_CONFIG; int c = 1; while (c < argc) { @@ -79,7 +79,7 @@ extern int main(int argc, char** argv) return 1; } else - cfg_file = argv[c]; + configFile = argv[c]; } #ifdef _WIN32 @@ -118,22 +118,12 @@ extern int main(int argc, char** argv) ++c; } - std::string cfg_def_file=_ACORE_CORE_CONFIG; - cfg_def_file += ".dist"; + sConfigMgr->SetConfigList(std::string(configFile), std::string(CONFIG_FILE_LIST)); - if (!sConfigMgr->LoadInitial(cfg_def_file.c_str())) { - printf("ERROR: Invalid or missing default configuration file : %s\n", cfg_def_file.c_str()); + if (!sConfigMgr->LoadAppConfigs()) return 1; - } - - if (!sConfigMgr->LoadMore(cfg_file)) - { - printf("WARNING: Invalid or missing configuration file : %s\n", cfg_file); - printf("Verify that the file exists and has \'[worldserver]' written in the top of the file!\n"); - } - - sLog->outString("Using configuration file %s.", cfg_file); + sLog->outString("Using configuration file %s.", configFile); sLog->outString("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); sLog->outString("Using ACE version: %s", ACE_VERSION); diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 34a264768..6bb69e3e6 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -156,8 +156,8 @@ int Master::Run() // set server offline (not connectable) LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID); - //set module config file list - sWorld->SetConfigFileList(CONFIG_FILE_LIST); + // Loading modules configs + sConfigMgr->LoadModulesConfigs(); ///- Initialize the World sWorld->SetInitialWorldSettings();