mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 10:37:02 +00:00
[11054] Do not allow async transaction execution while server is loading. Call Database::InitDelayThread() function explicitly to create async DB worker thread after server initialization is complete.
Signed-off-by: Ambal <pogrebniak@gala.net>
This commit is contained in:
parent
e6e7bf8573
commit
07c9f0cbb8
9 changed files with 59 additions and 58 deletions
|
|
@ -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 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)");
|
CharacterDatabase.Execute("DELETE FROM gameobject_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)");
|
||||||
//execute transaction directly
|
//execute transaction directly
|
||||||
CharacterDatabase.CommitTransactionDirect();
|
CharacterDatabase.CommitTransaction();
|
||||||
|
|
||||||
bar.step();
|
bar.step();
|
||||||
sLog.outString();
|
sLog.outString();
|
||||||
|
|
@ -562,7 +562,7 @@ void InstanceSaveManager::PackInstances()
|
||||||
CharacterDatabase.PExecute("UPDATE instance SET id = '%u' WHERE id = '%u'", InstanceNumber, *i);
|
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);
|
CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
||||||
//execute transaction synchronously
|
//execute transaction synchronously
|
||||||
CharacterDatabase.CommitTransactionDirect();
|
CharacterDatabase.CommitTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
++InstanceNumber;
|
++InstanceNumber;
|
||||||
|
|
|
||||||
|
|
@ -5598,7 +5598,7 @@ void ObjectMgr::PackGroupIds()
|
||||||
CharacterDatabase.BeginTransaction();
|
CharacterDatabase.BeginTransaction();
|
||||||
CharacterDatabase.PExecute("DELETE FROM groups WHERE groupId = '%u'", id);
|
CharacterDatabase.PExecute("DELETE FROM groups WHERE groupId = '%u'", id);
|
||||||
CharacterDatabase.PExecute("DELETE FROM group_member WHERE groupId = '%u'", id);
|
CharacterDatabase.PExecute("DELETE FROM group_member WHERE groupId = '%u'", id);
|
||||||
CharacterDatabase.CommitTransactionDirect();
|
CharacterDatabase.CommitTransaction();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5621,7 +5621,7 @@ void ObjectMgr::PackGroupIds()
|
||||||
CharacterDatabase.BeginTransaction();
|
CharacterDatabase.BeginTransaction();
|
||||||
CharacterDatabase.PExecute("UPDATE groups SET groupId = '%u' WHERE groupId = '%u'", groupId, *i);
|
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.PExecute("UPDATE group_member SET groupId = '%u' WHERE groupId = '%u'", groupId, *i);
|
||||||
CharacterDatabase.CommitTransactionDirect();
|
CharacterDatabase.CommitTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
++groupId;
|
++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 mail_items WHERE item_guid >= '%u'", m_ItemGuids.GetNextAfterMaxUsed());
|
||||||
CharacterDatabase.PExecute("DELETE FROM auction WHERE itemguid >= '%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.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" );
|
result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject" );
|
||||||
if( result )
|
if( result )
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,12 @@ int Master::Run()
|
||||||
///- Initialize the World
|
///- Initialize the World
|
||||||
sWorld.SetInitialWorldSettings();
|
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
|
///- Catch termination signals
|
||||||
_HookSignals();
|
_HookSignals();
|
||||||
|
|
||||||
|
|
@ -208,7 +214,7 @@ int Master::Run()
|
||||||
{
|
{
|
||||||
std::string builds = AcceptableClientBuildsListStr();
|
std::string builds = AcceptableClientBuildsListStr();
|
||||||
LoginDatabase.escape_string(builds);
|
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;
|
ACE_Based::Thread* cliThread = NULL;
|
||||||
|
|
@ -328,7 +334,7 @@ int Master::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
///- Set server offline in realmlist
|
///- 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
|
///- Remove signal handling before leaving
|
||||||
_UnhookSignals();
|
_UnhookSignals();
|
||||||
|
|
|
||||||
|
|
@ -221,8 +221,10 @@ extern int main(int argc, char **argv)
|
||||||
|
|
||||||
// cleanup query
|
// cleanup query
|
||||||
// set expired bans to inactive
|
// set expired bans to inactive
|
||||||
|
LoginDatabase.BeginTransaction();
|
||||||
LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
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.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||||
|
LoginDatabase.CommitTransaction();
|
||||||
|
|
||||||
///- Launch the listening network socket
|
///- Launch the listening network socket
|
||||||
ACE_Acceptor<AuthSocket, ACE_SOCK_Acceptor> acceptor;
|
ACE_Acceptor<AuthSocket, ACE_SOCK_Acceptor> acceptor;
|
||||||
|
|
@ -285,6 +287,9 @@ extern int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//server has started up successfully => enable async DB requests
|
||||||
|
LoginDatabase.InitDelayThread();
|
||||||
|
|
||||||
// maximum counter for next ping
|
// maximum counter for next ping
|
||||||
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
|
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
|
||||||
uint32 loopCounter = 0;
|
uint32 loopCounter = 0;
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,7 @@
|
||||||
|
|
||||||
Database::~Database()
|
Database::~Database()
|
||||||
{
|
{
|
||||||
HaltDelayThread();
|
StopServer();
|
||||||
/*Delete objects*/
|
|
||||||
delete m_pResultQueue;
|
|
||||||
delete m_pAsyncConn;
|
|
||||||
|
|
||||||
for (int i = 0; i < m_pQueryConnections.size(); ++i)
|
|
||||||
delete m_pQueryConnections[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::Initialize(const char * infoString, int nConns /*= 1*/)
|
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))
|
if(!m_pAsyncConn->Initialize(infoString))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
InitDelayThread();
|
m_pResultQueue = new SqlResultQueue;
|
||||||
return true;
|
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()
|
SqlDelayThread * Database::CreateDelayThread()
|
||||||
{
|
{
|
||||||
assert(m_pAsyncConn);
|
assert(m_pAsyncConn);
|
||||||
|
|
@ -94,7 +111,6 @@ void Database::InitDelayThread()
|
||||||
{
|
{
|
||||||
assert(!m_delayThread);
|
assert(!m_delayThread);
|
||||||
|
|
||||||
m_pResultQueue = new SqlResultQueue;
|
|
||||||
//New delay thread for delay execute
|
//New delay thread for delay execute
|
||||||
m_threadBody = CreateDelayThread(); // will deleted at m_delayThread delete
|
m_threadBody = CreateDelayThread(); // will deleted at m_delayThread delete
|
||||||
m_delayThread = new ACE_Based::Thread(m_threadBody);
|
m_delayThread = new ACE_Based::Thread(m_threadBody);
|
||||||
|
|
@ -109,14 +125,6 @@ void Database::HaltDelayThread()
|
||||||
delete m_delayThread; //This also deletes m_threadBody
|
delete m_delayThread; //This also deletes m_threadBody
|
||||||
m_delayThread = NULL;
|
m_delayThread = NULL;
|
||||||
m_threadBody = NULL;
|
m_threadBody = NULL;
|
||||||
|
|
||||||
//stop async result queue
|
|
||||||
if(m_pResultQueue)
|
|
||||||
{
|
|
||||||
m_pResultQueue->Update();
|
|
||||||
delete m_pResultQueue;
|
|
||||||
m_pResultQueue = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::ThreadStart()
|
void Database::ThreadStart()
|
||||||
|
|
@ -268,6 +276,10 @@ bool Database::Execute(const char *sql)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//if async execution is not available
|
||||||
|
if(!m_threadBody)
|
||||||
|
return DirectExecute(sql);
|
||||||
|
|
||||||
// Simple sql statement
|
// Simple sql statement
|
||||||
pTrans = new SqlTransaction;
|
pTrans = new SqlTransaction;
|
||||||
pTrans->DelayExecute(sql);
|
pTrans->DelayExecute(sql);
|
||||||
|
|
@ -350,6 +362,10 @@ bool Database::CommitTransaction()
|
||||||
if(!m_TransStorage->get())
|
if(!m_TransStorage->get())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
//if async execution is not available
|
||||||
|
if(!m_delayThread)
|
||||||
|
return CommitTransactionDirect();
|
||||||
|
|
||||||
//add SqlTransaction to the async queue
|
//add SqlTransaction to the async queue
|
||||||
m_threadBody->Delay(m_TransStorage->detach());
|
m_threadBody->Delay(m_TransStorage->detach());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,11 @@ class MANGOS_DLL_SPEC Database
|
||||||
virtual ~Database();
|
virtual ~Database();
|
||||||
|
|
||||||
virtual bool Initialize(const char *infoString, int nConns = 1);
|
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();
|
virtual void InitDelayThread();
|
||||||
|
//stop worker thread
|
||||||
virtual void HaltDelayThread();
|
virtual void HaltDelayThread();
|
||||||
|
|
||||||
/// Synchronous DB queries
|
/// Synchronous DB queries
|
||||||
|
|
@ -181,6 +185,8 @@ class MANGOS_DLL_SPEC Database
|
||||||
m_nQueryCounter = -1;
|
m_nQueryCounter = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StopServer();
|
||||||
|
|
||||||
//factory method to create SqlConnection objects
|
//factory method to create SqlConnection objects
|
||||||
virtual SqlConnection * CreateConnection() = 0;
|
virtual SqlConnection * CreateConnection() = 0;
|
||||||
//factory method to create SqlDelayThread objects
|
//factory method to create SqlDelayThread objects
|
||||||
|
|
|
||||||
|
|
@ -56,23 +56,7 @@ DatabaseMysql::DatabaseMysql()
|
||||||
|
|
||||||
DatabaseMysql::~DatabaseMysql()
|
DatabaseMysql::~DatabaseMysql()
|
||||||
{
|
{
|
||||||
if (m_delayThread)
|
StopServer();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Free Mysql library pointers for last ~DB
|
//Free Mysql library pointers for last ~DB
|
||||||
if(--db_count == 0)
|
if(--db_count == 0)
|
||||||
|
|
|
||||||
|
|
@ -43,23 +43,7 @@ DatabasePostgre::DatabasePostgre()
|
||||||
|
|
||||||
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()
|
SqlConnection * DatabasePostgre::CreateConnection()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "11053"
|
#define REVISION_NR "11054"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue