Migrate shared memory to use content database source; add logic in DB::core to prevent double freeing [skip ci]

This commit is contained in:
Akkadius 2020-03-12 01:23:06 -05:00
parent 49d835165c
commit 7ee28d6361
3 changed files with 47 additions and 23 deletions

View File

@ -42,11 +42,20 @@ DBcore::DBcore()
pCompress = false; pCompress = false;
pSSL = false; pSSL = false;
pStatus = Closed; pStatus = Closed;
connection_type = DATABASE_CONNECTION_DEFAULT;
} }
DBcore::~DBcore() 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); mysql_close(&mysql);
safe_delete_array(pHost); safe_delete_array(pHost);
safe_delete_array(pUser); 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)) { if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
pStatus = Connected; pStatus = Connected;
std::string connected_origin_host = pHost;
SetOriginHost(connected_origin_host);
return true; return true;
} }
else { else {
@ -266,18 +279,12 @@ void DBcore::SetMysql(MYSQL *mysql)
DBcore::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;
} }

View File

@ -13,9 +13,6 @@
#include <mysql.h> #include <mysql.h>
#include <string.h> #include <string.h>
const int8 DATABASE_CONNECTION_DEFAULT = 0;
const int8 DATABASE_CONNECTION_CONTENT = 1;
class DBcore { class DBcore {
public: public:
enum eStatus { enum eStatus {
@ -35,8 +32,8 @@ public:
MYSQL *getMySQL() { return &mysql; } MYSQL *getMySQL() { return &mysql; }
void SetMysql(MYSQL *mysql); void SetMysql(MYSQL *mysql);
int8 GetConnectionType() const; const std::string &GetOriginHost() const;
void SetConnectionType(int8 connection_type); void SetOriginHost(const std::string &origin_host);
protected: protected:
bool Open( bool Open(
@ -54,11 +51,12 @@ protected:
private: private:
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
int8 connection_type;
MYSQL mysql; MYSQL mysql;
Mutex MDatabase; Mutex MDatabase;
eStatus pStatus; eStatus pStatus;
std::string origin_host;
char *pHost; char *pHost;
char *pUser; char *pUser;
char *pPassword; char *pPassword;

View File

@ -87,6 +87,7 @@ int main(int argc, char **argv)
auto Config = EQEmuConfig::get(); auto Config = EQEmuConfig::get();
SharedDatabase database; SharedDatabase database;
SharedDatabase content_db;
LogInfo("Connecting to database"); LogInfo("Connecting to database");
if (!database.Connect( if (!database.Connect(
Config->DatabaseHost.c_str(), Config->DatabaseHost.c_str(),
@ -99,6 +100,24 @@ int main(int argc, char **argv)
return 1; 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 */ /* Register Log System and Settings */
database.LoadLogSettings(LogSys.log_settings); database.LoadLogSettings(LogSys.log_settings);
LogSys.StartFileLogs(); LogSys.StartFileLogs();
@ -194,7 +213,7 @@ int main(int argc, char **argv)
if (load_all || load_items) { if (load_all || load_items) {
LogInfo("Loading items"); LogInfo("Loading items");
try { try {
LoadItems(&database, hotfix_name); LoadItems(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;
@ -204,7 +223,7 @@ int main(int argc, char **argv)
if (load_all || load_factions) { if (load_all || load_factions) {
LogInfo("Loading factions"); LogInfo("Loading factions");
try { try {
LoadFactions(&database, hotfix_name); LoadFactions(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;
@ -214,7 +233,7 @@ int main(int argc, char **argv)
if (load_all || load_loot) { if (load_all || load_loot) {
LogInfo("Loading loot"); LogInfo("Loading loot");
try { try {
LoadLoot(&database, hotfix_name); LoadLoot(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;
@ -224,7 +243,7 @@ int main(int argc, char **argv)
if (load_all || load_skill_caps) { if (load_all || load_skill_caps) {
LogInfo("Loading skill caps"); LogInfo("Loading skill caps");
try { try {
LoadSkillCaps(&database, hotfix_name); LoadSkillCaps(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;
@ -234,7 +253,7 @@ int main(int argc, char **argv)
if (load_all || load_spells) { if (load_all || load_spells) {
LogInfo("Loading spells"); LogInfo("Loading spells");
try { try {
LoadSpells(&database, hotfix_name); LoadSpells(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;
@ -244,7 +263,7 @@ int main(int argc, char **argv)
if (load_all || load_bd) { if (load_all || load_bd) {
LogInfo("Loading base data"); LogInfo("Loading base data");
try { try {
LoadBaseData(&database, hotfix_name); LoadBaseData(&content_db, hotfix_name);
} catch (std::exception &ex) { } catch (std::exception &ex) {
LogError("{}", ex.what()); LogError("{}", ex.what());
return 1; return 1;