* HIGHLY EXPERIMENTAL - USE AT OWN RISK *
Database Layer: - Implement connection pooling: Instead of 1 delay thread per database, you can configure between 1 and 32 worker threads that have a seperate thread in the core and have a seperate connection to the MySQL server (based on raczman/Albator´s database layer for Trinitycore3) - Implement a configurable thread bundle for synchroneous requests from seperate core threads (see worldserver.conf.dist for more info) - Every mapupdate thread now has its seperate MySQL connection to the world and characters database - Drop inconsistent PExecuteLog function - query logging will be implemented CONSISTENTLY later - Drop current prepared statement interface - this will be done *properly* later - You´ll need to update your worldserver.conf and authserver.conf - You´re recommended to make a backup of your databases before using this. * HIGHLY EXPERIMENTAL - USE AT OWN RISK * * HIGHLY EXPERIMENTAL - USE AT OWN RISK * etc. --HG-- branch : trunk
This commit is contained in:
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Database/PreparedStatements.h"
|
||||
|
||||
#include "Configuration/Config.h"
|
||||
#include "Log.h"
|
||||
@@ -315,7 +314,7 @@ extern int main(int argc, char **argv)
|
||||
{
|
||||
loopCounter = 0;
|
||||
sLog.outDetail("Ping MySQL to keep connection alive");
|
||||
sPreparedStatement.Query(&LoginDatabase, "auth_ping");
|
||||
LoginDatabase.Query("SELECT 1 FROM realmlist");
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (m_ServiceStatus == 0) stopEvent = true;
|
||||
@@ -323,9 +322,8 @@ extern int main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
///- Wait for the delay thread to exit
|
||||
LoginDatabase.ThreadEnd();
|
||||
LoginDatabase.HaltDelayThread();
|
||||
///- Close the Database Pool
|
||||
LoginDatabase.Close();
|
||||
|
||||
sLog.outString("Halting process...");
|
||||
return 0;
|
||||
@@ -341,16 +339,18 @@ bool StartDB()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
uint8 num_threads = sConfig.GetIntDefault("LoginDatabase.WorkerThreads", 1);
|
||||
if (num_threads < 1 || num_threads > 32)
|
||||
{
|
||||
sLog.outError("Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1.");
|
||||
num_threads = 1;
|
||||
}
|
||||
|
||||
if (!LoginDatabase.Open(dbstring.c_str(), num_threads))
|
||||
{
|
||||
sLog.outError("Cannot connect to database");
|
||||
return false;
|
||||
}
|
||||
LoginDatabase.ThreadStart();
|
||||
|
||||
uint32 count = 0;
|
||||
sPreparedStatement.LoadAuthserver(&LoginDatabase, count);
|
||||
sLog.outString("Loaded %u prepared MySQL statements for auth DB.", count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,6 @@
|
||||
###############################################################################
|
||||
# AUTH SERVER SETTINGS
|
||||
#
|
||||
# LoginDatabaseInfo
|
||||
# Database connection settings for the realm server.
|
||||
# Default:
|
||||
# hostname;port;username;password;database
|
||||
# .;somenumber;username;password;database
|
||||
# - use named pipes in Windows
|
||||
# Named pipes: mySQL required adding
|
||||
# "enable-named-pipe" to [mysqld] section my.ini
|
||||
# .;/path/to/unix_socket;username;password;database
|
||||
# - use Unix sockets in Unix/Linux
|
||||
#
|
||||
# LogsDir
|
||||
# Logs directory setting.
|
||||
# Important: Logs dir must exists, or all logs need to be disabled
|
||||
@@ -146,3 +135,30 @@ RealmsStateUpdateDelay = 20
|
||||
WrongPass.MaxCount = 0
|
||||
WrongPass.BanTime = 600
|
||||
WrongPass.BanType = 0
|
||||
|
||||
###############################################################################
|
||||
# MYSQL SETTINGS
|
||||
#
|
||||
# LoginDatabaseInfo
|
||||
# Database connection settings for the realm server.
|
||||
# Default:
|
||||
# hostname;port;username;password;database
|
||||
# .;somenumber;username;password;database
|
||||
# - use named pipes in Windows
|
||||
# Named pipes: mySQL required adding
|
||||
# "enable-named-pipe" to [mysqld] section my.ini
|
||||
# .;/path/to/unix_socket;username;password;database
|
||||
# - use Unix sockets in Unix/Linux
|
||||
#
|
||||
# LoginDatabase.WorkerThreads
|
||||
# The amount of worker threads spawned to handle
|
||||
# asynchroneous 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
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
|
||||
LoginDatabase.WorkerThreads = 1
|
||||
|
||||
@@ -48,8 +48,7 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
|
||||
return AOR_NAME_ALREDY_EXIST; // username does already exist
|
||||
}
|
||||
|
||||
if (!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str()))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str());
|
||||
LoginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
|
||||
|
||||
return AOR_OK; // everything's fine
|
||||
@@ -89,16 +88,12 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
|
||||
LoginDatabase.BeginTransaction();
|
||||
|
||||
bool res =
|
||||
LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
|
||||
LoginDatabase.PExecute("DELETE FROM account_access WHERE id ='%d'", accid) &&
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid);
|
||||
LoginDatabase.PExecute("DELETE FROM account_access WHERE id ='%d'", accid);
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
|
||||
LoginDatabase.CommitTransaction();
|
||||
|
||||
if (!res)
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error;
|
||||
|
||||
return AOR_OK;
|
||||
}
|
||||
|
||||
@@ -120,9 +115,8 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
|
||||
std::string safe_new_uname = new_uname;
|
||||
LoginDatabase.escape_string(safe_new_uname);
|
||||
|
||||
if (!LoginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(),
|
||||
CalculateShaPassHash(new_uname, new_passwd).c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
LoginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(),
|
||||
CalculateShaPassHash(new_uname, new_passwd).c_str(), accid);
|
||||
|
||||
return AOR_OK;
|
||||
}
|
||||
@@ -141,9 +135,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
normalizeString(new_passwd);
|
||||
|
||||
// also reset s and v to force update at next realmd login
|
||||
if (!LoginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'",
|
||||
CalculateShaPassHash(username, new_passwd).c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
LoginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'",
|
||||
CalculateShaPassHash(username, new_passwd).c_str(), accid);
|
||||
|
||||
return AOR_OK;
|
||||
}
|
||||
|
||||
@@ -84,12 +84,10 @@ Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team)
|
||||
else // save
|
||||
{
|
||||
// _name is already escaped at this point.
|
||||
if (CharacterDatabase.PExecute("INSERT INTO channels (m_name, m_team, m_announce, m_moderate, m_public, m_password) "
|
||||
"VALUES ('%s', '%u', '1', '0', '1', '')", _name.c_str(), m_Team))
|
||||
{
|
||||
sLog.outDebug("New Channel(%s) saved", name.c_str());
|
||||
m_IsSaved = true;
|
||||
}
|
||||
CharacterDatabase.PExecute("INSERT INTO channels (m_name, m_team, m_announce, m_moderate, m_public, m_password) "
|
||||
"VALUES ('%s', '%u', '1', '0', '1', '')", _name.c_str(), m_Team);
|
||||
sLog.outDebug("New Channel(%s) saved", name.c_str());
|
||||
m_IsSaved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,8 +99,9 @@ bool Channel::_UpdateStringInDB(const std::string& colName, const std::string& c
|
||||
std::string _colValue(colValue);
|
||||
CharacterDatabase.escape_string(_colValue);
|
||||
CharacterDatabase.escape_string(_name);
|
||||
return CharacterDatabase.PExecute("UPDATE channels SET %s = '%s' WHERE m_name = '%s' AND m_team = '%u'",
|
||||
CharacterDatabase.PExecute("UPDATE channels SET %s = '%s' WHERE m_name = '%s' AND m_team = '%u'",
|
||||
colName.c_str(), _colValue.c_str(), _name.c_str(), m_Team);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Channel::_UpdateIntInDB(const std::string& colName, int colValue) const
|
||||
@@ -110,8 +109,9 @@ bool Channel::_UpdateIntInDB(const std::string& colName, int colValue) const
|
||||
// Prevent SQL-injection
|
||||
std::string _name(m_name);
|
||||
CharacterDatabase.escape_string(_name);
|
||||
return CharacterDatabase.PExecute("UPDATE channels SET %s = '%u' WHERE m_name = '%s' AND m_team = '%u'",
|
||||
CharacterDatabase.PExecute("UPDATE channels SET %s = '%u' WHERE m_name = '%s' AND m_team = '%u'",
|
||||
colName.c_str(), colValue, _name.c_str(), m_Team);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Channel::_UpdateBanListInDB() const
|
||||
|
||||
@@ -1174,7 +1174,7 @@ bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
|
||||
//WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
|
||||
|
||||
// update movement type
|
||||
WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
|
||||
WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
|
||||
if (pCreature && pCreature->GetWaypointPath())
|
||||
{
|
||||
pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
|
||||
@@ -1253,7 +1253,7 @@ bool ChatHandler::HandleNpcFlagCommand(const char* args)
|
||||
|
||||
pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
|
||||
WorldDatabase.PExecute("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
|
||||
|
||||
SendSysMessage(LANG_VALUE_SAVED_REJOIN);
|
||||
|
||||
@@ -1372,7 +1372,7 @@ bool ChatHandler::HandleNpcMoveCommand(const char* args)
|
||||
}
|
||||
}
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
|
||||
WorldDatabase.PExecute("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
|
||||
PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
|
||||
return true;
|
||||
}
|
||||
@@ -1583,7 +1583,7 @@ bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
|
||||
}
|
||||
|
||||
// and DB
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
|
||||
WorldDatabase.PExecute("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1621,7 +1621,7 @@ bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
|
||||
pCreature->Respawn();
|
||||
}
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
|
||||
WorldDatabase.PExecute("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
|
||||
PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
|
||||
return true;
|
||||
}
|
||||
@@ -1653,7 +1653,7 @@ bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
|
||||
else
|
||||
return false;
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
|
||||
WorldDatabase.PExecute("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
|
||||
pCreature->SetRespawnDelay((uint32)i_stime);
|
||||
PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
|
||||
|
||||
@@ -2384,7 +2384,7 @@ bool ChatHandler::HandleWpAddCommand(const char* args)
|
||||
Player* player = m_session->GetPlayer();
|
||||
//Map *map = player->GetMap();
|
||||
|
||||
WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES ('%u','%u','%f', '%f', '%f')",
|
||||
WorldDatabase.PExecute("INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES ('%u','%u','%f', '%f', '%f')",
|
||||
pathid, point+1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
|
||||
|
||||
PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point+1,"|r|cff00ff00 created. ");
|
||||
@@ -2588,7 +2588,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
|
||||
if (result)
|
||||
{
|
||||
WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id);
|
||||
WorldDatabase.PExecute("DELETE FROM waypoint_scripts WHERE guid = %u", id);
|
||||
PSendSysMessage("%s%s%u|r","|cff00ff00","Wp Event: Waypoint script removed: ", id);
|
||||
}
|
||||
else
|
||||
@@ -2647,7 +2647,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
{
|
||||
uint32 newid = atoi(arg_3);
|
||||
PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r","|cff00ff00","Wp Event: Wypoint scipt guid: ", newid," id changed: ", id);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'",
|
||||
newid, id); return true;
|
||||
}
|
||||
else
|
||||
@@ -2663,7 +2663,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
if (arg_str_2 == "posx")
|
||||
{
|
||||
coord = atof(arg_3);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'",
|
||||
coord, id);
|
||||
PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id);
|
||||
return true;
|
||||
@@ -2671,7 +2671,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
else if (arg_str_2 == "posy")
|
||||
{
|
||||
coord = atof(arg_3);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'",
|
||||
coord, id);
|
||||
PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id);
|
||||
return true;
|
||||
@@ -2679,7 +2679,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
else if (arg_str_2 == "posz")
|
||||
{
|
||||
coord = atof(arg_3);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'",
|
||||
coord, id);
|
||||
PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id);
|
||||
return true;
|
||||
@@ -2687,14 +2687,14 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
else if (arg_str_2 == "orientation")
|
||||
{
|
||||
coord = atof(arg_3);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'",
|
||||
coord, id);
|
||||
PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id);
|
||||
return true;
|
||||
}
|
||||
else if (arg_str_2 == "dataint")
|
||||
{
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'",
|
||||
arg_2, atoi(arg_3), id);
|
||||
PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id);
|
||||
return true;
|
||||
@@ -2703,7 +2703,7 @@ bool ChatHandler::HandleWpEventCommand(const char* args)
|
||||
{
|
||||
std::string arg_str_3 = arg_3;
|
||||
WorldDatabase.escape_string(arg_str_3);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'",
|
||||
arg_2, arg_str_3.c_str(), id);
|
||||
}
|
||||
}
|
||||
@@ -2832,9 +2832,9 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
|
||||
wpCreature->AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'",
|
||||
WorldDatabase.PExecute("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'",
|
||||
pathid, point);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'",
|
||||
pathid, point);
|
||||
|
||||
PSendSysMessage(LANG_WAYPOINT_REMOVED);
|
||||
@@ -2875,7 +2875,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
|
||||
//sMapMgr.GetMap(npcCreature->GetMapId())->Add(wpCreature2);
|
||||
}
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'",
|
||||
chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point);
|
||||
|
||||
PSendSysMessage(LANG_WAYPOINT_CHANGED);
|
||||
@@ -2888,7 +2888,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
|
||||
if (text == 0)
|
||||
{
|
||||
// show_str check for present in list of correct values, no sql injection possible
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'",
|
||||
show_str, pathid, point);
|
||||
}
|
||||
else
|
||||
@@ -2896,7 +2896,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
|
||||
// show_str check for present in list of correct values, no sql injection possible
|
||||
std::string text2 = text;
|
||||
WorldDatabase.escape_string(text2);
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'",
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'",
|
||||
show_str, text2.c_str(), pathid, point);
|
||||
}
|
||||
|
||||
@@ -3031,7 +3031,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
|
||||
{
|
||||
PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
|
||||
hasError = true;
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
|
||||
WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", wpguid);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3075,7 +3075,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
|
||||
|
||||
sLog.outDebug("DEBUG: UPDATE waypoint_data SET wpguid = '%u");
|
||||
// set "wpguid" column to the visual waypoint
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
|
||||
|
||||
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
|
||||
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
|
||||
@@ -3205,7 +3205,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
|
||||
{
|
||||
PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
|
||||
hasError = true;
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
|
||||
WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", guid);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3216,8 +3216,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
|
||||
}
|
||||
while (result->NextRow());
|
||||
// set "wpguid" column to "empty" - no visual waypoint spawned
|
||||
WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'");
|
||||
//WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
|
||||
WorldDatabase.PExecute("UPDATE waypoint_data SET wpguid = '0'");
|
||||
//WorldDatabase.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
|
||||
|
||||
if (hasError)
|
||||
{
|
||||
@@ -4210,7 +4210,7 @@ bool ChatHandler::HandleNpcAddFormationCommand(const char* args)
|
||||
CreatureGroupMap[lowguid] = group_member;
|
||||
pCreature->SearchFormation();
|
||||
|
||||
WorldDatabase.PExecuteLog("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')",
|
||||
WorldDatabase.PExecute("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')",
|
||||
leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI);
|
||||
|
||||
PSendSysMessage("Creature %u added to formation with leader %u", lowguid, leaderGUID);
|
||||
|
||||
@@ -1054,7 +1054,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
// updated in DB
|
||||
WorldDatabase.BeginTransaction();
|
||||
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "INSERT INTO creature VALUES ("
|
||||
@@ -1077,7 +1077,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
<< (m_isDeadByDefault ? 1 : 0) << "," //is_dead
|
||||
<< GetDefaultMovementType() << ")"; //default movement generator type
|
||||
|
||||
WorldDatabase.PExecuteLog(ss.str().c_str());
|
||||
WorldDatabase.PExecute(ss.str().c_str());
|
||||
|
||||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
@@ -1349,10 +1349,10 @@ void Creature::DeleteFromDB()
|
||||
sObjectMgr.DeleteCreatureData(m_DBTableGuid);
|
||||
|
||||
WorldDatabase.BeginTransaction();
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
|
||||
@@ -645,8 +645,8 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
<< uint32(GetGoState()) << ")";
|
||||
|
||||
WorldDatabase.BeginTransaction();
|
||||
WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog(ss.str().c_str());
|
||||
WorldDatabase.PExecute("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute(ss.str().c_str());
|
||||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
@@ -722,8 +722,8 @@ void GameObject::DeleteFromDB()
|
||||
{
|
||||
sObjectMgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0);
|
||||
sObjectMgr.DeleteGOData(m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
WorldDatabase.PExecute("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid);
|
||||
}
|
||||
|
||||
GameObject* GameObject::GetGameObject(WorldObject& object, uint64 guid)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
#include "OutdoorPvPMgr.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "Chat.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "AsyncDatabaseImpl.h"
|
||||
#include "Spell.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "GameEventMgr.h"
|
||||
@@ -15811,7 +15811,7 @@ float Player::GetFloatValueFromArray(Tokens const& data, uint16 index)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Player::LoadFromDB(uint32 guid, SqlQueryHolder *holder)
|
||||
bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
|
||||
{
|
||||
//// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
//QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account,name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags,"
|
||||
|
||||
@@ -1407,7 +1407,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
/*** LOAD SYSTEM ***/
|
||||
/*********************************************************/
|
||||
|
||||
bool LoadFromDB(uint32 guid, SqlQueryHolder *holder);
|
||||
bool LoadFromDB(uint32 guid, SQLQueryHolder *holder);
|
||||
bool isBeingLoaded() const { return GetSession()->PlayerLoading();}
|
||||
|
||||
void Initialize(uint32 guid);
|
||||
|
||||
@@ -5822,7 +5822,7 @@ bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inD
|
||||
// add link to DB
|
||||
if (inDB)
|
||||
{
|
||||
WorldDatabase.PExecuteLog("INSERT INTO game_graveyard_zone (id,ghost_zone,faction) "
|
||||
WorldDatabase.PExecute("INSERT INTO game_graveyard_zone (id,ghost_zone,faction) "
|
||||
"VALUES ('%u', '%u','%u')",id,zoneId,team);
|
||||
}
|
||||
|
||||
@@ -8033,8 +8033,9 @@ bool ObjectMgr::AddGameTele(GameTele& tele)
|
||||
|
||||
m_GameTeleMap[new_id] = tele;
|
||||
|
||||
return WorldDatabase.PExecuteLog("INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')",
|
||||
WorldDatabase.PExecute("INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')",
|
||||
new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectMgr::DeleteGameTele(const std::string& name)
|
||||
@@ -8051,7 +8052,7 @@ bool ObjectMgr::DeleteGameTele(const std::string& name)
|
||||
{
|
||||
if (itr->second.wnameLow == wname)
|
||||
{
|
||||
WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str());
|
||||
WorldDatabase.PExecute("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str());
|
||||
m_GameTeleMap.erase(itr);
|
||||
return true;
|
||||
}
|
||||
@@ -8577,7 +8578,7 @@ void ObjectMgr::AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 i
|
||||
vList.AddItem(item, maxcount, incrtime, extendedcost);
|
||||
|
||||
if (savetodb)
|
||||
WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')", entry, item, maxcount, incrtime, extendedcost);
|
||||
WorldDatabase.PExecute("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')", entry, item, maxcount, incrtime, extendedcost);
|
||||
}
|
||||
|
||||
bool ObjectMgr::RemoveVendorItem(uint32 entry,uint32 item, bool savetodb)
|
||||
@@ -8589,7 +8590,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry,uint32 item, bool savetodb)
|
||||
if(!iter->second.RemoveItem(item))
|
||||
return false;
|
||||
|
||||
if (savetodb) WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item);
|
||||
if (savetodb) WorldDatabase.PExecute("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ class WDBThreadStartReq1 : public ACE_Method_Request
|
||||
|
||||
virtual int call()
|
||||
{
|
||||
WorldDatabase.ThreadStart();
|
||||
WorldDatabase.Init_MySQL_Connection();
|
||||
CharacterDatabase.Init_MySQL_Connection();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@@ -31,7 +32,8 @@ class WDBThreadEndReq1 : public ACE_Method_Request
|
||||
|
||||
virtual int call()
|
||||
{
|
||||
WorldDatabase.ThreadEnd();
|
||||
WorldDatabase.End_MySQL_Connection();
|
||||
CharacterDatabase.End_MySQL_Connection();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "WorldSession.h"
|
||||
#include "MD5.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "AsyncDatabaseImpl.h"
|
||||
|
||||
#include "ArenaTeam.h"
|
||||
#include "Chat.h"
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "Util.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
||||
class LoginQueryHolder : public SqlQueryHolder
|
||||
class LoginQueryHolder : public SQLQueryHolder
|
||||
{
|
||||
private:
|
||||
uint32 m_accountId;
|
||||
@@ -117,7 +117,7 @@ class CharacterHandler
|
||||
return;
|
||||
session->HandleCharEnum(result);
|
||||
}
|
||||
void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SqlQueryHolder * holder)
|
||||
void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SQLQueryHolder * holder)
|
||||
{
|
||||
if (!holder) return;
|
||||
WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId());
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "Common.h"
|
||||
#include "Language.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "AsyncDatabaseImpl.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Log.h"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "Common.h"
|
||||
#include "Language.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "AsyncDatabaseImpl.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
@@ -158,7 +158,21 @@ class ReactorRunnable : protected ACE_Task_Base
|
||||
{
|
||||
DEBUG_LOG ("Network Thread Starting");
|
||||
|
||||
WorldDatabase.ThreadStart();
|
||||
bool needInit = true;
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
LoginDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
CharacterDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (needInit)
|
||||
MySQL::Thread_Init();
|
||||
|
||||
ACE_ASSERT (m_Reactor);
|
||||
|
||||
@@ -195,7 +209,14 @@ class ReactorRunnable : protected ACE_Task_Base
|
||||
}
|
||||
}
|
||||
|
||||
WorldDatabase.ThreadEnd();
|
||||
///- Free MySQL thread resources and deallocate lingering connections
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
LoginDatabase.End_MySQL_Connection();
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
CharacterDatabase.End_MySQL_Connection();
|
||||
|
||||
if (needInit)
|
||||
MySQL::Thread_End();
|
||||
|
||||
DEBUG_LOG ("Network Thread Exitting");
|
||||
|
||||
|
||||
@@ -629,8 +629,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||
|
||||
fixNULLfields(line);
|
||||
|
||||
if (!CharacterDatabase.Execute(line.c_str()))
|
||||
ROLLBACK(DUMP_FILE_BROKEN);
|
||||
CharacterDatabase.Execute(line.c_str());
|
||||
}
|
||||
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "VMapFactory.h"
|
||||
#include "GameEventMgr.h"
|
||||
#include "PoolMgr.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "AsyncDatabaseImpl.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
@@ -1223,6 +1223,11 @@ void World::LoadConfigSettings(bool reload)
|
||||
// Dungeon finder
|
||||
m_configs[CONFIG_DUNGEON_FINDER_ENABLE] = sConfig.GetBoolDefault("DungeonFinder.Enable", false);
|
||||
|
||||
// MySQL thread bundling config for other runnable tasks
|
||||
m_configs[CONFIG_MYSQL_BUNDLE_LOGINDB] = sConfig.GetIntDefault("LoginDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL);
|
||||
m_configs[CONFIG_MYSQL_BUNDLE_CHARDB] = sConfig.GetIntDefault("CharacterDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL);
|
||||
m_configs[CONFIG_MYSQL_BUNDLE_WORLDDB] = sConfig.GetIntDefault("WorldDatabase.ThreadBundleMask", MYSQL_BUNDLE_ALL);
|
||||
|
||||
sScriptMgr.OnConfigLoad(reload);
|
||||
}
|
||||
|
||||
@@ -2478,7 +2483,7 @@ void World::SendRNDBroadcast()
|
||||
|
||||
void World::InitResultQueue()
|
||||
{
|
||||
m_resultQueue = new SqlResultQueue;
|
||||
m_resultQueue = new SQLResultQueue;
|
||||
CharacterDatabase.SetResultQueue(m_resultQueue);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class WorldSession;
|
||||
class Player;
|
||||
struct ScriptAction;
|
||||
struct ScriptInfo;
|
||||
class SqlResultQueue;
|
||||
class SQLResultQueue;
|
||||
class QueryResult;
|
||||
class WorldSocket;
|
||||
class SystemMgr;
|
||||
@@ -286,6 +286,9 @@ enum WorldConfigs
|
||||
CONFIG_CHARDELETE_MIN_LEVEL,
|
||||
CONFIG_CLEAN_CHARACTER_DB,
|
||||
CONFIG_DUNGEON_FINDER_ENABLE,
|
||||
CONFIG_MYSQL_BUNDLE_LOGINDB,
|
||||
CONFIG_MYSQL_BUNDLE_CHARDB,
|
||||
CONFIG_MYSQL_BUNDLE_WORLDDB,
|
||||
CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
@@ -761,7 +764,7 @@ class World
|
||||
|
||||
// CLI command holder to be thread safe
|
||||
ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
|
||||
SqlResultQueue *m_resultQueue;
|
||||
SQLResultQueue *m_resultQueue;
|
||||
|
||||
// next daily quests and random bg reset time
|
||||
time_t m_NextDailyQuestReset;
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "Database/DatabaseWorkerPool.h"
|
||||
#include "Database/SQLOperation.h"
|
||||
|
||||
|
||||
/// Function body definitions for the template function members of the Database class
|
||||
|
||||
#define ASYNC_QUERY_BODY(sql, queue_itr) \
|
||||
if (!sql) return false; \
|
||||
\
|
||||
QueryQueues::iterator queue_itr; \
|
||||
\
|
||||
{ \
|
||||
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
|
||||
queue_itr = m_queryQueues.find(queryThread); \
|
||||
if (queue_itr == m_queryQueues.end()) return false; \
|
||||
}
|
||||
|
||||
#define ASYNC_PQUERY_BODY(format, szQuery) \
|
||||
if(!format) return false; \
|
||||
\
|
||||
char szQuery [MAX_QUERY_LEN]; \
|
||||
\
|
||||
{ \
|
||||
va_list ap; \
|
||||
\
|
||||
va_start(ap, format); \
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \
|
||||
va_end(ap); \
|
||||
\
|
||||
if(res==-1) \
|
||||
{ \
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \
|
||||
if (!holder) return false; \
|
||||
\
|
||||
QueryQueues::iterator queue_itr; \
|
||||
\
|
||||
{ \
|
||||
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
|
||||
queue_itr = m_queryQueues.find(queryThread); \
|
||||
if (queue_itr == m_queryQueues.end()) return false; \
|
||||
}
|
||||
|
||||
|
||||
// -- Query / member --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class>(object, method), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// -- Query / static --
|
||||
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// -- PQuery / member --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, param2, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, param2, param3, szQuery);
|
||||
}
|
||||
|
||||
|
||||
// -- PQuery / static --
|
||||
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, param2, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, param2, param3, szQuery);
|
||||
}
|
||||
|
||||
|
||||
// -- QueryHolder --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder)
|
||||
{
|
||||
ASYNC_DELAYHOLDER_BODY(holder, itr)
|
||||
SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1)
|
||||
{
|
||||
ASYNC_DELAYHOLDER_BODY(holder, itr)
|
||||
SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), itr->second);
|
||||
Enqueue(task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#undef ASYNC_QUERY_BODY
|
||||
#undef ASYNC_PQUERY_BODY
|
||||
#undef ASYNC_DELAYHOLDER_BODY
|
||||
@@ -28,8 +28,10 @@
|
||||
#include "Database/Field.h"
|
||||
#include "Database/QueryResult.h"
|
||||
|
||||
#include "Database/Database.h"
|
||||
typedef Database DatabaseType;
|
||||
#include "Database/DatabaseWorkerPool.h"
|
||||
#include "Database/MySQLThreading.h"
|
||||
|
||||
typedef DatabaseWorkerPool DatabaseType;
|
||||
#define _LIKE_ "LIKE"
|
||||
#define _TABLE_SIM_ "`"
|
||||
#define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )"
|
||||
@@ -39,5 +41,7 @@ extern DatabaseType WorldDatabase;
|
||||
extern DatabaseType CharacterDatabase;
|
||||
extern DatabaseType LoginDatabase;
|
||||
|
||||
#define MAX_QUERY_LEN 32*1024
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "Database/Database.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
|
||||
|
||||
/// Function body definitions for the template function members of the Database class
|
||||
|
||||
|
||||
#define ASYNC_QUERY_BODY(sql, queue_itr) \
|
||||
if (!sql) return false; \
|
||||
\
|
||||
QueryQueues::iterator queue_itr; \
|
||||
\
|
||||
{ \
|
||||
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
|
||||
queue_itr = m_queryQueues.find(queryThread); \
|
||||
if (queue_itr == m_queryQueues.end()) return false; \
|
||||
}
|
||||
|
||||
|
||||
#define ASYNC_PQUERY_BODY(format, szQuery) \
|
||||
if(!format) return false; \
|
||||
\
|
||||
char szQuery [MAX_QUERY_LEN]; \
|
||||
\
|
||||
{ \
|
||||
va_list ap; \
|
||||
\
|
||||
va_start(ap, format); \
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \
|
||||
va_end(ap); \
|
||||
\
|
||||
if(res==-1) \
|
||||
{ \
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \
|
||||
if (!holder) return false; \
|
||||
\
|
||||
QueryQueues::iterator queue_itr; \
|
||||
\
|
||||
{ \
|
||||
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
|
||||
queue_itr = m_queryQueues.find(queryThread); \
|
||||
if (queue_itr == m_queryQueues.end()) return false; \
|
||||
}
|
||||
|
||||
|
||||
// -- Query / member --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class>(object, method), itr->second));
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second));
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second));
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second));
|
||||
}
|
||||
|
||||
|
||||
// -- Query / static --
|
||||
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second));
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second));
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
|
||||
{
|
||||
ASYNC_QUERY_BODY(sql, itr)
|
||||
return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second));
|
||||
}
|
||||
|
||||
|
||||
// -- PQuery / member --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, param2, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(object, method, param1, param2, param3, szQuery);
|
||||
}
|
||||
|
||||
|
||||
// -- PQuery / static --
|
||||
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool
|
||||
Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, param2, szQuery);
|
||||
}
|
||||
|
||||
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool
|
||||
Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
|
||||
{
|
||||
ASYNC_PQUERY_BODY(format, szQuery)
|
||||
return AsyncQuery(method, param1, param2, param3, szQuery);
|
||||
}
|
||||
|
||||
|
||||
// -- QueryHolder --
|
||||
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*), SqlQueryHolder *holder)
|
||||
{
|
||||
ASYNC_DELAYHOLDER_BODY(holder, itr)
|
||||
return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), m_threadBody, itr->second);
|
||||
}
|
||||
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1)
|
||||
{
|
||||
ASYNC_DELAYHOLDER_BODY(holder, itr)
|
||||
return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), m_threadBody, itr->second);
|
||||
}
|
||||
|
||||
|
||||
#undef ASYNC_QUERY_BODY
|
||||
#undef ASYNC_PQUERY_BODY
|
||||
#undef ASYNC_DELAYHOLDER_BODY
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseWorker.h"
|
||||
#include "SQLOperation.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) :
|
||||
m_queue(new_queue),
|
||||
m_conn(con)
|
||||
{
|
||||
/// Assign thread to task
|
||||
activate();
|
||||
}
|
||||
|
||||
int DatabaseWorker::svc()
|
||||
{
|
||||
if (!m_queue)
|
||||
return -1;
|
||||
|
||||
SQLOperation *request = NULL;
|
||||
while (1)
|
||||
{
|
||||
request = (SQLOperation*)(m_queue->dequeue());
|
||||
if (!request)
|
||||
break;
|
||||
|
||||
request->SetConnection(m_conn);
|
||||
request->call();
|
||||
delete request;
|
||||
}
|
||||
|
||||
delete m_conn;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DatabaseWorker::activate()
|
||||
{
|
||||
/* THR_DETACHED:
|
||||
Create an asynchronous thread. The exit status of the thread would not be available to any other threads.
|
||||
The thread resources are reclaimed by the operating system whenever the thread is terminated. */
|
||||
|
||||
/* THR_NEW_LWP:
|
||||
Create an explicit kernel-level thread (as opposed to a user-level thread). */
|
||||
|
||||
ACE_Task_Base::activate(THR_NEW_LWP | THR_DETACHED, 1);
|
||||
return 0; //^ - Spawn one thread to handle this task.
|
||||
// However more of these tasks may be activated
|
||||
// See DatabaseWorkerPool ctor.
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _WORKERTHREAD_H
|
||||
#define _WORKERTHREAD_H
|
||||
|
||||
#include <ace/Task.h>
|
||||
#include <ace/Activation_Queue.h>
|
||||
|
||||
class MySQLConnection;
|
||||
|
||||
class DatabaseWorker : protected ACE_Task_Base
|
||||
{
|
||||
public:
|
||||
DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con);
|
||||
|
||||
///- Inherited from ACE_Task_Base
|
||||
int svc();
|
||||
int activate();
|
||||
|
||||
private:
|
||||
DatabaseWorker() : ACE_Task_Base() {}
|
||||
ACE_Activation_Queue* m_queue;
|
||||
MySQLConnection* m_conn;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DatabaseWorkerPool.h"
|
||||
#include "MySQLConnection.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "SQLOperation.h"
|
||||
|
||||
DatabaseWorkerPool::DatabaseWorkerPool() :
|
||||
m_queue(new ACE_Activation_Queue(new ACE_Message_Queue<ACE_MT_SYNCH>)),
|
||||
m_connections(0)
|
||||
{
|
||||
m_infoString = "";
|
||||
|
||||
mysql_library_init(-1, NULL, NULL);
|
||||
WPFatal (mysql_thread_safe(), "Used MySQL library isn't thread-safe.");
|
||||
}
|
||||
|
||||
DatabaseWorkerPool::~DatabaseWorkerPool()
|
||||
{
|
||||
}
|
||||
|
||||
bool DatabaseWorkerPool::Open(const std::string& infoString, uint8 num_threads)
|
||||
{
|
||||
sLog.outDebug("Creating bundled/master MySQL connection.");
|
||||
m_bundle_conn = new MySQLConnection();
|
||||
m_bundle_conn->Open(infoString);
|
||||
++m_connections;
|
||||
|
||||
m_async_connections.resize(num_threads);
|
||||
|
||||
/// Open the Async pool
|
||||
for (uint8 i = 0; i < num_threads; i++)
|
||||
{
|
||||
m_async_connections[i] = new MySQLConnection(m_queue);
|
||||
m_async_connections[i]->Open(infoString);
|
||||
++m_connections;
|
||||
sLog.outDebug("Async database thread pool opened. Worker thread count: %u", num_threads);
|
||||
}
|
||||
|
||||
m_infoString = infoString;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::Close()
|
||||
{
|
||||
/// Shuts down worker threads for this connection pool.
|
||||
for (uint8 i = 0; i < m_async_connections.size(); i++)
|
||||
Enqueue(NULL);
|
||||
|
||||
//- MySQL::Thread_End() should be called manually from the aborting calling threads
|
||||
|
||||
delete m_bundle_conn;
|
||||
m_bundle_conn = NULL;
|
||||
}
|
||||
|
||||
/*! This function creates a new MySQL connection for every MapUpdate thread
|
||||
and every unbundled task.
|
||||
*/
|
||||
void DatabaseWorkerPool::Init_MySQL_Connection()
|
||||
{
|
||||
MySQLConnection* conn = new MySQLConnection();
|
||||
conn->Open(m_infoString);
|
||||
|
||||
{
|
||||
ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx);
|
||||
m_sync_connections[ACE_Based::Thread::current()] = conn;
|
||||
}
|
||||
|
||||
sLog.outDebug("Core thread with ID ["UI64FMTD"] initializing MySQL connection.",
|
||||
(uint64)ACE_Based::Thread::currentId());
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::End_MySQL_Connection()
|
||||
{
|
||||
MySQLConnection* conn;
|
||||
{
|
||||
ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx);
|
||||
conn = m_sync_connections[ACE_Based::Thread::current()];
|
||||
}
|
||||
delete conn;
|
||||
conn = NULL;
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::Execute(const char* sql)
|
||||
{
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
BasicStatementTask* task = new BasicStatementTask(sql);
|
||||
Enqueue(task);
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::PExecute(const char* sql, ...)
|
||||
{
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
char szQuery[MAX_QUERY_LEN];
|
||||
va_start(ap, sql);
|
||||
int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
|
||||
va_end(ap);
|
||||
|
||||
Execute(szQuery);
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::DirectExecute(const char* sql)
|
||||
{
|
||||
if (sql)
|
||||
GetConnection()->Execute(sql);
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::DirectPExecute(const char* sql, ...)
|
||||
{
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
char szQuery[MAX_QUERY_LEN];
|
||||
va_start(ap, sql);
|
||||
int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
|
||||
va_end(ap);
|
||||
|
||||
return DirectExecute(szQuery);
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr DatabaseWorkerPool::Query(const char* sql)
|
||||
{
|
||||
return GetConnection()->Query(sql);
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr DatabaseWorkerPool::PQuery(const char* sql, ...)
|
||||
{
|
||||
if (!sql)
|
||||
return QueryResult_AutoPtr(NULL);
|
||||
|
||||
va_list ap;
|
||||
char szQuery[MAX_QUERY_LEN];
|
||||
va_start(ap, sql);
|
||||
int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
|
||||
va_end(ap);
|
||||
|
||||
return Query(szQuery);
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::BeginTransaction()
|
||||
{
|
||||
ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx);
|
||||
ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction
|
||||
TransactionQueues::iterator itr = m_tranQueues.find(tranThread);
|
||||
if (itr != m_tranQueues.end() && itr->second != NULL)
|
||||
{
|
||||
itr->second->ForcefulDelete();
|
||||
delete itr->second;
|
||||
}
|
||||
m_tranQueues[tranThread] = new TransactionTask();
|
||||
return;
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::RollbackTransaction()
|
||||
{
|
||||
ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx);
|
||||
ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction
|
||||
TransactionQueues::iterator itr = m_tranQueues.find(tranThread);
|
||||
if (itr != m_tranQueues.end() && itr->second != NULL)
|
||||
{
|
||||
itr->second->ForcefulDelete();
|
||||
delete itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseWorkerPool::CommitTransaction()
|
||||
{
|
||||
ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx);
|
||||
ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction
|
||||
TransactionQueues::iterator itr = m_tranQueues.find(tranThread);
|
||||
if (itr != m_tranQueues.end() && itr->second != NULL)
|
||||
{
|
||||
Enqueue(itr->second);
|
||||
m_tranQueues.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MySQLConnection* DatabaseWorkerPool::GetConnection()
|
||||
{
|
||||
MySQLConnection* conn;
|
||||
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())
|
||||
conn = itr->second;
|
||||
}
|
||||
/*! Bundled threads */
|
||||
conn = m_bundle_conn;
|
||||
ASSERT (conn);
|
||||
return conn;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DATABASEWORKERPOOL_H
|
||||
#define _DATABASEWORKERPOOL_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Logging/Log.h"
|
||||
|
||||
#include <ace/Activation_Queue.h>
|
||||
#include <ace/Atomic_Op_T.h>
|
||||
#include <ace/Thread_Mutex.h>
|
||||
|
||||
#include "SQLOperation.h"
|
||||
#include "QueryResult.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
enum MySQLThreadBundle
|
||||
{
|
||||
MYSQL_BUNDLE_NONE = 0x00, //- Each task will run their own MySQL connection
|
||||
MYSQL_BUNDLE_CLI = 0x01, //- Commandline interface thread
|
||||
MYSQL_BUNDLE_RA = 0x02, //- Remote admin thread
|
||||
MYSQL_BUNDLE_RAR = 0x04, //- Reactor runnable thread
|
||||
MYSQL_BUNDLE_WORLD = 0x08, //- WorldRunnable
|
||||
MYSQL_BUNDLE_ALL = MYSQL_BUNDLE_CLI | MYSQL_BUNDLE_RA | MYSQL_BUNDLE_RAR | MYSQL_BUNDLE_WORLD,
|
||||
};
|
||||
|
||||
class DatabaseWorkerPool
|
||||
{
|
||||
public:
|
||||
DatabaseWorkerPool();
|
||||
~DatabaseWorkerPool();
|
||||
|
||||
bool Open(const std::string& infoString, uint8 num_threads);
|
||||
void Close();
|
||||
|
||||
void Init_MySQL_Connection();
|
||||
void End_MySQL_Connection();
|
||||
|
||||
void Execute(const char* sql);
|
||||
void PExecute(const char* sql, ...);
|
||||
void DirectExecute(const char* sql);
|
||||
void DirectPExecute(const char* sql, ...);
|
||||
QueryResult_AutoPtr Query(const char* sql);
|
||||
QueryResult_AutoPtr PQuery(const char* sql, ...);
|
||||
|
||||
/// Async queries and query holders, implemented in DatabaseImpl.h
|
||||
|
||||
// Query / member
|
||||
template<class Class>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql);
|
||||
template<class Class, typename ParamType1>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
|
||||
// Query / static
|
||||
template<typename ParamType1>
|
||||
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
|
||||
// PQuery / member
|
||||
template<class Class>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) ATTR_PRINTF(4,5);
|
||||
template<class Class, typename ParamType1>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
|
||||
template<class Class, typename ParamType1, typename ParamType2>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(6,7);
|
||||
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(7,8);
|
||||
// PQuery / static
|
||||
template<typename ParamType1>
|
||||
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(4,5);
|
||||
template<typename ParamType1, typename ParamType2>
|
||||
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6);
|
||||
template<typename ParamType1, typename ParamType2, typename ParamType3>
|
||||
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(6,7);
|
||||
template<class Class>
|
||||
// QueryHolder
|
||||
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder);
|
||||
template<class Class, typename ParamType1>
|
||||
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1);
|
||||
|
||||
void SetResultQueue(SQLResultQueue * queue)
|
||||
{
|
||||
m_queryQueues[ACE_Based::Thread::current()] = queue;
|
||||
}
|
||||
|
||||
void BeginTransaction();
|
||||
void RollbackTransaction();
|
||||
void CommitTransaction();
|
||||
|
||||
void escape_string(std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return;
|
||||
|
||||
char* buf = new char[str.size()*2+1];
|
||||
escape_string(buf,str.c_str(),str.size());
|
||||
str = buf;
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
unsigned long escape_string(char *to, const char *from, unsigned long length)
|
||||
{
|
||||
if (!to || !from || !length)
|
||||
return 0;
|
||||
return (mysql_real_escape_string(GetConnection()->GetHandle(), to, from, length));
|
||||
}
|
||||
|
||||
private:
|
||||
void Enqueue(SQLOperation* op)
|
||||
{
|
||||
m_queue->enqueue(op);
|
||||
}
|
||||
|
||||
MySQLConnection* GetConnection();
|
||||
|
||||
private:
|
||||
typedef UNORDERED_MAP<ACE_Based::Thread*, MySQLConnection*> ConnectionMap;
|
||||
typedef UNORDERED_MAP<ACE_Based::Thread*, TransactionTask*> TransactionQueues;
|
||||
typedef UNORDERED_MAP<ACE_Based::Thread*, SQLResultQueue*> QueryQueues;
|
||||
typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, uint32> AtomicUInt;
|
||||
|
||||
private:
|
||||
ACE_Activation_Queue* m_queue; //! Queue shared by async worker threads.
|
||||
ACE_Thread_Mutex m_queue_mtx; //! For thread safe enqueues of delayed statements.
|
||||
std::vector<MySQLConnection*> 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
|
||||
MySQLConnection* m_bundle_conn; //! Bundled connection (see Database.ThreadBundleMask config)
|
||||
AtomicUInt m_connections; //! Counter of MySQL connections;
|
||||
std::string m_infoString; //! Infostring that is passed on to child connections.
|
||||
TransactionQueues m_tranQueues; //! Transaction queues from diff. threads
|
||||
ACE_Thread_Mutex m_transQueues_mtx; //! To guard m_transQueues
|
||||
QueryQueues m_queryQueues; //! Query queues from diff threads
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "MySQLConnection.h"
|
||||
#include "DatabaseWorker.h"
|
||||
#include "Utilities/Util.h"
|
||||
#include "Utilities/Timer.h"
|
||||
|
||||
MySQLConnection::MySQLConnection() :
|
||||
m_Mysql(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue) :
|
||||
m_queue(queue),
|
||||
m_Mysql(NULL)
|
||||
{
|
||||
m_worker = new DatabaseWorker(m_queue, this);
|
||||
}
|
||||
|
||||
MySQLConnection::~MySQLConnection()
|
||||
{
|
||||
delete m_worker;
|
||||
}
|
||||
|
||||
bool MySQLConnection::Open(const std::string& infoString)
|
||||
{
|
||||
MYSQL *mysqlInit;
|
||||
mysqlInit = mysql_init(NULL);
|
||||
if (!mysqlInit)
|
||||
{
|
||||
sLog.outError("Could not initialize Mysql connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
Tokens tokens = StrSplit(infoString, ";");
|
||||
|
||||
Tokens::iterator iter;
|
||||
|
||||
std::string host, port_or_socket, user, password, database;
|
||||
int port;
|
||||
char const* unix_socket;
|
||||
|
||||
iter = tokens.begin();
|
||||
|
||||
if (iter != tokens.end())
|
||||
host = *iter++;
|
||||
if (iter != tokens.end())
|
||||
port_or_socket = *iter++;
|
||||
if (iter != tokens.end())
|
||||
user = *iter++;
|
||||
if (iter != tokens.end())
|
||||
password = *iter++;
|
||||
if (iter != tokens.end())
|
||||
database = *iter++;
|
||||
|
||||
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
|
||||
#ifdef _WIN32
|
||||
if (host==".") // named pipe use option (Windows)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_PIPE;
|
||||
mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
|
||||
port = 0;
|
||||
unix_socket = 0;
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#else
|
||||
if (host==".") // socket use option (Unix/Linux)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
|
||||
mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
|
||||
host = "localhost";
|
||||
port = 0;
|
||||
unix_socket = port_or_socket.c_str();
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_Mysql = mysql_real_connect(mysqlInit, host.c_str(), user.c_str(),
|
||||
password.c_str(), database.c_str(), port, unix_socket, 0);
|
||||
|
||||
if (m_Mysql)
|
||||
{
|
||||
sLog.outDetail("Connected to MySQL database at %s", host.c_str());
|
||||
sLog.outString("MySQL client library: %s", mysql_get_client_info());
|
||||
sLog.outString("MySQL server ver: %s ", mysql_get_server_info( m_Mysql));
|
||||
|
||||
if (!mysql_autocommit(m_Mysql, 1))
|
||||
sLog.outDetail("AUTOCOMMIT SUCCESSFULLY SET TO 1");
|
||||
else
|
||||
sLog.outDetail("AUTOCOMMIT NOT SET TO 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
|
||||
Execute("SET NAMES `utf8`");
|
||||
Execute("SET CHARACTER SET `utf8`");
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50003
|
||||
my_bool my_true = (my_bool)1;
|
||||
if (mysql_options(m_Mysql, MYSQL_OPT_RECONNECT, &my_true))
|
||||
sLog.outDetail("Failed to turn on MYSQL_OPT_RECONNECT.");
|
||||
else
|
||||
sLog.outDetail("Successfully turned on MYSQL_OPT_RECONNECT.");
|
||||
#else
|
||||
#warning "Your mySQL client lib version does not support reconnecting after a timeout.\nIf this causes you any trouble we advice you to upgrade your mySQL client libs to at least mySQL 5.0.13 to resolve this problem."
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Could not connect to MySQL database at %s: %s\n", host.c_str(), mysql_error(mysqlInit));
|
||||
mysql_close(mysqlInit);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MySQLConnection::Execute(const char* sql)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
{
|
||||
// guarded block for thread-safe mySQL request
|
||||
ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex);
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
sLog.outErrorDb("SQL: %s", sql);
|
||||
sLog.outErrorDb("SQL ERROR: %s", mysql_error(m_Mysql));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TRINITY_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr MySQLConnection::Query(const char* sql)
|
||||
{
|
||||
if (!sql)
|
||||
return QueryResult_AutoPtr(NULL);
|
||||
|
||||
MYSQL_RES *result = NULL;
|
||||
MYSQL_FIELD *fields = NULL;
|
||||
uint64 rowCount = 0;
|
||||
uint32 fieldCount = 0;
|
||||
|
||||
if (!_Query(sql, &result, &fields, &rowCount, &fieldCount))
|
||||
return QueryResult_AutoPtr(NULL);
|
||||
|
||||
QueryResult *queryResult = new QueryResult(result, fields, rowCount, fieldCount);
|
||||
|
||||
queryResult->NextRow();
|
||||
|
||||
return QueryResult_AutoPtr(queryResult);
|
||||
}
|
||||
|
||||
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
{
|
||||
// guarded block for thread-safe mySQL request
|
||||
ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex);
|
||||
#ifdef TRINITY_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
sLog.outErrorDb("SQL: %s", sql);
|
||||
sLog.outErrorDb("query ERROR: %s", mysql_error(m_Mysql));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TRINITY_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql);
|
||||
#endif
|
||||
}
|
||||
|
||||
*pResult = mysql_store_result(m_Mysql);
|
||||
*pRowCount = mysql_affected_rows(m_Mysql);
|
||||
*pFieldCount = mysql_field_count(m_Mysql);
|
||||
}
|
||||
|
||||
if (!*pResult )
|
||||
return false;
|
||||
|
||||
if (!*pRowCount)
|
||||
{
|
||||
mysql_free_result(*pResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
*pFields = mysql_fetch_fields(*pResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MySQLConnection::BeginTransaction()
|
||||
{
|
||||
Execute("START TRANSACTION");
|
||||
}
|
||||
|
||||
void MySQLConnection::RollbackTransaction()
|
||||
{
|
||||
Execute("ROLLBACK");
|
||||
}
|
||||
|
||||
void MySQLConnection::CommitTransaction()
|
||||
{
|
||||
Execute("COMMIT");
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MYSQLCONNECTION_H
|
||||
#define _MYSQLCONNECTION_H
|
||||
|
||||
class DatabaseWorker;
|
||||
|
||||
class MySQLConnection
|
||||
{
|
||||
friend class DatabaseWorkerPool;
|
||||
|
||||
public:
|
||||
MySQLConnection(); //! Constructor for synchroneous connections.
|
||||
MySQLConnection(ACE_Activation_Queue* queue); //! Constructor for asynchroneous connections.
|
||||
~MySQLConnection();
|
||||
|
||||
bool Open(const std::string& infoString); //! Connection details.
|
||||
|
||||
public:
|
||||
bool Execute(const char* sql);
|
||||
QueryResult_AutoPtr Query(const char* sql);
|
||||
bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount);
|
||||
|
||||
void BeginTransaction();
|
||||
void RollbackTransaction();
|
||||
void CommitTransaction();
|
||||
|
||||
operator bool () const { return m_Mysql != NULL; }
|
||||
|
||||
protected:
|
||||
MYSQL* GetHandle() { return m_Mysql; }
|
||||
|
||||
private:
|
||||
ACE_Activation_Queue* m_queue; //! Queue shared with other asynchroneous connections.
|
||||
DatabaseWorker* m_worker; //! Core worker task.
|
||||
MYSQL * m_Mysql; //! MySQL Handle.
|
||||
ACE_Thread_Mutex m_Mutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MYSQLTHREADING_H
|
||||
#define _MYSQLTHREADING_H
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
class MySQL
|
||||
{
|
||||
public:
|
||||
/*! Create a thread on the MySQL server to mirrior the calling thread,
|
||||
initializes thread-specific variables and allows thread-specific
|
||||
operations without concurrence from other threads.
|
||||
This should only be called if multiple core threads are running
|
||||
on the same MySQL connection. Seperate MySQL connections implicitly
|
||||
create a mirror thread.
|
||||
*/
|
||||
static void Thread_Init()
|
||||
{
|
||||
mysql_thread_init();
|
||||
printf("Core thread with ID ["UI64FMTD"] initializing MySQL thread.",
|
||||
(uint64)ACE_Based::Thread::currentId());
|
||||
}
|
||||
|
||||
/*! Shuts down MySQL thread and frees resources, should only be called
|
||||
when we terminate. MySQL threads and connections are not configurable
|
||||
during runtime.
|
||||
*/
|
||||
static void Thread_End()
|
||||
{
|
||||
mysql_thread_end();
|
||||
printf("Core thread with ID ["UI64FMTD"] shutting down MySQL thread.",
|
||||
(uint64)ACE_Based::Thread::currentId());
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
#include "PreparedStatements.h"
|
||||
|
||||
void PreparedStatementHolder::_prepareStatement(const char* name, const char* sql, Database *db, uint32 &count)
|
||||
{
|
||||
const char prefix[] = "PREPARE ";
|
||||
size_t querySize = 8 + strlen(name) + 6 + strlen(sql) + 2 + 1;
|
||||
char* query = new char[querySize];
|
||||
strcpy(query, prefix);
|
||||
strcat(query, name);
|
||||
strcat(query, " FROM ");
|
||||
strcat(query, "'");
|
||||
strcat(query, sql);
|
||||
strcat(query, "'");
|
||||
|
||||
DEBUG_LOG("Preparing statement: %s", query);
|
||||
db->Execute(query);
|
||||
|
||||
delete[] query;
|
||||
++count;
|
||||
}
|
||||
|
||||
void PreparedStatementHolder::LoadAuthserver(Database *db, uint32 &count)
|
||||
{
|
||||
_prepareStatement("auth_ping", "SELECT 1 FROM realmlist LIMIT 1", db, count);
|
||||
};
|
||||
|
||||
void PreparedStatementHolder::Execute(Database *db, const char *name)
|
||||
{
|
||||
const char prefix[] = "EXECUTE ";
|
||||
size_t querySize = 8 + strlen(name) + 1;
|
||||
char* query = new char[querySize];
|
||||
strcpy(query, prefix);
|
||||
strcat(query, name);
|
||||
|
||||
DEBUG_LOG("Prepared statement: %s", query);
|
||||
db->Execute(query);
|
||||
delete[] query;
|
||||
}
|
||||
|
||||
void PreparedStatementHolder::PExecute(Database *db, const char *name, const char* args)
|
||||
{
|
||||
// NOTE: if args == NULL, we're crashing here. No need to waste performance on checking;
|
||||
// devs must make sure they use PExecute for args and Execute for no args.
|
||||
|
||||
const char prefix[] = "EXECUTE ";
|
||||
size_t querySize = 8 + strlen(name) + 7 + strlen(args) + 1;
|
||||
char* query = new char[querySize];
|
||||
strcpy(query, prefix);
|
||||
strcat(query, name);
|
||||
strcat(query, " USING ");
|
||||
strcat(query, args);
|
||||
|
||||
DEBUG_LOG("Prepared statement (parsed args): %s", query);
|
||||
db->Execute(query);
|
||||
delete[] query;
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr PreparedStatementHolder::Query(Database *db, const char *name)
|
||||
{
|
||||
QueryResult_AutoPtr _return = QueryResult_AutoPtr(NULL);
|
||||
|
||||
const char prefix[] = "EXECUTE ";
|
||||
size_t querySize = 8 + strlen(name) + 1;
|
||||
char* query = new char[querySize];
|
||||
strcpy(query, prefix);
|
||||
strcat(query, name);
|
||||
|
||||
DEBUG_LOG("Prepared statement with resultset: %s", query);
|
||||
_return = db->Query(query);
|
||||
delete[] query;
|
||||
return _return;
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr PreparedStatementHolder::PQuery(Database *db, const char *name, const char *args)
|
||||
{
|
||||
// NOTE: if args == NULL, we're crashing here. No need to waste performance on checking;
|
||||
// devs must make sure they use PQuery for args and Query for no args.
|
||||
|
||||
QueryResult_AutoPtr _return = QueryResult_AutoPtr(NULL);
|
||||
|
||||
const char prefix[] = "EXECUTE ";
|
||||
size_t querySize = 8 + strlen(name) + 7 + strlen(args) + 1;
|
||||
char* query = new char[querySize];
|
||||
strcpy(query, prefix);
|
||||
strcat(query, name);
|
||||
strcat(query, " USING ");
|
||||
strcat(query, args);
|
||||
|
||||
DEBUG_LOG("Prepared statement with resultset (parsed args): %s", query);
|
||||
_return = db->Query(query);
|
||||
delete[] query;
|
||||
return _return;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef sPreparedStatement
|
||||
|
||||
#include "ace/Singleton.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
class PreparedStatementHolder
|
||||
{
|
||||
public:
|
||||
///- Load prepare statements on database $db and increase $count for every statement
|
||||
void LoadCharacters(Database *db, uint32 &count);
|
||||
void LoadAuthserver(Database *db, uint32 &count);
|
||||
void LoadWorldserver(Database *db, uint32 &count);
|
||||
|
||||
///- Executes prepared statement that doesn't require feedback with name $name on database $db
|
||||
void Execute(Database *db, const char* name);
|
||||
///- Executes prepared statement that doesn't require feedback with name $name and args $args
|
||||
///- on database $db
|
||||
void PExecute(Database *db, const char* name, const char* args);
|
||||
|
||||
///- Executes a prepared statement without args on db $db with name $name and puts the result set in a pointer.
|
||||
QueryResult_AutoPtr Query(Database* db, const char* name);
|
||||
///- Executes a prepared statement with args $args on db $db with name $name and put the result set in a pointer.
|
||||
QueryResult_AutoPtr PQuery(Database* db, const char* name, const char* args);
|
||||
|
||||
private:
|
||||
void _prepareStatement(const char* name, const char* sql, Database *db, uint32 &count);
|
||||
|
||||
};
|
||||
#define sPreparedStatement (*ACE_Singleton<PreparedStatementHolder, ACE_Null_Mutex>::instance())
|
||||
#endif
|
||||
+79
-76
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,71 +16,74 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SqlOperations.h"
|
||||
#include "SqlDelayThread.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseImpl.h"
|
||||
#include "SQLOperation.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
|
||||
|
||||
void SqlStatement::Execute(Database *db)
|
||||
/*! Basic, ad-hoc queries. */
|
||||
BasicStatementTask::BasicStatementTask(const char* sql)
|
||||
{
|
||||
/// just do it
|
||||
db->DirectExecute(m_sql);
|
||||
m_sql = strdup(sql);
|
||||
}
|
||||
|
||||
void SqlTransaction::Execute(Database *db)
|
||||
BasicStatementTask::~BasicStatementTask()
|
||||
{
|
||||
free((void*)m_sql);
|
||||
}
|
||||
|
||||
bool BasicStatementTask::Execute()
|
||||
{
|
||||
return m_conn->Execute(m_sql);
|
||||
}
|
||||
|
||||
/*! Transactions. */
|
||||
TransactionTask::TransactionTask()
|
||||
{
|
||||
}
|
||||
|
||||
TransactionTask::~TransactionTask()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TransactionTask::ForcefulDelete()
|
||||
{
|
||||
while (!m_queries.empty())
|
||||
{
|
||||
free((void*)const_cast<char*>(m_queries.front()));
|
||||
m_queries.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool TransactionTask::Execute()
|
||||
{
|
||||
if (m_queries.empty())
|
||||
return false;
|
||||
|
||||
const char* sql;
|
||||
|
||||
m_Mutex.acquire();
|
||||
if (m_queue.empty())
|
||||
m_conn->BeginTransaction();
|
||||
while (!m_queries.empty())
|
||||
{
|
||||
m_Mutex.release();
|
||||
return;
|
||||
}
|
||||
|
||||
db->DirectExecute("START TRANSACTION");
|
||||
while (!m_queue.empty())
|
||||
{
|
||||
sql = m_queue.front();
|
||||
|
||||
if (!db->DirectExecute(sql))
|
||||
sql = m_queries.front();
|
||||
if (!m_conn->Execute(sql))
|
||||
{
|
||||
free((void*)const_cast<char*>(sql));
|
||||
m_queue.pop();
|
||||
db->DirectExecute("ROLLBACK");
|
||||
while (!m_queue.empty())
|
||||
{
|
||||
free((void*)const_cast<char*>(m_queue.front()));
|
||||
m_queue.pop();
|
||||
}
|
||||
m_Mutex.release();
|
||||
return;
|
||||
m_queries.pop();
|
||||
m_conn->RollbackTransaction();
|
||||
ForcefulDelete();
|
||||
return false;
|
||||
}
|
||||
|
||||
free((void*)const_cast<char*>(sql));
|
||||
m_queue.pop();
|
||||
m_queries.pop();
|
||||
}
|
||||
|
||||
db->DirectExecute("COMMIT");
|
||||
m_Mutex.release();
|
||||
m_conn->CommitTransaction();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ---- ASYNC QUERIES ----
|
||||
|
||||
void SqlQuery::Execute(Database *db)
|
||||
{
|
||||
if (!m_callback || !m_queue)
|
||||
return;
|
||||
|
||||
/// execute the query and store the result in the callback
|
||||
m_callback->SetResult(db->Query(m_sql));
|
||||
/// add the callback to the sql result queue of the thread it originated from
|
||||
m_queue->add(m_callback);
|
||||
}
|
||||
|
||||
void SqlResultQueue::Update()
|
||||
/*! Callback statements/holders */
|
||||
void SQLResultQueue::Update()
|
||||
{
|
||||
/// execute the callbacks waiting in the synchronization queue
|
||||
Trinity::IQueryCallback* callback;
|
||||
@@ -93,39 +94,27 @@ void SqlResultQueue::Update()
|
||||
}
|
||||
}
|
||||
|
||||
bool SqlQueryHolder::Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue)
|
||||
{
|
||||
if (!callback || !thread || !queue)
|
||||
return false;
|
||||
|
||||
/// delay the execution of the queries, sync them with the delay thread
|
||||
/// which will in turn resync on execution (via the queue) and call back
|
||||
SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue);
|
||||
thread->Delay(holderEx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlQueryHolder::SetQuery(size_t index, const char *sql)
|
||||
bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
|
||||
{
|
||||
if (m_queries.size() <= index)
|
||||
{
|
||||
sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,(uint32)m_queries.size(),sql);
|
||||
sLog.outError("Query index (%u) out of range (size: %u) for query: %s", index, (uint32)m_queries.size(), sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_queries[index].first != NULL)
|
||||
{
|
||||
sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",
|
||||
index,m_queries[index].first,sql);
|
||||
index, m_queries[index].first, sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// not executed yet, just stored (it's not called a holder for nothing)
|
||||
m_queries[index] = SqlResultPair(strdup(sql), QueryResult_AutoPtr(NULL));
|
||||
m_queries[index] = SQLResultPair(strdup(sql), QueryResult_AutoPtr(NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
|
||||
bool SQLQueryHolder::SetPQuery(size_t index, const char *format, ...)
|
||||
{
|
||||
if (!format)
|
||||
{
|
||||
@@ -145,10 +134,10 @@ bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetQuery(index,szQuery);
|
||||
return SetQuery(index, szQuery);
|
||||
}
|
||||
|
||||
QueryResult_AutoPtr SqlQueryHolder::GetResult(size_t index)
|
||||
QueryResult_AutoPtr SQLQueryHolder::GetResult(size_t index)
|
||||
{
|
||||
if (index < m_queries.size())
|
||||
{
|
||||
@@ -165,14 +154,14 @@ QueryResult_AutoPtr SqlQueryHolder::GetResult(size_t index)
|
||||
return QueryResult_AutoPtr(NULL);
|
||||
}
|
||||
|
||||
void SqlQueryHolder::SetResult(size_t index, QueryResult_AutoPtr result)
|
||||
void SQLQueryHolder::SetResult(size_t index, QueryResult_AutoPtr result)
|
||||
{
|
||||
/// store the result in the holder
|
||||
if (index < m_queries.size())
|
||||
m_queries[index].second = result;
|
||||
}
|
||||
|
||||
SqlQueryHolder::~SqlQueryHolder()
|
||||
SQLQueryHolder::~SQLQueryHolder()
|
||||
{
|
||||
for (size_t i = 0; i < m_queries.size(); i++)
|
||||
{
|
||||
@@ -183,27 +172,41 @@ SqlQueryHolder::~SqlQueryHolder()
|
||||
}
|
||||
}
|
||||
|
||||
void SqlQueryHolder::SetSize(size_t size)
|
||||
void SQLQueryHolder::SetSize(size_t size)
|
||||
{
|
||||
/// to optimize push_back, reserve the number of queries about to be executed
|
||||
m_queries.resize(size);
|
||||
}
|
||||
|
||||
void SqlQueryHolderEx::Execute(Database *db)
|
||||
bool SQLQueryHolderTask::Execute()
|
||||
{
|
||||
if (!m_holder || !m_callback || !m_queue)
|
||||
return;
|
||||
return false;
|
||||
|
||||
/// we can do this, we are friends
|
||||
std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries;
|
||||
std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries;
|
||||
|
||||
for (size_t i = 0; i < queries.size(); i++)
|
||||
{
|
||||
/// execute all queries in the holder and pass the results
|
||||
char const *sql = queries[i].first;
|
||||
if(sql) m_holder->SetResult(i, db->Query(sql));
|
||||
if (sql)
|
||||
m_holder->SetResult(i, m_conn->Query(sql));
|
||||
}
|
||||
|
||||
/// sync with the caller thread
|
||||
m_queue->add(m_callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SQLQueryTask::Execute()
|
||||
{
|
||||
if (!m_callback || !m_queue)
|
||||
return false;
|
||||
|
||||
/// execute the query and store the result in the callback
|
||||
m_callback->SetResult(m_conn->Query(m_sql));
|
||||
/// add the callback to the sql result queue of the thread it originated from
|
||||
m_queue->add(m_callback);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SQLOPERATION_H
|
||||
#define _SQLOPERATION_H
|
||||
|
||||
#include <ace/Method_Request.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Threading/Callback.h"
|
||||
|
||||
class MySQLConnection;
|
||||
|
||||
class SQLOperation : public ACE_Method_Request
|
||||
{
|
||||
public:
|
||||
SQLOperation(){};
|
||||
int call()
|
||||
{
|
||||
Execute();
|
||||
return 0;
|
||||
}
|
||||
virtual bool Execute() = 0;
|
||||
|
||||
virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
|
||||
|
||||
MySQLConnection* m_conn;
|
||||
};
|
||||
|
||||
/*! Raw, ad-hoc query. */
|
||||
class BasicStatementTask : public SQLOperation
|
||||
{
|
||||
public:
|
||||
BasicStatementTask(const char* sql);
|
||||
~BasicStatementTask();
|
||||
|
||||
bool Execute();
|
||||
|
||||
private:
|
||||
const char* m_sql; //- Raw query to be executed
|
||||
};
|
||||
|
||||
/*! Transactions */
|
||||
class TransactionTask : public SQLOperation
|
||||
{
|
||||
public:
|
||||
TransactionTask();
|
||||
~TransactionTask();
|
||||
void ForcefulDelete();
|
||||
|
||||
bool Execute();
|
||||
|
||||
private:
|
||||
std::queue<char*> m_queries;
|
||||
};
|
||||
|
||||
/*! ResultQueue */
|
||||
class SQLResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex>
|
||||
{
|
||||
public:
|
||||
SQLResultQueue() {}
|
||||
void Update();
|
||||
};
|
||||
|
||||
class SQLQueryHolder
|
||||
{
|
||||
friend class SQLQueryHolderTask;
|
||||
private:
|
||||
typedef std::pair<const char*, QueryResult_AutoPtr> SQLResultPair;
|
||||
std::vector<SQLResultPair> m_queries;
|
||||
public:
|
||||
SQLQueryHolder() {}
|
||||
~SQLQueryHolder();
|
||||
bool SetQuery(size_t index, const char *sql);
|
||||
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4);
|
||||
void SetSize(size_t size);
|
||||
QueryResult_AutoPtr GetResult(size_t index);
|
||||
void SetResult(size_t index, QueryResult_AutoPtr result);
|
||||
};
|
||||
|
||||
class SQLQueryHolderTask : public SQLOperation
|
||||
{
|
||||
private:
|
||||
SQLQueryHolder * m_holder;
|
||||
Trinity::IQueryCallback * m_callback;
|
||||
SQLResultQueue * m_queue;
|
||||
public:
|
||||
SQLQueryHolderTask(SQLQueryHolder *holder, Trinity::IQueryCallback * callback, SQLResultQueue * queue)
|
||||
: m_holder(holder), m_callback(callback), m_queue(queue) {}
|
||||
bool Execute();
|
||||
};
|
||||
|
||||
class SQLQueryTask : public SQLOperation
|
||||
{
|
||||
private:
|
||||
const char *m_sql;
|
||||
Trinity::IQueryCallback * m_callback;
|
||||
SQLResultQueue * m_queue;
|
||||
public:
|
||||
SQLQueryTask(const char *sql, Trinity::IQueryCallback * callback, SQLResultQueue * queue)
|
||||
: m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
|
||||
~SQLQueryTask() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
|
||||
bool Execute();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "SQLStorage.h"
|
||||
#include "SQLStorageImpl.h"
|
||||
|
||||
extern Database WorldDatabase;
|
||||
extern DatabaseType WorldDatabase;
|
||||
|
||||
const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiisi";
|
||||
const char CreatureInfodstfmt[]="iiiiiiiiiisssibbiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiiii";
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __SQLOPERATIONS_H
|
||||
#define __SQLOPERATIONS_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "ace/Thread_Mutex.h"
|
||||
#include "ace/Method_Request.h"
|
||||
#include "Threading/LockedQueue.h"
|
||||
#include <queue>
|
||||
#include "Threading/Callback.h"
|
||||
#include "QueryResult.h"
|
||||
|
||||
/// ---- BASE ---
|
||||
|
||||
class Database;
|
||||
class SqlDelayThread;
|
||||
|
||||
class SqlOperation
|
||||
{
|
||||
public:
|
||||
virtual void OnRemove() { delete this; }
|
||||
virtual void Execute(Database *db) = 0;
|
||||
virtual ~SqlOperation() {}
|
||||
};
|
||||
|
||||
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
|
||||
|
||||
class SqlStatement : public SqlOperation
|
||||
{
|
||||
private:
|
||||
const char *m_sql;
|
||||
public:
|
||||
SqlStatement(const char *sql) : m_sql(strdup(sql)){}
|
||||
~SqlStatement() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
class SqlTransaction : public SqlOperation
|
||||
{
|
||||
private:
|
||||
std::queue<const char*> m_queue;
|
||||
ACE_Thread_Mutex m_Mutex;
|
||||
public:
|
||||
SqlTransaction() {}
|
||||
void DelayExecute(const char *sql)
|
||||
{
|
||||
m_Mutex.acquire();
|
||||
char* _sql = strdup(sql);
|
||||
if (_sql)
|
||||
m_queue.push(_sql);
|
||||
m_Mutex.release();
|
||||
}
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
/// ---- ASYNC QUERIES ----
|
||||
|
||||
class SqlQuery; /// contains a single async query
|
||||
class QueryResult; /// the result of one
|
||||
class SqlResultQueue; /// queue for thread sync
|
||||
class SqlQueryHolder; /// groups several async quries
|
||||
class SqlQueryHolderEx; /// points to a holder, added to the delay thread
|
||||
|
||||
class SqlResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex>
|
||||
{
|
||||
public:
|
||||
SqlResultQueue() {}
|
||||
void Update();
|
||||
};
|
||||
|
||||
class SqlQuery : public SqlOperation
|
||||
{
|
||||
private:
|
||||
const char *m_sql;
|
||||
Trinity::IQueryCallback * m_callback;
|
||||
SqlResultQueue * m_queue;
|
||||
public:
|
||||
SqlQuery(const char *sql, Trinity::IQueryCallback * callback, SqlResultQueue * queue)
|
||||
: m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
|
||||
~SqlQuery() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
class SqlQueryHolder
|
||||
{
|
||||
friend class SqlQueryHolderEx;
|
||||
private:
|
||||
typedef std::pair<const char*, QueryResult_AutoPtr> SqlResultPair;
|
||||
std::vector<SqlResultPair> m_queries;
|
||||
public:
|
||||
SqlQueryHolder() {}
|
||||
~SqlQueryHolder();
|
||||
bool SetQuery(size_t index, const char *sql);
|
||||
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4);
|
||||
void SetSize(size_t size);
|
||||
QueryResult_AutoPtr GetResult(size_t index);
|
||||
void SetResult(size_t index, QueryResult_AutoPtr result);
|
||||
bool Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue);
|
||||
};
|
||||
|
||||
class SqlQueryHolderEx : public SqlOperation
|
||||
{
|
||||
private:
|
||||
SqlQueryHolder * m_holder;
|
||||
Trinity::IQueryCallback * m_callback;
|
||||
SqlResultQueue * m_queue;
|
||||
public:
|
||||
SqlQueryHolderEx(SqlQueryHolder *holder, Trinity::IQueryCallback * callback, SqlResultQueue * queue)
|
||||
: m_holder(holder), m_callback(callback), m_queue(queue) {}
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
class SqlAsyncTask : public ACE_Method_Request
|
||||
{
|
||||
public:
|
||||
SqlAsyncTask(Database * db, SqlOperation * op) : m_db(db), m_op(op){}
|
||||
~SqlAsyncTask()
|
||||
{
|
||||
if (!m_op)
|
||||
return;
|
||||
|
||||
delete m_op;
|
||||
m_op = NULL;
|
||||
}
|
||||
|
||||
int call()
|
||||
{
|
||||
if (m_db == NULL || m_op == NULL)
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
m_op->Execute(m_db);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Database * m_db;
|
||||
SqlOperation * m_op;
|
||||
};
|
||||
#endif //__SQLOPERATIONS_H
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Threading/Threading.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Database/SqlDelayThread.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
#include "Database/DatabaseWorker.h"
|
||||
#include "Database/SQLOperation.h"
|
||||
#include "Debugging/Errors.h"
|
||||
#include "Dynamic/TypeList.h"
|
||||
#include "Dynamic/UnorderedMap.h"
|
||||
|
||||
@@ -690,8 +690,28 @@ int kb_hit_return()
|
||||
/// %Thread start
|
||||
void CliRunnable::run()
|
||||
{
|
||||
///- Init new SQL thread for the world database (one connection call enough)
|
||||
WorldDatabase.ThreadStart(); // let thread do safe mySQL requests
|
||||
///- Init MySQL threads or connections
|
||||
bool needInit = true;
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_WORLDDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
WorldDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
LoginDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
CharacterDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (needInit)
|
||||
MySQL::Thread_Init();
|
||||
|
||||
char commandbuf[256];
|
||||
|
||||
@@ -759,6 +779,14 @@ void CliRunnable::run()
|
||||
|
||||
}
|
||||
|
||||
///- End the database thread
|
||||
WorldDatabase.ThreadEnd(); // free mySQL thread resources
|
||||
///- Free MySQL thread resources and deallocate lingering connections
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_WORLDDB) & MYSQL_BUNDLE_RA))
|
||||
WorldDatabase.End_MySQL_Connection();
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
LoginDatabase.End_MySQL_Connection();
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
CharacterDatabase.End_MySQL_Connection();
|
||||
if (needInit)
|
||||
MySQL::Thread_End();
|
||||
}
|
||||
|
||||
@@ -370,9 +370,9 @@ int Master::Run()
|
||||
clearOnlineAccounts();
|
||||
|
||||
///- Wait for delay threads to end
|
||||
CharacterDatabase.HaltDelayThread();
|
||||
WorldDatabase.HaltDelayThread();
|
||||
LoginDatabase.HaltDelayThread();
|
||||
CharacterDatabase.Close();
|
||||
WorldDatabase.Close();
|
||||
LoginDatabase.Close();
|
||||
|
||||
sLog.outString( "Halting process..." );
|
||||
|
||||
@@ -439,8 +439,8 @@ bool Master::_StartDB()
|
||||
{
|
||||
sLog.SetLogDB(false);
|
||||
std::string dbstring;
|
||||
uint8 num_threads;
|
||||
|
||||
///- Get world database info from configuration file
|
||||
dbstring = sConfig.GetStringDefault("WorldDatabaseInfo", "");
|
||||
if (dbstring.empty())
|
||||
{
|
||||
@@ -448,13 +448,20 @@ bool Master::_StartDB()
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the world database
|
||||
if( !WorldDatabase.Initialize(dbstring.c_str()))
|
||||
num_threads = sConfig.GetIntDefault("WorldDatabase.WorkerThreads", 1);
|
||||
if (num_threads < 1 || num_threads > 32)
|
||||
{
|
||||
sLog.outError("Cannot connect to world database %s",dbstring.c_str());
|
||||
sLog.outError("World database: invalid number of worker threads specified. "
|
||||
"Please pick a value between 1 and 32.");
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the world database
|
||||
if (!WorldDatabase.Open(dbstring, num_threads))
|
||||
{
|
||||
sLog.outError("Cannot connect to world database %s", dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
///- Get character database info from configuration file
|
||||
dbstring = sConfig.GetStringDefault("CharacterDatabaseInfo", "");
|
||||
if (dbstring.empty())
|
||||
@@ -463,13 +470,20 @@ bool Master::_StartDB()
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the Character database
|
||||
if (!CharacterDatabase.Initialize(dbstring.c_str()))
|
||||
num_threads = sConfig.GetIntDefault("CharacterDatabase.WorkerThreads", 1);
|
||||
if (num_threads < 1 || num_threads > 32)
|
||||
{
|
||||
sLog.outError("Cannot connect to Character database %s",dbstring.c_str());
|
||||
sLog.outError("Character database: invalid number of worker threads specified. "
|
||||
"Please pick a value between 1 and 32.");
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the Character database
|
||||
if (!CharacterDatabase.Open(dbstring, num_threads))
|
||||
{
|
||||
sLog.outError("Cannot connect to Character database %s", dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
///- Get login database info from configuration file
|
||||
dbstring = sConfig.GetStringDefault("LoginDatabaseInfo", "");
|
||||
if (dbstring.empty())
|
||||
@@ -478,13 +492,20 @@ bool Master::_StartDB()
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the login database
|
||||
if (!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
num_threads = sConfig.GetIntDefault("LoginDatabase.WorkerThreads", 1);
|
||||
if (num_threads < 1 || num_threads > 32)
|
||||
{
|
||||
sLog.outError("Cannot connect to login database %s",dbstring.c_str());
|
||||
sLog.outError("Login database: invalid number of worker threads specified. "
|
||||
"Please pick a value between 1 and 32.");
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Initialise the login database
|
||||
if (!LoginDatabase.Open(dbstring, num_threads))
|
||||
{
|
||||
sLog.outError("Cannot connect to login database %s", dbstring.c_str());
|
||||
return false;
|
||||
}
|
||||
///- Get the realm Id from the configuration file
|
||||
realmID = sConfig.GetIntDefault("RealmID", 0);
|
||||
if (!realmID)
|
||||
|
||||
@@ -43,8 +43,27 @@ extern int m_ServiceStatus;
|
||||
/// Heartbeat for the World
|
||||
void WorldRunnable::run()
|
||||
{
|
||||
///- Init new SQL thread for the world database
|
||||
WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough)
|
||||
///- Init MySQL threads or connections
|
||||
bool needInit = true;
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_WORLDDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
WorldDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
LoginDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
{
|
||||
CharacterDatabase.Init_MySQL_Connection();
|
||||
needInit = false;
|
||||
}
|
||||
|
||||
if (needInit)
|
||||
MySQL::Thread_Init();
|
||||
|
||||
sWorld.InitResultQueue();
|
||||
|
||||
@@ -99,6 +118,16 @@ void WorldRunnable::run()
|
||||
|
||||
sMapMgr.UnloadAll(); // unload all grids (including locked in memory)
|
||||
|
||||
///- End the database thread
|
||||
WorldDatabase.ThreadEnd(); // free mySQL thread resources
|
||||
///- Free MySQL thread resources and deallocate lingering connections
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_WORLDDB) & MYSQL_BUNDLE_RA))
|
||||
WorldDatabase.End_MySQL_Connection();
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_LOGINDB) & MYSQL_BUNDLE_RA))
|
||||
LoginDatabase.End_MySQL_Connection();
|
||||
|
||||
if (!(sWorld.getConfig(CONFIG_MYSQL_BUNDLE_CHARDB) & MYSQL_BUNDLE_RA))
|
||||
CharacterDatabase.End_MySQL_Connection();
|
||||
|
||||
if (needInit)
|
||||
MySQL::Thread_End();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,30 @@
|
||||
# .;/path/to/unix_socket;username;password;database
|
||||
# - use Unix sockets in Unix/Linux
|
||||
#
|
||||
# LoginDatabase.WorkerThreads
|
||||
# WorldDatabase.WorkerThreads
|
||||
# CharacterDatabase.WorkerThreads
|
||||
# The amount of worker threads spawned to handle
|
||||
# asynchroneous 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
|
||||
#
|
||||
# MaxPingTime
|
||||
# Settings for maximum database-ping interval (minutes between pings)
|
||||
#
|
||||
@@ -53,6 +77,12 @@ LogsDir = ""
|
||||
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
|
||||
WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world"
|
||||
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
|
||||
MaxPingTime = 30
|
||||
WorldServerPort = 8085
|
||||
BindIP = "0.0.0.0"
|
||||
|
||||
Reference in New Issue
Block a user