diff options
author | Machiavelli <none@none> | 2010-09-27 00:20:56 +0200 |
---|---|---|
committer | Machiavelli <none@none> | 2010-09-27 00:20:56 +0200 |
commit | a9e9a2c8848c22e4a3e3b7bab0caeca25d9ea408 (patch) | |
tree | a7c4960796d0a9a42cb1e0252d4a75c4436d1f01 | |
parent | 894b2081b3837575bd44c71ea4ebc76008b5b5e3 (diff) |
Core/DBLayer:
- DB Threading model update
* Get rid of ThreadBundleMask and bundled connection
* Implement configurable amount of Synch threads for databasepools
* Use modulus based algorithm to check for free synchronous connections instead of previous ¨get connection by thread key or bundlemask¨ feature
* Locks on mysql context objects are now managed outside the mysql query methods
Fixes issue #4058
Fixes issue #4059
Introduces a ton of more issues. Use at own risk. You were warned. Really.
Don´t forget to update your worldserver.conf
--HG--
branch : trunk
-rw-r--r-- | src/server/authserver/Main.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Maps/MapUpdater.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocketMgr.cpp | 17 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorker.cpp | 5 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorker.h | 2 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.h | 227 | ||||
-rw-r--r-- | src/server/shared/Database/MySQLConnection.cpp | 22 | ||||
-rw-r--r-- | src/server/shared/Database/MySQLConnection.h | 16 | ||||
-rw-r--r-- | src/server/worldserver/Master.cpp | 40 | ||||
-rw-r--r-- | src/server/worldserver/WorldThread/WorldRunnable.cpp | 34 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 27 |
11 files changed, 171 insertions, 240 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index d23aecf3313..f92949aadc5 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -339,15 +339,22 @@ bool StartDB() return false; } - uint8 num_threads = sConfig.GetIntDefault("LoginDatabase.WorkerThreads", 1); - if (num_threads < 1 || num_threads > 32) + uint8 worker_threads = sConfig.GetIntDefault("LoginDatabase.WorkerThreads", 1); + if (worker_threads < 1 || worker_threads > 32) { sLog.outError("Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1."); - num_threads = 1; + worker_threads = 1; } - //- Authserver has singlethreaded synchronous DB access, hence MYSQL_BUNDLE_ALL - if (!LoginDatabase.Open(dbstring.c_str(), num_threads, MYSQL_BUNDLE_ALL)) + uint8 synch_threads = sConfig.GetIntDefault("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(), worker_threads, synch_threads)) { sLog.outError("Cannot connect to database"); return false; diff --git a/src/server/game/Maps/MapUpdater.cpp b/src/server/game/Maps/MapUpdater.cpp index f9b1b5dda62..7e6b2f03bd0 100644 --- a/src/server/game/Maps/MapUpdater.cpp +++ b/src/server/game/Maps/MapUpdater.cpp @@ -16,8 +16,6 @@ class WDBThreadStartReq1 : public ACE_Method_Request virtual int call() { - WorldDatabase.Init_MySQL_Connection(); - CharacterDatabase.Init_MySQL_Connection(); return 0; } }; @@ -32,8 +30,6 @@ class WDBThreadEndReq1 : public ACE_Method_Request virtual int call() { - WorldDatabase.End_MySQL_Connection(); - CharacterDatabase.End_MySQL_Connection(); return 0; } }; diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp index 7422170fa59..a7778f9405e 100644 --- a/src/server/game/Server/WorldSocketMgr.cpp +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -158,16 +158,6 @@ class ReactorRunnable : protected ACE_Task_Base { sLog.outStaticDebug ("Network Thread Starting"); - bool needInit = true; - if (!(LoginDatabase.GetBundleMask() & MYSQL_BUNDLE_RAR)) - { - LoginDatabase.Init_MySQL_Connection(); - needInit = false; - } - - if (needInit) - MySQL::Thread_Init(); - ACE_ASSERT (m_Reactor); SocketSet::iterator i, t; @@ -203,13 +193,6 @@ class ReactorRunnable : protected ACE_Task_Base } } - ///- Free MySQL thread resources and deallocate lingering connections - if (!(LoginDatabase.GetBundleMask() & MYSQL_BUNDLE_RAR)) - LoginDatabase.End_MySQL_Connection(); - - if (needInit) - MySQL::Thread_End(); - sLog.outStaticDebug ("Network Thread Exitting"); return 0; diff --git a/src/server/shared/Database/DatabaseWorker.cpp b/src/server/shared/Database/DatabaseWorker.cpp index 0fd7287f23a..9d903ac6db4 100644 --- a/src/server/shared/Database/DatabaseWorker.cpp +++ b/src/server/shared/Database/DatabaseWorker.cpp @@ -35,8 +35,6 @@ int DatabaseWorker::svc() if (!m_queue) return -1; - MySQL::Thread_Init(); - SQLOperation *request = NULL; while (1) { @@ -50,8 +48,7 @@ int DatabaseWorker::svc() delete request; } - MySQL::Thread_End(); - delete m_conn; + m_conn->Close(); return 0; } diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/shared/Database/DatabaseWorker.h index cb224620020..5bb3a64eba3 100644 --- a/src/server/shared/Database/DatabaseWorker.h +++ b/src/server/shared/Database/DatabaseWorker.h @@ -24,7 +24,7 @@ class MySQLConnection; -class DatabaseWorker : protected ACE_Task_Base +class DatabaseWorker : public ACE_Task_Base { public: DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con); diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 9a7134eb2ce..164fce8cb5f 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -33,23 +33,20 @@ #include "QueryHolder.h" #include "AdhocStatement.h" -enum MySQLThreadBundle -{ - MYSQL_BUNDLE_NONE = 0x00, //- Each task will run their own MySQL connection - MYSQL_BUNDLE_UNUSED = 0x01, //- Temp unused - MYSQL_BUNDLE_RA = 0x02, //- Remote admin thread - MYSQL_BUNDLE_RAR = 0x04, //- Reactor runnable thread - MYSQL_BUNDLE_WORLD = 0x08, //- WorldRunnable - MYSQL_BUNDLE_ALL = MYSQL_BUNDLE_RA | MYSQL_BUNDLE_RAR | MYSQL_BUNDLE_WORLD, -}; - class PingOperation : public SQLOperation { /// Operation for idle delaythreads bool Execute() { - m_conn->Ping(); - return true; + for (;;) + if (m_conn->LockIfReady()) + { + m_conn->Ping(); + m_conn->Unlock(); + return true; + } + + return false; } }; @@ -57,7 +54,6 @@ template <class T> class DatabaseWorkerPool { private: - typedef UNORDERED_MAP<ACE_Based::Thread*, MySQLConnection*> ConnectionMap; typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, uint32> AtomicUInt; public: @@ -66,6 +62,7 @@ class DatabaseWorkerPool m_connections(0) { m_infoString = ""; + m_connections.resize(IDX_SIZE); mysql_library_init(-1, NULL, NULL); WPFatal (mysql_thread_safe(), "Used MySQL library isn't thread-safe."); @@ -73,97 +70,69 @@ class DatabaseWorkerPool ~DatabaseWorkerPool() { + sLog.outSQLDriver("~DatabaseWorkerPool for '%s'.", "missingname"); mysql_library_end(); } - bool Open(const std::string& infoString, uint8 num_threads, MySQLThreadBundle mask) + bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads) { - //- Only created bundled connection if configured - m_bundle_conn = NULL; - if (mask != MYSQL_BUNDLE_NONE) + sLog.outSQLDriver("Opening databasepool '%s'. Async threads: %u, synch threads: %u", "nonameyet", async_threads, synch_threads); + + /// Open asynchronous connections (delayed operations) + m_connections[IDX_ASYNC].resize(async_threads); + for (uint8 i = 0; i < async_threads; ++i) { - sLog.outSQLDriver("Creating bundled/master MySQL connection."); - m_bundle_conn = new T(); - m_bundle_conn->Open(infoString); - ++m_connections; + T* t = new T(m_queue); + t->Open(infoString); + m_connections[IDX_ASYNC][i] = t; + ++m_connectionCount; } - m_async_connections.resize(num_threads); - - /// Open the Async pool - for (uint8 i = 0; i < num_threads; i++) + /// Open synchronous connections (direct, blocking operations) + m_connections[IDX_SYNCH].resize(synch_threads); + for (uint8 i = 0; i < synch_threads; ++i) { - m_async_connections[i] = new T(m_queue); - m_async_connections[i]->Open(infoString); - ++m_connections; - sLog.outSQLDriver("Async database thread pool opened. Worker thread count: %u", num_threads); + T* t = new T(); + t->Open(infoString); + m_connections[IDX_SYNCH][i] = t; + ++m_connectionCount; } + /// TODO: Connection details in a struct m_infoString = infoString; + + sLog.outSQLDriver("Databasepool opened succesfuly. %u connections running.", (uint32)m_connectionCount.value()); return true; } void Close() { - sLog.outSQLDriver("Closing down %u connections on this DatabaseWorkerPool", (uint32)m_connections.value()); - /// Shuts down worker threads for this connection pool. - m_queue->queue()->deactivate(); - - for (uint8 i = 0; i < m_async_connections.size(); i++) - { - m_async_connections[i]->m_worker->wait(); - --m_connections; - } - - if (m_bundleMask != MYSQL_BUNDLE_NONE) - { - delete m_bundle_conn; - m_bundle_conn = NULL; - --m_connections; - sLog.outSQLDriver("Closed bundled connection."); - } - - //- MySQL::Thread_End() should be called manually from the aborting calling threads - } - - void Init_MySQL_Connection() - { - T* conn = new T(); - conn->Open(m_infoString); + sLog.outSQLDriver("Closing down databasepool '%s'.", "missingname"); - // no idea why it doesn't accept sLog here + /// Shuts down delaythreads for this connection pool. + m_queue->queue()->deactivate(); + for (uint8 i = 0; i < m_connections[IDX_ASYNC].size(); ++i) { - ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); - ConnectionMap::const_iterator itr = m_sync_connections.find(ACE_Based::Thread::current()); - #ifdef _DEBUG - if (itr != m_sync_connections.end()) - ACE_Singleton<Log, ACE_Thread_Mutex>::instance()->outSQLDriver("Thread ["UI64FMTD"] already started a MySQL connection", (uint64)ACE_Based::Thread::currentId()); - #endif - m_sync_connections[ACE_Based::Thread::current()] = conn; + /// TODO: Better way. probably should flip a boolean and check it on low level code before doing anything on the mysql ctx + /// Now we just wait until m_queue gives the signal to the worker threads to stop + T* t = m_connections[IDX_ASYNC][i]; + t->m_worker->wait(); // t->Close(); is called from worker thread + --m_connectionCount; } - ACE_Singleton<Log, ACE_Thread_Mutex>::instance()->outSQLDriver("Core thread with ID ["UI64FMTD"] initializing MySQL connection.", - (uint64)ACE_Based::Thread::currentId()); + sLog.outSQLDriver("Asynchronous connections on databasepool '%s' terminated. Proceeding with synchronous connections.", "missingname"); - ++m_connections; - } - - void End_MySQL_Connection() - { - MySQLConnection* conn; + /// Shut down the synchronous connections + for (uint8 i = 0; i < m_connections[IDX_SYNCH].size(); ++i) { - ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); - ConnectionMap::iterator itr = m_sync_connections.find(ACE_Based::Thread::current()); - #ifdef _DEBUG - if (itr == m_sync_connections.end()) - sLog.outSQLDriver("Thread ["UI64FMTD"] already shut down their MySQL connection.", (uint64)ACE_Based::Thread::currentId()); - #endif - conn = itr->second; - m_sync_connections.erase(itr); + T* t = m_connections[IDX_SYNCH][i]; + //while (1) + // if (t->LockIfReady()) -- For some reason deadlocks us + t->Close(); + --m_connectionCount; } - delete conn; - conn = NULL; - --m_connections; + + sLog.outSQLDriver("All connections on databasepool 'missingname' closed."); } void Execute(const char* sql) @@ -191,8 +160,12 @@ class DatabaseWorkerPool void DirectExecute(const char* sql) { - if (sql) - GetConnection()->Execute(sql); + if (!sql) + return; + + T* t = GetFreeConnection(); + t->Execute(sql); + t->Unlock(); } void DirectPExecute(const char* sql, ...) @@ -209,9 +182,13 @@ class DatabaseWorkerPool return DirectExecute(szQuery); } - QueryResult Query(const char* sql) + QueryResult Query(const char* sql, MySQLConnection* conn = NULL) { - ResultSet* result = GetConnection()->Query(sql); + if (!conn) + conn = GetFreeConnection(); + + ResultSet* result = conn->Query(sql); + conn->Unlock(); if (!result || !result->GetRowCount()) return QueryResult(NULL); @@ -219,6 +196,20 @@ class DatabaseWorkerPool return QueryResult(result); } + QueryResult PQuery(const char* sql, MySQLConnection* conn, ...) + { + if (!sql) + return QueryResult(NULL); + + va_list ap; + char szQuery[MAX_QUERY_LEN]; + va_start(ap, sql); + vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); + va_end(ap); + + return Query(szQuery, conn); + } + QueryResult PQuery(const char* sql, ...) { if (!sql) @@ -303,11 +294,12 @@ class DatabaseWorkerPool delete[] buf; } - MySQLThreadBundle GetBundleMask() { return m_bundleMask; } - PreparedQueryResult Query(PreparedStatement* stmt) { - PreparedResultSet* ret = GetConnection()->Query(stmt); + T* t = GetFreeConnection(); + PreparedResultSet* ret = t->Query(stmt); + t->Unlock(); + if (!ret || !ret->GetRowCount()) return PreparedQueryResult(NULL); @@ -316,22 +308,14 @@ class DatabaseWorkerPool void KeepAlive() { - ConnectionMap::const_iterator itr; - { - /*! MapUpdate + unbundled threads */ - ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); - itr = m_sync_connections.find(ACE_Based::Thread::current()); - if (itr != m_sync_connections.end()) - itr->second->Ping(); - } - - if (m_bundle_conn) - m_bundle_conn->Ping(); + /// Ping syncrhonous connections + for (uint8 i = 0; i < m_connections[IDX_SYNCH].size(); ++i) + m_connections[IDX_SYNCH][i]->Ping(); /// Assuming all worker threads are free, every worker thread will receive 1 ping operation request /// If one or more worker threads are busy, the ping operations will not be split evenly, but this doesn't matter /// as the sole purpose is to prevent connections from idling. - for (size_t i = 0; i < m_async_connections.size(); ++i) + for (size_t i = 0; i < m_connections[IDX_ASYNC].size(); ++i) Enqueue(new PingOperation); } @@ -340,7 +324,11 @@ class DatabaseWorkerPool { if (!to || !from || !length) return 0; - return (mysql_real_escape_string(GetConnection()->GetHandle(), to, from, length)); + + T* t = GetFreeConnection(); + unsigned long ret = mysql_real_escape_string(t->GetHandle(), to, from, length); + t->Unlock(); + return ret; } void Enqueue(SQLOperation* op) @@ -348,32 +336,33 @@ class DatabaseWorkerPool m_queue->enqueue(op); } - MySQLConnection* GetConnection() + T* GetFreeConnection() { - MySQLConnection* conn; - ConnectionMap::const_iterator itr; + uint8 i = 0; + size_t num_cons = m_connections[IDX_SYNCH].size(); + for (;;) /// Block forever until a connection is free { - /*! MapUpdate + unbundled threads */ - ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); - itr = m_sync_connections.find(ACE_Based::Thread::current()); - if (itr != m_sync_connections.end()) - return itr->second; + T* t = m_connections[IDX_SYNCH][++i % num_cons ]; + if (t->LockIfReady()) /// Must be matched with t->Unlock() or you will get deadlocks + return t; } - /*! Bundled threads */ - conn = m_bundle_conn; - ASSERT (conn); - return conn; + + // This will be called when Celine Dion learns to sing + return NULL; } private: + enum + { + IDX_ASYNC, + IDX_SYNCH, + IDX_SIZE, + }; + ACE_Activation_Queue* m_queue; //! Queue shared by async worker threads. - std::vector<T*> m_async_connections; - ConnectionMap m_sync_connections; //! Holds a mysql connection+thread per mapUpdate thread and unbundled runnnables. - ACE_Thread_Mutex m_connectionMap_mtx; //! For thread safe access to the synchroneous connection map - T* m_bundle_conn; //! Bundled connection (see Database.ThreadBundleMask config) - AtomicUInt m_connections; //! Counter of MySQL connections; + std::vector< std::vector<T*> > m_connections; + AtomicUInt m_connectionCount; //! Counter of MySQL connections; std::string m_infoString; //! Infostring that is passed on to child connections. - MySQLThreadBundle m_bundleMask; //! Our configured bundle mask (see enum) }; #endif diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/shared/Database/MySQLConnection.cpp index f3fa2f352da..83d95268e1a 100644 --- a/src/server/shared/Database/MySQLConnection.cpp +++ b/src/server/shared/Database/MySQLConnection.cpp @@ -49,11 +49,20 @@ m_Mysql(NULL) MySQLConnection::~MySQLConnection() { + ASSERT (m_Mysql); /// MySQL context must be present at this point + + sLog.outSQLDriver("MySQLConnection::~MySQLConnection()"); for (size_t i = 0; i < m_stmts.size(); ++i) delete m_stmts[i]; - MySQL::Thread_End(); mysql_close(m_Mysql); + Unlock(); /// Unlock while we die, how ironic +} + +void MySQLConnection::Close() +{ + /// Only close us if we're not operating + delete this; } bool MySQLConnection::Open(const std::string& infoString) @@ -163,9 +172,6 @@ bool MySQLConnection::Execute(const char* sql) return false; { - // guarded block for thread-safe mySQL request - ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); - #ifdef SQLQUERY_LOG uint32 _s = getMSTime(); #endif @@ -193,9 +199,6 @@ bool MySQLConnection::Execute(PreparedStatement* stmt) uint32 index = stmt->m_index; { - // guarded block for thread-safe mySQL request - ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); - MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output @@ -238,9 +241,6 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, MYSQL uint32 index = stmt->m_index; { - // guarded block for thread-safe mySQL request - ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); - MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index); ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query m_mStmt->m_stmt = stmt; // Cross reference them for debug output @@ -304,8 +304,6 @@ bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD * return false; { - // guarded block for thread-safe mySQL request - ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); #ifdef SQLQUERY_LOG uint32 _s = getMSTime(); #endif diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h index 93812421c8a..f83d22218dd 100644 --- a/src/server/shared/Database/MySQLConnection.h +++ b/src/server/shared/Database/MySQLConnection.h @@ -25,10 +25,12 @@ class DatabaseWorker; class PreparedStatement; class MySQLPreparedStatement; +class PingOperation; class MySQLConnection { template <class T> friend class DatabaseWorkerPool; + friend class PingOperation; public: MySQLConnection(); //! Constructor for synchroneous connections. @@ -36,6 +38,7 @@ class MySQLConnection ~MySQLConnection(); virtual bool Open(const std::string& infoString); //! Connection details. + void Close(); public: bool Execute(const char* sql); @@ -58,6 +61,19 @@ class MySQLConnection void PrepareStatement(uint32 index, const char* sql); std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage + bool LockIfReady() + { + /// Tries to acquire lock. If lock is acquired by another thread + /// the calling parent will just try another connection + return m_Mutex.tryacquire() != -1; + } + + void Unlock() + { + /// Called by parent databasepool. Will let other threads access this connection + m_Mutex.release(); + } + private: ACE_Activation_Queue* m_queue; //! Queue shared with other asynchroneous connections. DatabaseWorker* m_worker; //! Core worker task. diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 3dca8d3935b..bf1811523bb 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -163,14 +163,6 @@ public: sLog.outString ("Starting Remote access listner on port %d on %s", raport, stringip.c_str ()); } - - if ((LoginDatabase.GetBundleMask() & MYSQL_BUNDLE_RA)) - { - LoginDatabase.Init_MySQL_Connection(); - needInit = false; - } - if (needInit) - MySQL::Thread_Init(); } // Socket Selet time is in microseconds , not miliseconds!! @@ -184,11 +176,6 @@ public: h.Select (0, socketSelecttime); checkping (); } - - if (!needInit) - LoginDatabase.End_MySQL_Connection(); - else - MySQL::Thread_End(); } else { @@ -452,8 +439,7 @@ bool Master::_StartDB() { sLog.SetLogDB(false); std::string dbstring; - uint8 num_threads; - int32 mask; + uint8 async_threads, synch_threads; dbstring = sConfig.GetStringDefault("WorldDatabaseInfo", ""); if (dbstring.empty()) @@ -462,18 +448,18 @@ bool Master::_StartDB() return false; } - num_threads = sConfig.GetIntDefault("WorldDatabase.WorkerThreads", 1); - if (num_threads < 1 || num_threads > 32) + async_threads = sConfig.GetIntDefault("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; } - mask = sConfig.GetIntDefault("WorldDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL); + synch_threads = sConfig.GetIntDefault("WorldDatabase.SynchThreads", 1); ///- Initialise the world database - if (!WorldDatabase.Open(dbstring, num_threads, MySQLThreadBundle(mask))) + if (!WorldDatabase.Open(dbstring, async_threads, synch_threads)) { sLog.outError("Cannot connect to world database %s", dbstring.c_str()); return false; @@ -486,18 +472,18 @@ bool Master::_StartDB() return false; } - num_threads = sConfig.GetIntDefault("CharacterDatabase.WorkerThreads", 1); - if (num_threads < 1 || num_threads > 32) + async_threads = sConfig.GetIntDefault("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; } - mask = sConfig.GetIntDefault("CharacterDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL); + synch_threads = sConfig.GetIntDefault("CharacterDatabase.SynchThreads", 2); ///- Initialise the Character database - if (!CharacterDatabase.Open(dbstring, num_threads, MySQLThreadBundle(mask))) + if (!CharacterDatabase.Open(dbstring, async_threads, synch_threads)) { sLog.outError("Cannot connect to Character database %s", dbstring.c_str()); return false; @@ -511,18 +497,18 @@ bool Master::_StartDB() return false; } - num_threads = sConfig.GetIntDefault("LoginDatabase.WorkerThreads", 1); - if (num_threads < 1 || num_threads > 32) + async_threads = sConfig.GetIntDefault("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; } - mask = sConfig.GetIntDefault("LoginDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL); + synch_threads = sConfig.GetIntDefault("LoginDatabase.SynchThreads", 1); ///- Initialise the login database - if (!LoginDatabase.Open(dbstring, num_threads, MySQLThreadBundle(mask))) + if (!LoginDatabase.Open(dbstring, async_threads, synch_threads)) { sLog.outError("Cannot connect to login database %s", dbstring.c_str()); return false; diff --git a/src/server/worldserver/WorldThread/WorldRunnable.cpp b/src/server/worldserver/WorldThread/WorldRunnable.cpp index 6dfe0d809a5..8bb7899d6ca 100644 --- a/src/server/worldserver/WorldThread/WorldRunnable.cpp +++ b/src/server/worldserver/WorldThread/WorldRunnable.cpp @@ -43,28 +43,6 @@ extern int m_ServiceStatus; /// Heartbeat for the World void WorldRunnable::run() { - ///- Init MySQL threads or connections - bool needInit = true; - if (!(WorldDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - { - WorldDatabase.Init_MySQL_Connection(); - needInit = false; - } - if (!(LoginDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - { - LoginDatabase.Init_MySQL_Connection(); - needInit = false; - } - - if (!(CharacterDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - { - CharacterDatabase.Init_MySQL_Connection(); - needInit = false; - } - - if (needInit) - MySQL::Thread_Init(); - uint32 realCurrTime = 0; uint32 realPrevTime = getMSTime(); @@ -116,16 +94,4 @@ void WorldRunnable::run() sMapMgr.UnloadAll(); // unload all grids (including locked in memory) - ///- Free MySQL thread resources and deallocate lingering connections - if (!(WorldDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - WorldDatabase.End_MySQL_Connection(); - - if (!(LoginDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - LoginDatabase.End_MySQL_Connection(); - - if (!(CharacterDatabase.GetBundleMask() & MYSQL_BUNDLE_WORLD)) - CharacterDatabase.End_MySQL_Connection(); - - if (needInit) - MySQL::Thread_End(); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 51be81430f6..3bbf0cc5f9e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -39,25 +39,18 @@ # WorldDatabase.WorkerThreads # CharacterDatabase.WorkerThreads # The amount of worker threads spawned to handle -# asynchroneous MySQL statements +# asynchronous (delayed) MySQL statements. # Each worker thread is mirrored with its own # connection to the MySQL server and their own # thread on the MySQL server. # Default: 1 # -# LoginDatabase.ThreadBundleMask -# WorldDatabase.ThreadBundleMask -# CharacterDatabase.ThreadBundleMask -# Defines which runnable threads are bundled into one synchroneous -# connection. Runnables not specified in the mask will have their -# seperate connection to the MySQL server. -# Value is a bitmask consisting of: -# MYSQL_BUNDLE_NONE = 0, Each task will run their own MySQL connection -# MYSQL_BUNDLE_CLI = 1, Commandline interface thread -# MYSQL_BUNDLE_RA = 2, Remote admin thread -# MYSQL_BUNDLE_RAR = 4, Reactor runnable thread -# MYSQL_BUNDLE_WORLD = 8, WorldRunnable -# MYSQL_BUNDLE_ALL = 15, All bundled together +# LoginDatabase.SynchThreads +# WorldDatabase.SynchThreads +# CharacterDatabase.SynchThreads +# The amount of MySQL connections spawned to handle +# synchronous (blocking) MySQL statements. +# Default: 1, 1, 2 # # MaxPingTime # Settings for maximum database-ping interval (minutes between pings) @@ -79,9 +72,9 @@ CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters" LoginDatabase.WorkerThreads = 1 WorldDatabase.WorkerThreads = 1 CharacterDatabase.WorkerThreads = 1 -LoginDatabase.ThreadBundleMask = 15 -WorldDatabase.ThreadBundleMask = 15 -CharacterDatabase.ThreadBundleMask = 15 +LoginDatabase.SynchThreads = 1 +WorldDatabase.SynchThreads = 1 +CharacterDatabase.SynchThreads = 2 MaxPingTime = 30 WorldServerPort = 8085 BindIP = "0.0.0.0" |