mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
[Bug Fix] Fix for undefined MySQL library behavior. (#2834)
* MYSQL objects cannot be copied in a well defined way, this removes the copy and replaces it with another connection * Change to share underlying pointers. * Push up mutex changes * Post rebase * Formatting --------- Co-authored-by: KimLS <KimLS@peqtgc.com> Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
#include <thread>
|
||||
#include "../../common/repositories/zone_repository.h"
|
||||
#include "../../common/eqemu_config.h"
|
||||
#include <signal.h>
|
||||
|
||||
Database db;
|
||||
Database db2;
|
||||
|
||||
volatile sig_atomic_t stop;
|
||||
void inthand(int signum) {
|
||||
stop = 1;
|
||||
}
|
||||
|
||||
[[noreturn]] void DatabaseTest()
|
||||
{
|
||||
while (true) {
|
||||
LogInfo("DatabaseTest Query");
|
||||
db.QueryDatabase("SELECT 1");
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] void DatabaseTestSecondConnection()
|
||||
{
|
||||
while (true) {
|
||||
LogInfo("DatabaseTest Query");
|
||||
db2.QueryDatabase("SELECT 1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||
{
|
||||
description = "Test command to test database concurrency";
|
||||
|
||||
if (cmd[{"-h", "--help"}]) {
|
||||
return;
|
||||
}
|
||||
|
||||
signal(SIGINT, inthand);
|
||||
|
||||
LogInfo("Database test");
|
||||
|
||||
auto mutex = new Mutex;
|
||||
|
||||
auto c = EQEmuConfig::get();
|
||||
LogInfo("Connecting to MySQL");
|
||||
if (!db.Connect(
|
||||
c->DatabaseHost.c_str(),
|
||||
c->DatabaseUsername.c_str(),
|
||||
c->DatabasePassword.c_str(),
|
||||
c->DatabaseDB.c_str(),
|
||||
c->DatabasePort
|
||||
)) {
|
||||
LogError("Cannot continue without a database connection");
|
||||
return;
|
||||
}
|
||||
|
||||
db.SetMutex(mutex);
|
||||
|
||||
db2.SetMySQL(db);
|
||||
|
||||
db2.SetMutex(mutex);
|
||||
|
||||
std::thread(DatabaseTest).detach();
|
||||
std::thread(DatabaseTest).detach();
|
||||
std::thread(DatabaseTestSecondConnection).detach();
|
||||
|
||||
while (!stop) {
|
||||
|
||||
}
|
||||
|
||||
safe_delete(mutex);
|
||||
}
|
||||
@@ -478,6 +478,8 @@ int main(int argc, char **argv)
|
||||
LogInfo("Signaling HTTP service to stop");
|
||||
LogSys.CloseFileLogs();
|
||||
|
||||
WorldBoot::Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -30,6 +30,8 @@
|
||||
extern ZSList zoneserver_list;
|
||||
extern WorldConfig Config;
|
||||
|
||||
auto mutex = new Mutex;
|
||||
|
||||
void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message)
|
||||
{
|
||||
// we don't want to loop up with chat messages
|
||||
@@ -136,9 +138,7 @@ bool WorldBoot::LoadDatabaseConnections()
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-tenancy: Content database
|
||||
*/
|
||||
// Multi-tenancy - content database
|
||||
if (!c->ContentDbHost.empty()) {
|
||||
if (!content_db.Connect(
|
||||
c->ContentDbHost.c_str(),
|
||||
@@ -153,7 +153,12 @@ bool WorldBoot::LoadDatabaseConnections()
|
||||
}
|
||||
}
|
||||
else {
|
||||
content_db.SetMysql(database.getMySQL());
|
||||
content_db.SetMySQL(database);
|
||||
// when database and content_db share the same underlying mysql connection
|
||||
// it needs to be protected by a shared mutex otherwise we produce concurrency issues
|
||||
// when database actions are occurring in different threads
|
||||
database.SetMutex(mutex);
|
||||
content_db.SetMutex(mutex);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -652,3 +657,8 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
||||
}
|
||||
}
|
||||
|
||||
void WorldBoot::Shutdown()
|
||||
{
|
||||
safe_delete(mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
static void RegisterLoginservers();
|
||||
static bool DatabaseLoadRoutines(int argc, char **argv);
|
||||
static void CheckForPossibleConfigurationIssues();
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -31,10 +31,12 @@ void WorldserverCLI::CommandHandler(int argc, char **argv)
|
||||
function_map["test:expansion"] = &WorldserverCLI::ExpansionTestCommand;
|
||||
function_map["test:repository"] = &WorldserverCLI::TestRepository;
|
||||
function_map["test:repository2"] = &WorldserverCLI::TestRepository2;
|
||||
function_map["test:db-concurrency"] = &WorldserverCLI::TestDatabaseConcurrency;
|
||||
|
||||
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
||||
}
|
||||
|
||||
#include "cli/database_concurrency.cpp"
|
||||
#include "cli/copy_character.cpp"
|
||||
#include "cli/database_dump.cpp"
|
||||
#include "cli/database_get_schema.cpp"
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
static void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
static void TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user