From 53ce87d0f7db456231b662d298d1c2cc7add37f9 Mon Sep 17 00:00:00 2001 From: Kargatum Date: Mon, 12 Apr 2021 15:09:13 +0700 Subject: [PATCH] feat(Core/Database): implement db loader (#4431) --- src/common/Database/DatabaseEnv.cpp | 10 ++ src/common/Database/DatabaseEnv.h | 11 +- src/common/Database/DatabaseLoader.cpp | 142 ++++++++++++++++++ src/common/Database/DatabaseLoader.h | 56 +++++++ src/common/Database/DatabaseWorkerPool.cpp | 141 +++++++++++++---- src/common/Database/DatabaseWorkerPool.h | 58 +++---- src/common/Database/MySQLConnection.cpp | 86 +++++------ src/common/Database/MySQLConnection.h | 7 +- src/server/authserver/Main.cpp | 53 +++---- src/server/game/Entities/Player/Player.cpp | 1 - src/server/game/Globals/ObjectMgr.cpp | 2 - .../Northrend/AzjolNerub/ahnkahet/ahnkahet.h | 1 - src/server/worldserver/Master.cpp | 81 ++-------- src/tools/vmap4_extractor/model.cpp | 2 - src/tools/vmap4_extractor/wmo.cpp | 1 - 15 files changed, 426 insertions(+), 226 deletions(-) create mode 100644 src/common/Database/DatabaseEnv.cpp create mode 100644 src/common/Database/DatabaseLoader.cpp create mode 100644 src/common/Database/DatabaseLoader.h diff --git a/src/common/Database/DatabaseEnv.cpp b/src/common/Database/DatabaseEnv.cpp new file mode 100644 index 000000000..3fd2f2a65 --- /dev/null +++ b/src/common/Database/DatabaseEnv.cpp @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2021+ WarheadCore + */ + +#include "DatabaseEnv.h" + +WorldDatabaseWorkerPool WorldDatabase; +CharacterDatabaseWorkerPool CharacterDatabase; +LoginDatabaseWorkerPool LoginDatabase; diff --git a/src/common/Database/DatabaseEnv.h b/src/common/Database/DatabaseEnv.h index 5c57dc37b..aaa1088c9 100644 --- a/src/common/Database/DatabaseEnv.h +++ b/src/common/Database/DatabaseEnv.h @@ -22,12 +22,17 @@ #define _CONCAT3_(A, B, C) "CONCAT( " A ", " B ", " C " )" #define _OFFSET_ "LIMIT %d, 1" -#include "Implementation/LoginDatabase.h" -#include "Implementation/CharacterDatabase.h" -#include "Implementation/WorldDatabase.h" +#include "LoginDatabase.h" +#include "CharacterDatabase.h" +#include "WorldDatabase.h" +/// Accessor to the world database extern WorldDatabaseWorkerPool WorldDatabase; + +/// Accessor to the character database extern CharacterDatabaseWorkerPool CharacterDatabase; + +/// Accessor to the realm/login database extern LoginDatabaseWorkerPool LoginDatabase; #endif diff --git a/src/common/Database/DatabaseLoader.cpp b/src/common/Database/DatabaseLoader.cpp new file mode 100644 index 000000000..ef712dcca --- /dev/null +++ b/src/common/Database/DatabaseLoader.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2021+ WarheadCore + */ + +#include "DatabaseLoader.h" +#include "Config.h" +#include "DatabaseEnv.h" +#include "Log.h" +#include "Duration.h" +#include +#include + +template +DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name) +{ + _open.push([this, name, &pool]() -> bool + { + std::string const dbString = sConfigMgr->GetOption(name + "DatabaseInfo", ""); + if (dbString.empty()) + { + sLog->outSQLDriver("Database %s not specified in configuration file!", name.c_str()); + return false; + } + + uint8 const asyncThreads = sConfigMgr->GetOption(name + "Database.WorkerThreads", 1); + if (asyncThreads < 1 || asyncThreads > 32) + { + sLog->outSQLDriver("%s database: invalid number of worker threads specified. Please pick a value between 1 and 32.", name.c_str()); + return false; + } + + uint8 const synchThreads = sConfigMgr->GetOption(name + "Database.SynchThreads", 1); + + pool.SetConnectionInfo(dbString, asyncThreads, synchThreads); + + if (uint32 error = pool.Open()) + { + // Try reconnect + if (error == CR_CONNECTION_ERROR) + { + // Possible improvement for future: make ATTEMPTS and SECONDS configurable values + uint32 const ATTEMPTS = 5; + Seconds durationSecs = 5s; + uint32 count = 1; + + auto sleepThread = [&]() + { + sLog->outSQLDriver("> Retrying after %u seconds", durationSecs.count()); + std::this_thread::sleep_for(durationSecs); + }; + + sleepThread(); + + do + { + error = pool.Open(); + + if (error == CR_CONNECTION_ERROR) + { + sleepThread(); + count++; + } + else + { + break; + } + + } while (count < ATTEMPTS); + } + + // If the error wasn't handled quit + if (error) + { + sLog->outSQLDriver("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile for specific errors", name.c_str()); + return false; + } + } + + // Add the close operation + _close.push([&pool] + { + pool.Close(); + }); + + return true; + }); + + _prepare.push([name, &pool]() -> bool + { + if (!pool.PrepareStatements()) + { + sLog->outSQLDriver("Could not prepare statements of the %s database, see log for details.", name.c_str()); + return false; + } + + return true; + }); + + return *this; +} + +bool DatabaseLoader::Load() +{ + return OpenDatabases() && PrepareStatements(); +} + +bool DatabaseLoader::OpenDatabases() +{ + return Process(_open); +} + +bool DatabaseLoader::PrepareStatements() +{ + return Process(_prepare); +} + +bool DatabaseLoader::Process(std::queue& queue) +{ + while (!queue.empty()) + { + if (!queue.front()()) + { + // Close all open databases which have a registered close operation + while (!_close.empty()) + { + _close.top()(); + _close.pop(); + } + + return false; + } + + queue.pop(); + } + + return true; +} + +template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); +template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); +template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); diff --git a/src/common/Database/DatabaseLoader.h b/src/common/Database/DatabaseLoader.h new file mode 100644 index 000000000..df0dcc678 --- /dev/null +++ b/src/common/Database/DatabaseLoader.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2021+ WarheadCore + */ + +#ifndef DatabaseLoader_h__ +#define DatabaseLoader_h__ + +#include "Define.h" +#include +#include +#include +#include + +template +class DatabaseWorkerPool; + +// A helper class to initiate all database worker pools, +// handles updating, delays preparing of statements and cleans up on failure. +class DatabaseLoader +{ +public: + // Register a database to the loader (lazy implemented) + template + DatabaseLoader& AddDatabase(DatabaseWorkerPool& pool, std::string const& name); + + // Load all databases + bool Load(); + + enum DatabaseTypeFlags + { + DATABASE_NONE = 0, + + DATABASE_LOGIN = 1, + DATABASE_CHARACTER = 2, + DATABASE_WORLD = 4, + + DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD + }; + +private: + bool OpenDatabases(); + bool PrepareStatements(); + + using Predicate = std::function; + using Closer = std::function; + + // Invokes all functions in the given queue and closes the databases on errors. + // Returns false when there was an error. + bool Process(std::queue& queue); + + std::queue _open, _prepare; + std::stack _close; +}; + +#endif // DatabaseLoader_h__ diff --git a/src/common/Database/DatabaseWorkerPool.cpp b/src/common/Database/DatabaseWorkerPool.cpp index 30ef85e0e..1b5add546 100644 --- a/src/common/Database/DatabaseWorkerPool.cpp +++ b/src/common/Database/DatabaseWorkerPool.cpp @@ -12,7 +12,9 @@ template DatabaseWorkerPool::DatabaseWorkerPool() : _mqueue(new ACE_Message_Queue(2 * 1024 * 1024, 2 * 1024 * 1024)), - _queue(new ACE_Activation_Queue(_mqueue)) + _queue(new ACE_Activation_Queue(_mqueue)), + _async_threads(0), + _synch_threads(0) { memset(_connectionCount, 0, sizeof(_connectionCount)); _connections.resize(IDX_SIZE); @@ -22,45 +24,39 @@ template DatabaseWorkerPool::DatabaseWorkerPool() : } template -bool DatabaseWorkerPool::Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads) +void DatabaseWorkerPool::SetConnectionInfo(std::string const& infoString, + uint8 const asyncThreads, uint8 const synchThreads) { - bool res = true; - _connectionInfo = MySQLConnectionInfo(infoString); + _connectionInfo = std::make_unique(infoString); + + _async_threads = asyncThreads; + _synch_threads = synchThreads; +} + +template +uint32 DatabaseWorkerPool::Open() +{ + WPFatal(_connectionInfo.get(), "Connection info was not set!"); sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.", - GetDatabaseName(), async_threads, synch_threads); + GetDatabaseName(), _async_threads, _synch_threads); - //! Open asynchronous connections (delayed operations) - _connections[IDX_ASYNC].resize(async_threads); - for (uint8 i = 0; i < async_threads; ++i) + uint32 error = OpenConnections(IDX_ASYNC, _async_threads); + + if (error) { - T* t = new T(_queue, _connectionInfo); - res &= t->Open(); - if (res) // only check mysql version if connection is valid - WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "AzerothCore does not support MySQL versions below 5.7"); - - _connections[IDX_ASYNC][i] = t; - ++_connectionCount[IDX_ASYNC]; + return error; } - //! Open synchronous connections (direct, blocking operations) - _connections[IDX_SYNCH].resize(synch_threads); - for (uint8 i = 0; i < synch_threads; ++i) + error = OpenConnections(IDX_SYNCH, _synch_threads); + + if (!error) { - T* t = new T(_connectionInfo); - res &= t->Open(); - _connections[IDX_SYNCH][i] = t; - ++_connectionCount[IDX_SYNCH]; + sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", + GetDatabaseName(), (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC])); } - if (res) - sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(), - (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC])); - else - sLog->outError("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " - "for specific errors.", GetDatabaseName()); - - return res; + return error; } template @@ -99,6 +95,91 @@ void DatabaseWorkerPool::Close() sLog->outSQLDriver("All connections on DatabasePool '%s' closed.", GetDatabaseName()); } +template +uint32 DatabaseWorkerPool::OpenConnections(InternalIndex type, uint8 numConnections) +{ + _connections[type].resize(numConnections); + for (uint8 i = 0; i < numConnections; ++i) + { + T* t; + + if (type == IDX_ASYNC) + { + t = new T(_queue, *_connectionInfo); + } + else if (type == IDX_SYNCH) + { + t = new T(*_connectionInfo); + } + else + { + ASSERT(false, "> Incorrect InternalIndex (%u)", static_cast(type)); + } + + _connections[type][i] = t; + ++_connectionCount[type]; + + uint32 error = t->Open(); + + if (!error) + { + if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION) + { + sLog->outSQLDriver("Not support MySQL versions below 5.7"); + error = 1; + } + } + + // Failed to open a connection or invalid version, abort and cleanup + if (error) + { + while (_connectionCount[type] != 0) + { + T* t = _connections[type][i--]; + delete t; + --_connectionCount[type]; + } + + return error; + } + } + + // Everything is fine + return 0; +} + +template +bool DatabaseWorkerPool::PrepareStatements() +{ + for (uint8 i = 0; i < IDX_SIZE; ++i) + { + for (uint32 c = 0; c < _connectionCount[i]; ++c) + { + T* t = _connections[i][c]; + t->LockIfReady(); + + if (!t->PrepareStatements()) + { + t->Unlock(); + Close(); + return false; + } + else + { + t->Unlock(); + } + } + } + + return true; +} + +template +char const* DatabaseWorkerPool::GetDatabaseName() const +{ + return _connectionInfo->database.c_str(); +} + template void DatabaseWorkerPool::Execute(const char* sql) { diff --git a/src/common/Database/DatabaseWorkerPool.h b/src/common/Database/DatabaseWorkerPool.h index eadeeaa26..f6290c9c0 100644 --- a/src/common/Database/DatabaseWorkerPool.h +++ b/src/common/Database/DatabaseWorkerPool.h @@ -7,8 +7,6 @@ #ifndef _DATABASEWORKERPOOL_H #define _DATABASEWORKERPOOL_H -#include - #include "Common.h" #include "Callback.h" #include "MySQLConnection.h" @@ -20,6 +18,7 @@ #include "QueryHolder.h" #include "AdhocStatement.h" #include "StringFormat.h" +#include class PingOperation : public SQLOperation { @@ -37,13 +36,20 @@ class DatabaseWorkerPool public: /* Activity state */ DatabaseWorkerPool(); - ~DatabaseWorkerPool() = default; - bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads); - + void SetConnectionInfo(std::string const& infoString, uint8 const asyncThreads, uint8 const synchThreads); + uint32 Open(); void Close(); + //! Prepares all prepared statements + bool PrepareStatements(); + + inline MySQLConnectionInfo const* GetConnectionInfo() const + { + return _connectionInfo.get(); + } + /** Delayed one-way statement methods. */ @@ -199,11 +205,6 @@ public: //! Keeps all our MySQL connections alive, prevent the server from disconnecting us. void KeepAlive(); - [[nodiscard]] char const* GetDatabaseName() const - { - return _connectionInfo.database.c_str(); - } - void EscapeString(std::string& str) { if (str.empty()) @@ -216,28 +217,33 @@ public: } private: - void Enqueue(SQLOperation* op) - { - _queue->enqueue(op); - } - - //! Gets a free connection in the synchronous connection pool. - //! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks. - T* GetFreeConnection(); - -private: - enum _internalIndex + enum InternalIndex { IDX_ASYNC, IDX_SYNCH, IDX_SIZE }; - ACE_Message_Queue* _mqueue; - ACE_Activation_Queue* _queue; //! Queue shared by async worker threads. - std::vector> _connections; - uint32 _connectionCount[2]; //! Counter of MySQL connections; - MySQLConnectionInfo _connectionInfo; + uint32 OpenConnections(InternalIndex type, uint8 numConnections); + + void Enqueue(SQLOperation* op) + { + _queue->enqueue(op); + } + + [[nodiscard]] char const* GetDatabaseName() const; + + //! Gets a free connection in the synchronous connection pool. + //! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks. + T* GetFreeConnection(); + + ACE_Message_Queue* _mqueue; + ACE_Activation_Queue* _queue; //! Queue shared by async worker threads. + std::vector> _connections; + uint32 _connectionCount[IDX_SIZE]; //! Counter of MySQL connections; + std::unique_ptr _connectionInfo; + std::vector _preparedStatementSize; + uint8 _async_threads, _synch_threads; }; #endif diff --git a/src/common/Database/MySQLConnection.cpp b/src/common/Database/MySQLConnection.cpp index d3b25fc2a..06e9fe351 100644 --- a/src/common/Database/MySQLConnection.cpp +++ b/src/common/Database/MySQLConnection.cpp @@ -47,12 +47,14 @@ MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInf MySQLConnection::~MySQLConnection() { - ASSERT (m_Mysql); /// MySQL context must be present at this point + for (auto stmt : m_stmts) + delete stmt; - for (size_t i = 0; i < m_stmts.size(); ++i) - delete m_stmts[i]; - - mysql_close(m_Mysql); + if (m_Mysql) + { + mysql_close(m_Mysql); + m_Mysql = nullptr; + } } void MySQLConnection::Close() @@ -61,10 +63,9 @@ void MySQLConnection::Close() delete this; } -bool MySQLConnection::Open() +uint32 MySQLConnection::Open() { - MYSQL* mysqlInit; - mysqlInit = mysql_init(nullptr); + MYSQL* mysqlInit = mysql_init(nullptr); if (!mysqlInit) { sLog->outError("Could not initialize Mysql connection to database `%s`", m_connectionInfo.database.c_str()); @@ -106,59 +107,44 @@ bool MySQLConnection::Open() } #endif - // Possible improvement for future: make ATTEMPTS and SECONDS configurable values - uint32 const ATTEMPTS = 180; + m_Mysql = mysql_real_connect( + mysqlInit, + m_connectionInfo.host.c_str(), + m_connectionInfo.user.c_str(), + m_connectionInfo.password.c_str(), + m_connectionInfo.database.c_str(), + port, + unix_socket, + 0); - uint32 count = 0; - do + if (m_Mysql) { - m_Mysql = mysql_real_connect( - mysqlInit, - m_connectionInfo.host.c_str(), - m_connectionInfo.user.c_str(), - m_connectionInfo.password.c_str(), - m_connectionInfo.database.c_str(), - port, - unix_socket, - 0); - - if (m_Mysql) + if (!m_reconnecting) { - if (!m_reconnecting) + sLog->outSQLDriver("MySQL client library: %s", mysql_get_client_info()); + sLog->outSQLDriver("MySQL server ver: %s ", mysql_get_server_info(m_Mysql)); + + if (mysql_get_server_version(m_Mysql) != mysql_get_client_version()) { - sLog->outSQLDriver("MySQL client library: %s", mysql_get_client_info()); - sLog->outSQLDriver("MySQL server ver: %s ", mysql_get_server_info(m_Mysql)); - // MySQL version above 5.1 IS required in both client and server and there is no known issue with different versions above 5.1 - // if (mysql_get_server_version(m_Mysql) != mysql_get_client_version()) - // sLog->outInfo(LOG_FILTER_SQL, "[WARNING] MySQL client/server version mismatch; may conflict with behaviour of prepared statements."); + sLog->outSQLDriver("[WARNING] MySQL client/server version mismatch; may conflict with behaviour of prepared statements."); } + } #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDetail("Connected to MySQL database at %s", m_connectionInfo.host.c_str()); + sLog->outDetail("Connected to MySQL database at %s", m_connectionInfo.host.c_str()); #endif - mysql_autocommit(m_Mysql, 1); + mysql_autocommit(m_Mysql, 1); - // set connection properties to UTF8 to properly handle locales for different - // server configs - core sends data in UTF8, so MySQL must expect UTF8 too - mysql_set_character_set(m_Mysql, "utf8"); - return PrepareStatements(); - } - else - { - count++; - sLog->outError("Could not connect to MySQL database at %s: %s\n", m_connectionInfo.host.c_str(), mysql_error(mysqlInit)); - sLog->outError("Retrying in 10 seconds...\n\n"); - std::this_thread::sleep_for(10s); - } - } while (!m_Mysql && count < ATTEMPTS); + // set connection properties to UTF8 to properly handle locales for different + // server configs - core sends data in UTF8, so MySQL must expect UTF8 too + mysql_set_character_set(m_Mysql, "utf8"); + return 0; + } - sLog->outError( - "Could not connect to MySQL database at %s: %s after %d attempts\n", - m_connectionInfo.host.c_str(), - mysql_error(mysqlInit), - ATTEMPTS); + sLog->outError("Could not connect to MySQL database at %s: %s", m_connectionInfo.host.c_str(), mysql_error(mysqlInit)); + uint32 errorCode = mysql_errno(mysqlInit); mysql_close(mysqlInit); - return false; + return errorCode; } bool MySQLConnection::PrepareStatements() diff --git a/src/common/Database/MySQLConnection.h b/src/common/Database/MySQLConnection.h index aabc71451..b90be5bad 100644 --- a/src/common/Database/MySQLConnection.h +++ b/src/common/Database/MySQLConnection.h @@ -63,8 +63,9 @@ public: MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections. virtual ~MySQLConnection(); - virtual bool Open(); + virtual uint32 Open(); void Close(); + bool PrepareStatements(); public: bool Execute(const char* sql); @@ -102,7 +103,6 @@ protected: MySQLPreparedStatement* GetPreparedStatement(uint32 index); void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags); - bool PrepareStatements(); virtual void DoPrepareStatements() = 0; protected: @@ -121,6 +121,9 @@ private: MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging) ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements) ACE_Thread_Mutex m_Mutex; + + MySQLConnection(MySQLConnection const& right) = delete; + MySQLConnection& operator=(MySQLConnection const& right) = delete; }; #endif diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index c8961ce29..c385c87fb 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -12,21 +12,22 @@ * authentication server */ -#include -#include -#include -#include -#include - #include "Common.h" -#include "Database/DatabaseEnv.h" -#include "Configuration/Config.h" +#include "DatabaseEnv.h" +#include "Config.h" #include "Log.h" #include "GitRevision.h" #include "Util.h" #include "SignalHandler.h" #include "RealmList.h" #include "RealmAcceptor.h" +#include "DatabaseLoader.h" +#include +#include +#include +#include +#include +#include #ifdef __linux__ #include @@ -43,8 +44,6 @@ void StopDB(); bool stopEvent = false; // Setting it to true stops the server -LoginDatabaseWorkerPool LoginDatabase; // Accessor to the authserver database - /// Print out the usage string for this program on the console. void usage(const char* prog) { @@ -281,33 +280,15 @@ bool StartDB() { MySQL::Library_Init(); - std::string dbstring = sConfigMgr->GetOption("LoginDatabaseInfo", ""); - if (dbstring.empty()) - { - sLog->outError("Database not specified"); + // Load databases + // NOTE: While authserver is singlethreaded you should keep synch_threads == 1. + // Increasing it is just silly since only 1 will be used ever. + DatabaseLoader loader; + loader + .AddDatabase(LoginDatabase, "Login"); + + if (!loader.Load()) return false; - } - - int32 worker_threads = sConfigMgr->GetOption("LoginDatabase.WorkerThreads", 1); - if (worker_threads < 1 || worker_threads > 32) - { - sLog->outError("Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1."); - worker_threads = 1; - } - - int32 synch_threads = sConfigMgr->GetOption("LoginDatabase.SynchThreads", 1); - if (synch_threads < 1 || synch_threads > 32) - { - sLog->outError("Improper value specified for LoginDatabase.SynchThreads, defaulting to 1."); - synch_threads = 1; - } - - // NOTE: While authserver is singlethreaded you should keep synch_threads == 1. Increasing it is just silly since only 1 will be used ever. - if (!LoginDatabase.Open(dbstring.c_str(), uint8(worker_threads), uint8(synch_threads))) - { - sLog->outError("Cannot connect to database"); - return false; - } sLog->outString("Started auth database connection pool."); return true; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c7ab3adb3..c12fbdae1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -19852,7 +19852,6 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map } } - Difficulty target_difficulty = GetDifficulty(mapEntry->IsRaid()); MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(target_map, target_difficulty); if (LevelMin || LevelMax || ilvlRequirementNotMet diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 00f79e2ec..52d5edfb2 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6342,7 +6342,6 @@ void ObjectMgr::LoadAccessRequirements() currentRequirementsList->push_back(progression_requirement); } - } while (progression_requirements_results->NextRow()); } @@ -6360,7 +6359,6 @@ void ObjectMgr::LoadAccessRequirements() _accessRequirementStore[mapid][difficulty] = ar; } while (access_template_result->NextRow()); - sLog->outString(">> Loaded %u rows from dungeon_access_template and %u rows from dungeon_access_requirements in %u ms", count, countProgressionRequirements, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h index 74866b171..161008be1 100644 --- a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h @@ -53,5 +53,4 @@ inline AI* GetAhnkahetAI(T* obj) return GetInstanceAI(obj, AhnahetScriptName); } - #endif diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 588e26009..792f3033d 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -29,6 +29,7 @@ #include "WorldRunnable.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" +#include "DatabaseLoader.h" #include #ifdef _WIN32 @@ -388,80 +389,16 @@ bool Master::_StartDB() MySQL::Library_Init(); sLog->SetLogDB(false); - std::string dbstring; - uint8 async_threads, synch_threads; - dbstring = sConfigMgr->GetOption("WorldDatabaseInfo", ""); - if (dbstring.empty()) - { - sLog->outError("World database not specified in configuration file"); + // Load databases + DatabaseLoader loader; + loader + .AddDatabase(LoginDatabase, "Login") + .AddDatabase(CharacterDatabase, "Character") + .AddDatabase(WorldDatabase, "World"); + + if (!loader.Load()) return false; - } - - async_threads = uint8(sConfigMgr->GetOption("WorldDatabase.WorkerThreads", 1)); - if (async_threads < 1 || async_threads > 32) - { - sLog->outError("World database: invalid number of worker threads specified. " - "Please pick a value between 1 and 32."); - return false; - } - - synch_threads = uint8(sConfigMgr->GetOption("WorldDatabase.SynchThreads", 1)); - ///- Initialise the world database - if (!WorldDatabase.Open(dbstring, async_threads, synch_threads)) - { - sLog->outError("Cannot connect to world database %s", dbstring.c_str()); - return false; - } - - ///- Get character database info from configuration file - dbstring = sConfigMgr->GetOption("CharacterDatabaseInfo", ""); - if (dbstring.empty()) - { - sLog->outError("Character database not specified in configuration file"); - return false; - } - - async_threads = uint8(sConfigMgr->GetOption("CharacterDatabase.WorkerThreads", 1)); - if (async_threads < 1 || async_threads > 32) - { - sLog->outError("Character database: invalid number of worker threads specified. " - "Please pick a value between 1 and 32."); - return false; - } - - synch_threads = uint8(sConfigMgr->GetOption("CharacterDatabase.SynchThreads", 2)); - - ///- Initialise the Character database - if (!CharacterDatabase.Open(dbstring, async_threads, synch_threads)) - { - sLog->outError("Cannot connect to Character database %s", dbstring.c_str()); - return false; - } - - ///- Get login database info from configuration file - dbstring = sConfigMgr->GetOption("LoginDatabaseInfo", ""); - if (dbstring.empty()) - { - sLog->outError("Login database not specified in configuration file"); - return false; - } - - async_threads = uint8(sConfigMgr->GetOption("LoginDatabase.WorkerThreads", 1)); - if (async_threads < 1 || async_threads > 32) - { - sLog->outError("Login database: invalid number of worker threads specified. " - "Please pick a value between 1 and 32."); - return false; - } - - synch_threads = uint8(sConfigMgr->GetOption("LoginDatabase.SynchThreads", 1)); - ///- Initialise the login database - if (!LoginDatabase.Open(dbstring, async_threads, synch_threads)) - { - sLog->outError("Cannot connect to login database %s", dbstring.c_str()); - return false; - } ///- Get the realm Id from the configuration file realmID = sConfigMgr->GetOption("RealmID", 0); diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index ce92d0d2f..b561f944d 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -120,7 +120,6 @@ bool Model::ConvertToVMAPModel(const char* outfilename) return true; } - Vec3D fixCoordSystem(Vec3D const& v) { return Vec3D(v.x, v.z, -v.y); @@ -250,4 +249,3 @@ void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, u fwrite(ModelInstName, sizeof(char), nlen, pDirfile); } } - diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 82bde3ae8..d7380e34a 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -558,5 +558,4 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(WmoInstName, sizeof(char), nlen, pDirfile); - }