From 7ee28d636118e539af8466b6c3cb7e02c6e0a4aa Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 12 Mar 2020 01:23:06 -0500 Subject: [PATCH] Migrate shared memory to use content database source; add logic in DB::core to prevent double freeing [skip ci] --- common/dbcore.cpp | 29 ++++++++++++++++++----------- common/dbcore.h | 10 ++++------ shared_memory/main.cpp | 31 +++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 0f07b5ab8..bc3ce0a72 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -42,11 +42,20 @@ DBcore::DBcore() pCompress = false; pSSL = false; pStatus = Closed; - connection_type = DATABASE_CONNECTION_DEFAULT; } DBcore::~DBcore() { + /** + * This prevents us from doing a double free in multi-tenancy setups where we + * are re-using the default database connection pointer when we dont have an + * external configuration setup ex: (content_database) + */ + std::string mysql_connection_host = mysql.host; + if (GetOriginHost() != mysql_connection_host) { + return; + } + mysql_close(&mysql); safe_delete_array(pHost); safe_delete_array(pUser); @@ -247,6 +256,10 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) } if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { pStatus = Connected; + + std::string connected_origin_host = pHost; + SetOriginHost(connected_origin_host); + return true; } else { @@ -266,18 +279,12 @@ void DBcore::SetMysql(MYSQL *mysql) DBcore::mysql = *mysql; } -int8 DBcore::GetConnectionType() const +const std::string &DBcore::GetOriginHost() const { - return connection_type; + return origin_host; } -void DBcore::SetConnectionType(int8 connection_type) +void DBcore::SetOriginHost(const std::string &origin_host) { - DBcore::connection_type = connection_type; + DBcore::origin_host = origin_host; } - - - - - - diff --git a/common/dbcore.h b/common/dbcore.h index cf5c4841f..8c508255b 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -13,9 +13,6 @@ #include #include -const int8 DATABASE_CONNECTION_DEFAULT = 0; -const int8 DATABASE_CONNECTION_CONTENT = 1; - class DBcore { public: enum eStatus { @@ -35,8 +32,8 @@ public: MYSQL *getMySQL() { return &mysql; } void SetMysql(MYSQL *mysql); - int8 GetConnectionType() const; - void SetConnectionType(int8 connection_type); + const std::string &GetOriginHost() const; + void SetOriginHost(const std::string &origin_host); protected: bool Open( @@ -54,11 +51,12 @@ protected: private: bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); - int8 connection_type; MYSQL mysql; Mutex MDatabase; eStatus pStatus; + std::string origin_host; + char *pHost; char *pUser; char *pPassword; diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index c5f8a5233..a515903e1 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -87,6 +87,7 @@ int main(int argc, char **argv) auto Config = EQEmuConfig::get(); SharedDatabase database; + SharedDatabase content_db; LogInfo("Connecting to database"); if (!database.Connect( Config->DatabaseHost.c_str(), @@ -99,6 +100,24 @@ int main(int argc, char **argv) return 1; } + /** + * Multi-tenancy: Content database + */ + if (!Config->ContentDbHost.empty()) { + if (!content_db.Connect( + Config->ContentDbHost.c_str() , + Config->ContentDbUsername.c_str(), + Config->ContentDbPassword.c_str(), + Config->ContentDbName.c_str(), + Config->ContentDbPort + )) { + LogError("Cannot continue without a content database connection"); + return 1; + } + } else { + content_db.SetMysql(database.getMySQL()); + } + /* Register Log System and Settings */ database.LoadLogSettings(LogSys.log_settings); LogSys.StartFileLogs(); @@ -194,7 +213,7 @@ int main(int argc, char **argv) if (load_all || load_items) { LogInfo("Loading items"); try { - LoadItems(&database, hotfix_name); + LoadItems(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1; @@ -204,7 +223,7 @@ int main(int argc, char **argv) if (load_all || load_factions) { LogInfo("Loading factions"); try { - LoadFactions(&database, hotfix_name); + LoadFactions(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1; @@ -214,7 +233,7 @@ int main(int argc, char **argv) if (load_all || load_loot) { LogInfo("Loading loot"); try { - LoadLoot(&database, hotfix_name); + LoadLoot(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1; @@ -224,7 +243,7 @@ int main(int argc, char **argv) if (load_all || load_skill_caps) { LogInfo("Loading skill caps"); try { - LoadSkillCaps(&database, hotfix_name); + LoadSkillCaps(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1; @@ -234,7 +253,7 @@ int main(int argc, char **argv) if (load_all || load_spells) { LogInfo("Loading spells"); try { - LoadSpells(&database, hotfix_name); + LoadSpells(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1; @@ -244,7 +263,7 @@ int main(int argc, char **argv) if (load_all || load_bd) { LogInfo("Loading base data"); try { - LoadBaseData(&database, hotfix_name); + LoadBaseData(&content_db, hotfix_name); } catch (std::exception &ex) { LogError("{}", ex.what()); return 1;