feat(Core/Database): implement db loader (#4431)

This commit is contained in:
Kargatum
2021-04-12 15:09:13 +07:00
committed by GitHub
parent 81301c67d9
commit 53ce87d0f7
15 changed files with 426 additions and 226 deletions

View File

@@ -0,0 +1,10 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#include "DatabaseEnv.h"
WorldDatabaseWorkerPool WorldDatabase;
CharacterDatabaseWorkerPool CharacterDatabase;
LoginDatabaseWorkerPool LoginDatabase;

View File

@@ -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

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#include "DatabaseLoader.h"
#include "Config.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "Duration.h"
#include <mysqld_error.h>
#include <errmsg.h>
template <class T>
DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::string const& name)
{
_open.push([this, name, &pool]() -> bool
{
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", "");
if (dbString.empty())
{
sLog->outSQLDriver("Database %s not specified in configuration file!", name.c_str());
return false;
}
uint8 const asyncThreads = sConfigMgr->GetOption<uint8>(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<uint8>(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<Predicate>& 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<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>&, std::string const&);
template DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
template DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#ifndef DatabaseLoader_h__
#define DatabaseLoader_h__
#include "Define.h"
#include <functional>
#include <queue>
#include <stack>
#include <string>
template <class T>
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 <class T>
DatabaseLoader& AddDatabase(DatabaseWorkerPool<T>& 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<bool()>;
using Closer = std::function<void()>;
// Invokes all functions in the given queue and closes the databases on errors.
// Returns false when there was an error.
bool Process(std::queue<Predicate>& queue);
std::queue<Predicate> _open, _prepare;
std::stack<Closer> _close;
};
#endif // DatabaseLoader_h__

View File

@@ -12,7 +12,9 @@
template <class T> DatabaseWorkerPool<T>::DatabaseWorkerPool() :
_mqueue(new ACE_Message_Queue<ACE_SYNCH>(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 <class T> DatabaseWorkerPool<T>::DatabaseWorkerPool() :
}
template <class T>
bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads)
void DatabaseWorkerPool<T>::SetConnectionInfo(std::string const& infoString,
uint8 const asyncThreads, uint8 const synchThreads)
{
bool res = true;
_connectionInfo = MySQLConnectionInfo(infoString);
_connectionInfo = std::make_unique<MySQLConnectionInfo>(infoString);
_async_threads = asyncThreads;
_synch_threads = synchThreads;
}
template <class T>
uint32 DatabaseWorkerPool<T>::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 <class T>
@@ -99,6 +95,91 @@ void DatabaseWorkerPool<T>::Close()
sLog->outSQLDriver("All connections on DatabasePool '%s' closed.", GetDatabaseName());
}
template <class T>
uint32 DatabaseWorkerPool<T>::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<uint32>(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 <class T>
bool DatabaseWorkerPool<T>::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 <class T>
char const* DatabaseWorkerPool<T>::GetDatabaseName() const
{
return _connectionInfo->database.c_str();
}
template <class T>
void DatabaseWorkerPool<T>::Execute(const char* sql)
{

View File

@@ -7,8 +7,6 @@
#ifndef _DATABASEWORKERPOOL_H
#define _DATABASEWORKERPOOL_H
#include <ace/Thread_Mutex.h>
#include "Common.h"
#include "Callback.h"
#include "MySQLConnection.h"
@@ -20,6 +18,7 @@
#include "QueryHolder.h"
#include "AdhocStatement.h"
#include "StringFormat.h"
#include <ace/Thread_Mutex.h>
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<ACE_SYNCH>* _mqueue;
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
std::vector<std::vector<T*>> _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<ACE_SYNCH>* _mqueue;
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
std::vector<std::vector<T*>> _connections;
uint32 _connectionCount[IDX_SIZE]; //! Counter of MySQL connections;
std::unique_ptr<MySQLConnectionInfo> _connectionInfo;
std::vector<uint8> _preparedStatementSize;
uint8 _async_threads, _synch_threads;
};
#endif

View File

@@ -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()

View File

@@ -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

View File

@@ -12,21 +12,22 @@
* authentication server
*/
#include <ace/Dev_Poll_Reactor.h>
#include <ace/TP_Reactor.h>
#include <ace/ACE.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#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 <ace/Dev_Poll_Reactor.h>
#include <ace/TP_Reactor.h>
#include <ace/ACE.h>
#include <ace/Sig_Handler.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#ifdef __linux__
#include <sched.h>
@@ -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<std::string>("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<int32>("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<int32>("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;

View File

@@ -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

View File

@@ -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();
}

View File

@@ -53,5 +53,4 @@ inline AI* GetAhnkahetAI(T* obj)
return GetInstanceAI<AI>(obj, AhnahetScriptName);
}
#endif

View File

@@ -29,6 +29,7 @@
#include "WorldRunnable.h"
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include "DatabaseLoader.h"
#include <ace/Sig_Handler.h>
#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<std::string>("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<int32>("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<int32>("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<std::string>("CharacterDatabaseInfo", "");
if (dbstring.empty())
{
sLog->outError("Character database not specified in configuration file");
return false;
}
async_threads = uint8(sConfigMgr->GetOption<int32>("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<int32>("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<std::string>("LoginDatabaseInfo", "");
if (dbstring.empty())
{
sLog->outError("Login database not specified in configuration file");
return false;
}
async_threads = uint8(sConfigMgr->GetOption<int32>("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<int32>("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<int32>("RealmID", 0);

View File

@@ -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);
}
}

View File

@@ -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);
}