diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index a34a65e4bc7..a642e26edf8 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -514,7 +514,7 @@ void InstanceSaveManager::CleanupInstances() CharacterDatabase.Execute("DELETE FROM creature_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)"); CharacterDatabase.Execute("DELETE FROM gameobject_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)"); //execute transaction directly - CharacterDatabase.CommitTransactionDirect(); + CharacterDatabase.CommitTransaction(); bar.step(); sLog.outString(); @@ -562,7 +562,7 @@ void InstanceSaveManager::PackInstances() CharacterDatabase.PExecute("UPDATE instance SET id = '%u' WHERE id = '%u'", InstanceNumber, *i); CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i); //execute transaction synchronously - CharacterDatabase.CommitTransactionDirect(); + CharacterDatabase.CommitTransaction(); } ++InstanceNumber; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 47c3b2a4ff6..07a2187adad 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5598,7 +5598,7 @@ void ObjectMgr::PackGroupIds() CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM groups WHERE groupId = '%u'", id); CharacterDatabase.PExecute("DELETE FROM group_member WHERE groupId = '%u'", id); - CharacterDatabase.CommitTransactionDirect(); + CharacterDatabase.CommitTransaction(); continue; } @@ -5621,7 +5621,7 @@ void ObjectMgr::PackGroupIds() CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("UPDATE groups SET groupId = '%u' WHERE groupId = '%u'", groupId, *i); CharacterDatabase.PExecute("UPDATE group_member SET groupId = '%u' WHERE groupId = '%u'", groupId, *i); - CharacterDatabase.CommitTransactionDirect(); + CharacterDatabase.CommitTransaction(); } ++groupId; @@ -5670,7 +5670,7 @@ void ObjectMgr::SetHighestGuids() CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", m_ItemGuids.GetNextAfterMaxUsed()); CharacterDatabase.PExecute("DELETE FROM auction WHERE itemguid >= '%u'", m_ItemGuids.GetNextAfterMaxUsed()); CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", m_ItemGuids.GetNextAfterMaxUsed()); - CharacterDatabase.CommitTransactionDirect(); + CharacterDatabase.CommitTransaction(); result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject" ); if( result ) diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index d3255b4b4eb..f9a86c3147c 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -197,6 +197,12 @@ int Master::Run() ///- Initialize the World sWorld.SetInitialWorldSettings(); + //server loaded successfully => enable async DB requests + //this is done to forbid any async transactions during server startup! + CharacterDatabase.InitDelayThread(); + WorldDatabase.InitDelayThread(); + LoginDatabase.InitDelayThread(); + ///- Catch termination signals _HookSignals(); @@ -208,7 +214,7 @@ int Master::Run() { std::string builds = AcceptableClientBuildsListStr(); LoginDatabase.escape_string(builds); - LoginDatabase.PExecute("UPDATE realmlist SET realmflags = realmflags & ~(%u), population = 0, realmbuilds = '%s' WHERE id = '%u'", REALM_FLAG_OFFLINE, builds.c_str(), realmID); + LoginDatabase.DirectPExecute("UPDATE realmlist SET realmflags = realmflags & ~(%u), population = 0, realmbuilds = '%s' WHERE id = '%u'", REALM_FLAG_OFFLINE, builds.c_str(), realmID); } ACE_Based::Thread* cliThread = NULL; @@ -328,7 +334,7 @@ int Master::Run() } ///- Set server offline in realmlist - LoginDatabase.PExecute("UPDATE realmlist SET realmflags = realmflags | %u WHERE id = '%u'", REALM_FLAG_OFFLINE, realmID); + LoginDatabase.DirectPExecute("UPDATE realmlist SET realmflags = realmflags | %u WHERE id = '%u'", REALM_FLAG_OFFLINE, realmID); ///- Remove signal handling before leaving _UnhookSignals(); diff --git a/src/realmd/Main.cpp b/src/realmd/Main.cpp index 6e501542bb2..1936e48d7a6 100644 --- a/src/realmd/Main.cpp +++ b/src/realmd/Main.cpp @@ -221,8 +221,10 @@ extern int main(int argc, char **argv) // cleanup query // set expired bans to inactive + LoginDatabase.BeginTransaction(); LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + LoginDatabase.CommitTransaction(); ///- Launch the listening network socket ACE_Acceptor acceptor; @@ -285,6 +287,9 @@ extern int main(int argc, char **argv) } #endif + //server has started up successfully => enable async DB requests + LoginDatabase.InitDelayThread(); + // maximum counter for next ping uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000)); uint32 loopCounter = 0; diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index d114c2c953d..e7046a8dc84 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -29,13 +29,7 @@ Database::~Database() { - HaltDelayThread(); - /*Delete objects*/ - delete m_pResultQueue; - delete m_pAsyncConn; - - for (int i = 0; i < m_pQueryConnections.size(); ++i) - delete m_pQueryConnections[i]; + StopServer(); } bool Database::Initialize(const char * infoString, int nConns /*= 1*/) @@ -80,10 +74,33 @@ bool Database::Initialize(const char * infoString, int nConns /*= 1*/) if(!m_pAsyncConn->Initialize(infoString)) return false; - InitDelayThread(); + m_pResultQueue = new SqlResultQueue; return true; } +void Database::StopServer() +{ + HaltDelayThread(); + /*Delete objects*/ + if(m_pResultQueue) + { + delete m_pResultQueue; + m_pResultQueue = NULL; + } + + if(m_pAsyncConn) + { + delete m_pAsyncConn; + m_pAsyncConn = NULL; + } + + for (size_t i = 0; i < m_pQueryConnections.size(); ++i) + delete m_pQueryConnections[i]; + + m_pQueryConnections.clear(); + +} + SqlDelayThread * Database::CreateDelayThread() { assert(m_pAsyncConn); @@ -94,7 +111,6 @@ void Database::InitDelayThread() { assert(!m_delayThread); - m_pResultQueue = new SqlResultQueue; //New delay thread for delay execute m_threadBody = CreateDelayThread(); // will deleted at m_delayThread delete m_delayThread = new ACE_Based::Thread(m_threadBody); @@ -109,14 +125,6 @@ void Database::HaltDelayThread() delete m_delayThread; //This also deletes m_threadBody m_delayThread = NULL; m_threadBody = NULL; - - //stop async result queue - if(m_pResultQueue) - { - m_pResultQueue->Update(); - delete m_pResultQueue; - m_pResultQueue = NULL; - } } void Database::ThreadStart() @@ -268,6 +276,10 @@ bool Database::Execute(const char *sql) } else { + //if async execution is not available + if(!m_threadBody) + return DirectExecute(sql); + // Simple sql statement pTrans = new SqlTransaction; pTrans->DelayExecute(sql); @@ -350,6 +362,10 @@ bool Database::CommitTransaction() if(!m_TransStorage->get()) return false; + //if async execution is not available + if(!m_delayThread) + return CommitTransactionDirect(); + //add SqlTransaction to the async queue m_threadBody->Delay(m_TransStorage->detach()); return true; diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 7df6bc691a8..b1d3a715aed 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -81,7 +81,11 @@ class MANGOS_DLL_SPEC Database virtual ~Database(); virtual bool Initialize(const char *infoString, int nConns = 1); + //start worker thread for async DB request execution + //you should call it explicitly after your server successfully started up + //NO ASYNC TRANSACTIONS DURING SERVER STARTUP - ONLY DURING RUNTIME!!! virtual void InitDelayThread(); + //stop worker thread virtual void HaltDelayThread(); /// Synchronous DB queries @@ -181,6 +185,8 @@ class MANGOS_DLL_SPEC Database m_nQueryCounter = -1; } + void StopServer(); + //factory method to create SqlConnection objects virtual SqlConnection * CreateConnection() = 0; //factory method to create SqlDelayThread objects diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp index cf3f66f9888..34e6b9af296 100644 --- a/src/shared/Database/DatabaseMysql.cpp +++ b/src/shared/Database/DatabaseMysql.cpp @@ -56,23 +56,7 @@ DatabaseMysql::DatabaseMysql() DatabaseMysql::~DatabaseMysql() { - if (m_delayThread) - HaltDelayThread(); - - //destroy SqlConnection objects - if(m_pQueryConnections.size()) - { - for (int i = 0; i < m_pQueryConnections.size(); ++i) - delete m_pQueryConnections[i]; - - m_pQueryConnections.clear(); - } - - if(m_pAsyncConn) - { - delete m_pAsyncConn; - m_pAsyncConn = NULL; - } + StopServer(); //Free Mysql library pointers for last ~DB if(--db_count == 0) diff --git a/src/shared/Database/DatabasePostgre.cpp b/src/shared/Database/DatabasePostgre.cpp index cb3df06d720..55cdb818beb 100644 --- a/src/shared/Database/DatabasePostgre.cpp +++ b/src/shared/Database/DatabasePostgre.cpp @@ -43,23 +43,7 @@ DatabasePostgre::DatabasePostgre() DatabasePostgre::~DatabasePostgre() { - if (m_delayThread) - HaltDelayThread(); - //destroy SqlConnection objects - if(m_pQueryConnections.size()) - { - for (int i = 0; i < m_pQueryConnections.size(); ++i) - delete m_pQueryConnections[i]; - - m_pQueryConnections.clear(); - } - - if(m_pAsyncConn) - { - delete m_pAsyncConn; - m_pAsyncConn = NULL; - } } SqlConnection * DatabasePostgre::CreateConnection() diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 89fafab6405..c5d9f064bdf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11053" + #define REVISION_NR "11054" #endif // __REVISION_NR_H__