diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 102 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/MiscHandler.cpp | 48 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/QueryHandler.cpp | 43 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.cpp | 62 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 19 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 39 | ||||
-rw-r--r-- | src/server/game/World/World.h | 10 | ||||
-rw-r--r-- | src/server/shared/Database/AsyncDatabaseImpl.h | 250 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.cpp | 26 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.h | 53 | ||||
-rw-r--r-- | src/server/shared/Database/SQLOperation.cpp | 48 | ||||
-rw-r--r-- | src/server/shared/Database/SQLOperation.h | 33 | ||||
-rw-r--r-- | src/server/shared/Threading/Callback.h | 427 | ||||
-rw-r--r-- | src/server/worldserver/WorldThread/WorldRunnable.cpp | 2 |
15 files changed, 302 insertions, 861 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index cb67ceef630..8d23f9a472c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -59,7 +59,6 @@ #include "OutdoorPvPMgr.h" #include "ArenaTeam.h" #include "Chat.h" -#include "AsyncDatabaseImpl.h" #include "Spell.h" #include "SocialMgr.h" #include "GameEventMgr.h" diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 2a764a366e8..01c1392f35b 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -27,7 +27,6 @@ #include "WorldSession.h" #include "MD5.h" #include "DatabaseEnv.h" -#include "AsyncDatabaseImpl.h" #include "ArenaTeam.h" #include "Chat.h" @@ -103,33 +102,6 @@ bool LoginQueryHolder::Initialize() return res; } -// don't call WorldSession directly -// it may get deleted before the query callbacks get executed -// instead pass an account id to this handler -class CharacterHandler -{ - - public: - void HandleCharEnumCallback(QueryResult_AutoPtr result, uint32 account) - { - WorldSession * session = sWorld.FindSession(account); - if (!session) - return; - session->HandleCharEnum(result); - } - void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SQLQueryHolder * holder) - { - if (!holder) return; - WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId()); - if (!session) - { - delete holder; - return; - } - session->HandlePlayerLogin((LoginQueryHolder*)holder); - } -} chrHandler; - void WorldSession::HandleCharEnum(QueryResult_AutoPtr result) { WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size @@ -158,31 +130,33 @@ void WorldSession::HandleCharEnum(QueryResult_AutoPtr result) void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) { /// get all the data necessary for loading all characters (along with their pets) on the account - CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(), - !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? - // ------- Query Without Declined Names -------- - // 0 1 2 3 4 5 6 7 - "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " - // 8 9 10 11 12 13 14 - "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " - "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " - "LEFT JOIN guild_member ON characters.guid = guild_member.guid " - "WHERE characters.account = '%u' ORDER BY characters.guid" - : - // --------- Query With Declined Names --------- - // 0 1 2 3 4 5 6 7 - "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " - // 8 9 10 11 12 13 14 - "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " - "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " - "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " - "LEFT JOIN guild_member ON characters.guid = guild_member.guid " - "WHERE characters.account = '%u' ORDER BY characters.guid", - PET_SAVE_AS_CURRENT,GetAccountId()); + m_charEnumCallback = + CharacterDatabase.AsyncPQuery( + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 3 4 5 6 7 + "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " + // 8 9 10 11 12 13 14 + "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " + // 15 16 17 18 19 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " + "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " + "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "WHERE characters.account = '%u' ORDER BY characters.guid" + : + // --------- Query With Declined Names --------- + // 0 1 2 3 4 5 6 7 + "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " + // 8 9 10 11 12 13 14 + "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " + // 15 16 17 18 19 20 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " + "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " + "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " + "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "WHERE characters.account = '%u' ORDER BY characters.guid", + PET_SAVE_AS_CURRENT, GetAccountId() + ); } void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) @@ -565,7 +539,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) return; } - CharacterDatabase.DelayQueryHolder(&chrHandler, &CharacterHandler::HandlePlayerLoginCallback, holder); + m_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); } void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) @@ -957,24 +931,22 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) // make sure that the character belongs to the current account, that rename at login is enabled // and that there is no character with the desired new name - CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, - GetAccountId(), newname, + m_charRenameCallback.SetParam(newname); + m_charRenameCallback.SetFutureResult( + CharacterDatabase.AsyncPQuery( "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() -); + ) + ); } -void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname) +void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, std::string newname) { - WorldSession * session = sWorld.FindSession(accountId); - if (!session) - return; - if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << uint8(CHAR_CREATE_ERROR); - session->SendPacket(&data); + SendPacket(&data); return; } @@ -985,13 +957,13 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr resu CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow); - sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); data << uint8(RESPONSE_SUCCESS); data << uint64(guid); data << newname; - session->SendPacket(&data); + SendPacket(&data); } void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp index 79e3374c975..5d5ffc39417 100644 --- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp @@ -21,7 +21,6 @@ #include "Common.h" #include "Language.h" #include "DatabaseEnv.h" -#include "AsyncDatabaseImpl.h" #include "WorldPacket.h" #include "Opcodes.h" #include "Log.h" @@ -554,21 +553,19 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data) sLog.outDebug("WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName(), friendName.c_str()); - CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str()); + m_addFriendCallback.SetParam(friendNote); + m_addFriendCallback.SetFutureResult( + CharacterDatabase.AsyncPQuery("SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str()) + ); } -void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote) +void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, std::string friendNote) { uint64 friendGuid; uint64 friendAcctid; uint32 team; FriendsResult friendResult; - WorldSession * session = sWorld.FindSession(accountId); - - if (!session || !session->GetPlayer()) - return; - friendResult = FRIEND_NOT_FOUND; friendGuid = 0; @@ -578,35 +575,35 @@ void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uin team = Player::TeamForRace((*result)[1].GetUInt8()); friendAcctid = (*result)[2].GetUInt32(); - if (session->GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || sAccountMgr.GetSecurity(friendAcctid) < SEC_MODERATOR) + if (GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || sAccountMgr.GetSecurity(friendAcctid) < SEC_MODERATOR) { if (friendGuid) { - if (friendGuid == session->GetPlayer()->GetGUID()) + if (friendGuid == GetPlayer()->GetGUID()) friendResult = FRIEND_SELF; - else if (session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR) + else if (GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && GetSecurity() < SEC_MODERATOR) friendResult = FRIEND_ENEMY; - else if (session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) + else if (GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) friendResult = FRIEND_ALREADY; else { Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); - if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer())) + if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) friendResult = FRIEND_ADDED_ONLINE; else friendResult = FRIEND_ADDED_OFFLINE; - if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) + if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) { friendResult = FRIEND_LIST_FULL; - sLog.outDebug("WORLD: %s's friend list is full.", session->GetPlayer()->GetName()); + sLog.outDebug("WORLD: %s's friend list is full.", GetPlayer()->GetName()); } } - session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); + GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); } } } - sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); + sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); } @@ -642,19 +639,14 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data) sLog.outDebug("WORLD: %s asked to Ignore: '%s'", GetPlayer()->GetName(), IgnoreName.c_str()); - CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); + m_addIgnoreCallback = CharacterDatabase.AsyncPQuery("SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); } -void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId) +void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result) { uint64 IgnoreGuid; FriendsResult ignoreResult; - WorldSession * session = sWorld.FindSession(accountId); - - if (!session || !session->GetPlayer()) - return; - ignoreResult = FRIEND_IGNORE_NOT_FOUND; IgnoreGuid = 0; @@ -664,22 +656,22 @@ void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uin if (IgnoreGuid) { - if (IgnoreGuid == session->GetPlayer()->GetGUID()) //not add yourself + if (IgnoreGuid == GetPlayer()->GetGUID()) //not add yourself ignoreResult = FRIEND_IGNORE_SELF; - else if (session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid))) + else if (GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid))) ignoreResult = FRIEND_IGNORE_ALREADY; else { ignoreResult = FRIEND_IGNORE_ADDED; // ignore list full - if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) + if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) ignoreResult = FRIEND_IGNORE_FULL; } } } - sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); + sSocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); } diff --git a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp index 7cb60435d69..a830ff09ed6 100644 --- a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp @@ -21,7 +21,6 @@ #include "Common.h" #include "Language.h" #include "DatabaseEnv.h" -#include "AsyncDatabaseImpl.h" #include "WorldPacket.h" #include "WorldSession.h" #include "Opcodes.h" @@ -61,37 +60,37 @@ void WorldSession::SendNameQueryOpcode(Player *p) void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid) { - CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(), - !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? - // ------- Query Without Declined Names -------- - // 0 1 2 3 4 - "SELECT guid, name, race, gender, class " - "FROM characters WHERE guid = '%u'" - : - // --------- Query With Declined Names --------- - // 0 1 2 3 4 - "SELECT characters.guid, name, race, gender, class, " - // 5 6 7 8 9 - "genitive, dative, accusative, instrumental, prepositional " - "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'", - GUID_LOPART(guid)); + m_nameQueryCallbacks.insert( + CharacterDatabase.AsyncPQuery( + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 3 4 + "SELECT guid, name, race, gender, class " + "FROM characters WHERE guid = '%u'" + : + // --------- Query With Declined Names --------- + // 0 1 2 3 4 + "SELECT characters.guid, name, race, gender, class, " + // 5 6 7 8 9 + "genitive, dative, accusative, instrumental, prepositional " + "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'", + GUID_LOPART(guid)) + ); + +// CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(), } -void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId) +void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result) { if (!result) return; - WorldSession * session = sWorld.FindSession(accountId); - if (!session) - return; - Field *fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); std::string name = fields[1].GetCppString(); uint8 pRace = 0, pGender = 0, pClass = 0; if (name == "") - name = session->GetTrinityString(LANG_NON_EXIST_CHARACTER); + name = GetTrinityString(LANG_NON_EXIST_CHARACTER); else { pRace = fields[2].GetUInt8(); @@ -118,7 +117,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, else data << uint8(0); // is not declined - session->SendPacket(&data); + SendPacket(&data); } void WorldSession::HandleNameQueryOpcode(WorldPacket & recv_data) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index fc63e2b6e75..9dc27b07a85 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -290,6 +290,8 @@ bool WorldSession::Update(uint32 diff) delete packet; } + ProcessQueryCallbacks(); + time_t currTime = time(NULL); ///- If necessary, log the player out if (ShouldLogOut(currTime) && !m_playerLoading) @@ -955,3 +957,63 @@ void WorldSession::SetPlayer(Player *plr) if (_player) m_GUIDLow = _player->GetGUIDLow(); } + +void WorldSession::ProcessQueryCallbacks() +{ + QueryResult_AutoPtr result; + + //! HandleNameQueryOpcode + while (!m_nameQueryCallbacks.is_empty()) + { + QueryResultFuture lResult; + ACE_Time_Value timeout = ACE_Time_Value::zero; + if (m_nameQueryCallbacks.next_readable(lResult, &timeout) != 1) + break; + + lResult.get(result); + SendNameQueryOpcodeFromDBCallBack(result); + } + + //! HandleCharEnumOpcode + if (m_charEnumCallback.ready()) + { + m_charEnumCallback.get(result); + HandleCharEnum(result); + m_charEnumCallback.cancel(); + } + + //! HandlePlayerLoginOpcode + if (m_charLoginCallback.ready()) + { + SQLQueryHolder* param; + m_charLoginCallback.get(param); + HandlePlayerLogin((LoginQueryHolder*)param); + m_charLoginCallback.cancel(); + } + + //! HandleAddFriendOpcode + if (m_addFriendCallback.IsReady()) + { + std::string& param = m_addFriendCallback.GetParam(); + m_addFriendCallback.GetResult(result); + HandleAddFriendOpcodeCallBack(result, param); + m_addFriendCallback.FreeResult(); + } + + //- HandleCharRenameOpcode + if (m_charRenameCallback.IsReady()) + { + std::string& param = m_charRenameCallback.GetParam(); + m_charRenameCallback.GetResult(result); + HandleChangePlayerNameOpcodeCallBack(result, param); + m_charRenameCallback.FreeResult(); + } + + //- HandleCharAddIgnoreOpcode + if (m_addIgnoreCallback.ready()) + { + m_addIgnoreCallback.get(result); + HandleAddIgnoreOpcodeCallBack(result); + m_addIgnoreCallback.cancel(); + } +}
\ No newline at end of file diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 7251e900ae0..a8578056d5a 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -192,7 +192,7 @@ class WorldSession //void SendTestCreatureQueryOpcode(uint32 entry, uint64 guid, uint32 testvalue); void SendNameQueryOpcode(Player* p); void SendNameQueryOpcodeFromDB(uint64 guid); - static void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId); + void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result); void SendTrainerList(uint64 guid); void SendTrainerList(uint64 guid, const std::string& strTitle); @@ -389,10 +389,10 @@ class WorldSession void HandleEmoteOpcode(WorldPacket& recvPacket); void HandleContactListOpcode(WorldPacket& recvPacket); void HandleAddFriendOpcode(WorldPacket& recvPacket); - static void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote); + void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, std::string friendNote); void HandleDelFriendOpcode(WorldPacket& recvPacket); void HandleAddIgnoreOpcode(WorldPacket& recvPacket); - static void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId); + void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result); void HandleDelIgnoreOpcode(WorldPacket& recvPacket); void HandleSetContactNotesOpcode(WorldPacket& recvPacket); void HandleBugOpcode(WorldPacket& recvPacket); @@ -665,7 +665,7 @@ class WorldSession void HandleSetActionBarToggles(WorldPacket& recv_data); void HandleCharRenameOpcode(WorldPacket& recv_data); - static void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname); + void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, std::string newname); void HandleSetPlayerDeclinedNames(WorldPacket& recv_data); void HandleTotemDestroyed(WorldPacket& recv_data); @@ -798,6 +798,17 @@ class WorldSession void HandleQuestPOIQuery(WorldPacket& recv_data); void HandleEjectPasenger(WorldPacket &data); void HandleEnterPlayerVehicle(WorldPacket &data); + + private: + void ProcessQueryCallbacks(); + + QueryResultFutureSet m_nameQueryCallbacks; + QueryResultFuture m_charEnumCallback; + QueryResultFuture m_addIgnoreCallback; + QueryCallback<std::string> m_charRenameCallback; + QueryCallback<std::string> m_addFriendCallback; + QueryResultHolderFuture m_charLoginCallback; + private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a52d2a7d48e..c6db1e81d96 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -54,7 +54,6 @@ #include "VMapFactory.h" #include "GameEventMgr.h" #include "PoolMgr.h" -#include "AsyncDatabaseImpl.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "InstanceSaveMgr.h" @@ -103,7 +102,6 @@ World::World() m_maxQueuedSessionCount = 0; m_PlayerCount = 0; m_MaxPlayerCount = 0; - m_resultQueue = NULL; m_NextDailyQuestReset = 0; m_NextWeeklyQuestReset = 0; m_scheduledScripts = 0; @@ -134,8 +132,6 @@ World::~World() VMAP::VMapFactory::clear(); - delete m_resultQueue; - //TODO free addSessQueue } @@ -1979,8 +1975,8 @@ void World::Update(uint32 diff) RecordTimeDiff("UpdateLFGMgr"); // execute callbacks from sql queries that were queued recently - UpdateResultQueue(); - RecordTimeDiff("UpdateResultQueue"); + ProcessQueryCallbacks(); + RecordTimeDiff("ProcessQueryCallbacks"); ///- Erase corpses once every 20 minutes if (m_timers[WUPDATE_CORPSES].Passed()) @@ -2500,21 +2496,12 @@ void World::SendRNDBroadcast() } } -void World::InitResultQueue() -{ - m_resultQueue = new SQLResultQueue; - CharacterDatabase.SetResultQueue(m_resultQueue); -} - -void World::UpdateResultQueue() -{ - m_resultQueue->Update(); -} - void World::UpdateRealmCharCount(uint32 accountId) { - CharacterDatabase.AsyncPQuery(this, &World::_UpdateRealmCharCount, accountId, - "SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId); + m_realmCharCallback.SetParam(accountId); + m_realmCharCallback.SetFutureResult( + LoginDatabase.AsyncPQuery("SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId) + ); } void World::_UpdateRealmCharCount(QueryResult_AutoPtr resultCharCount, uint32 accountId) @@ -2742,3 +2729,17 @@ uint64 World::getWorldState(uint32 index) const WorldStatesMap::const_iterator it = m_worldstates.find(index); return it != m_worldstates.end() ? it->second : 0; } + +void World::ProcessQueryCallbacks() +{ + QueryResult_AutoPtr result; + + //-UpdateRealmCharCount + if (m_realmCharCallback.IsReady()) + { + uint32 param = m_realmCharCallback.GetParam(); + m_realmCharCallback.GetResult(result); + _UpdateRealmCharCount(result, param); + m_realmCharCallback.FreeResult(); + } +}
\ No newline at end of file diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 2ade43c26a9..74993e6b30a 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -31,6 +31,7 @@ #include "SharedDefines.h" #include "ace/Atomic_Op.h" #include "QueryResult.h" +#include "Callback.h" #include <map> #include <set> @@ -42,7 +43,6 @@ class WorldSession; class Player; struct ScriptAction; struct ScriptInfo; -class SQLResultQueue; class QueryResult; class WorldSocket; class SystemMgr; @@ -670,9 +670,6 @@ class World void ProcessCliCommands(); void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); } - void UpdateResultQueue(); - void InitResultQueue(); - void ForceGameEventUpdate(); void UpdateRealmCharCount(uint32 accid); @@ -768,7 +765,6 @@ class World // CLI command holder to be thread safe ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue; - SQLResultQueue *m_resultQueue; // next daily quests and random bg reset time time_t m_NextDailyQuestReset; @@ -787,6 +783,10 @@ class World std::string m_CreatureEventAIVersion; std::list<std::string> m_Autobroadcasts; + + private: + void ProcessQueryCallbacks(); + QueryCallback<uint32> m_realmCharCallback; }; extern uint32 realmID; diff --git a/src/server/shared/Database/AsyncDatabaseImpl.h b/src/server/shared/Database/AsyncDatabaseImpl.h deleted file mode 100644 index 39a5e6551d5..00000000000 --- a/src/server/shared/Database/AsyncDatabaseImpl.h +++ /dev/null @@ -1,250 +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 "DatabaseWorkerPool.h" -#include "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 diff --git a/src/server/shared/Database/DatabaseWorkerPool.cpp b/src/server/shared/Database/DatabaseWorkerPool.cpp index 849fd67d8c0..2e50f6bf8fa 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.cpp +++ b/src/server/shared/Database/DatabaseWorkerPool.cpp @@ -197,6 +197,32 @@ void DatabaseWorkerPool::CommitTransaction() } } +QueryResultFuture DatabaseWorkerPool::AsyncQuery(const char* sql) +{ + QueryResultFuture res; + BasicStatementTask* task = new BasicStatementTask(sql, res); + Enqueue(task); + return res; //! Fool compiler, has no use yet +} + +QueryResultFuture DatabaseWorkerPool::AsyncPQuery(const char* sql, ...) +{ + 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 AsyncQuery(szQuery); +} + +QueryResultHolderFuture DatabaseWorkerPool::DelayQueryHolder(SQLQueryHolder* holder) +{ + QueryResultHolderFuture res; + SQLQueryHolderTask* task = new SQLQueryHolderTask(holder, res); + Enqueue(task); + return res; //! Fool compiler, has no use yet +} MySQLConnection* DatabaseWorkerPool::GetConnection() { diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 06374e44143..c1c645e088e 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -26,6 +26,7 @@ #include "SQLOperation.h" #include "QueryResult.h" +#include "Callback.h" #include "MySQLConnection.h" enum MySQLThreadBundle @@ -56,52 +57,10 @@ class DatabaseWorkerPool 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; - } - + QueryResultFuture AsyncQuery(const char* sql); + QueryResultFuture AsyncPQuery(const char* sql, ...); + QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder); + void BeginTransaction(); void RollbackTransaction(); void CommitTransaction(); @@ -135,7 +94,6 @@ class DatabaseWorkerPool 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: @@ -149,7 +107,6 @@ class DatabaseWorkerPool 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 diff --git a/src/server/shared/Database/SQLOperation.cpp b/src/server/shared/Database/SQLOperation.cpp index c9e3ba3e937..35a61dc9518 100644 --- a/src/server/shared/Database/SQLOperation.cpp +++ b/src/server/shared/Database/SQLOperation.cpp @@ -21,7 +21,15 @@ #include "Log.h" /*! Basic, ad-hoc queries. */ -BasicStatementTask::BasicStatementTask(const char* sql) +BasicStatementTask::BasicStatementTask(const char* sql) : +m_has_result(false) +{ + m_sql = strdup(sql); +} + +BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) : +m_result(result), +m_has_result(true) { m_sql = strdup(sql); } @@ -33,6 +41,15 @@ BasicStatementTask::~BasicStatementTask() bool BasicStatementTask::Execute() { + if (m_has_result) + { + m_result.set( + m_conn->Query(m_sql) + ); + + return true; + } + return m_conn->Execute(m_sql); } @@ -83,18 +100,6 @@ bool TransactionTask::Execute() return true; } -/*! Callback statements/holders */ -void SQLResultQueue::Update() -{ - /// execute the callbacks waiting in the synchronization queue - Trinity::IQueryCallback* callback; - while (next(callback)) - { - callback->Execute(); - delete callback; - } -} - bool SQLQueryHolder::SetQuery(size_t index, const char *sql) { if (m_queries.size() <= index) @@ -181,7 +186,7 @@ void SQLQueryHolder::SetSize(size_t size) bool SQLQueryHolderTask::Execute() { - if (!m_holder || !m_callback || !m_queue) + if (!m_holder) return false; /// we can do this, we are friends @@ -195,19 +200,6 @@ bool SQLQueryHolderTask::Execute() 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); + m_result.set(m_holder); return true; } diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/shared/Database/SQLOperation.h index 4833e28164e..0bf08d3e3eb 100644 --- a/src/server/shared/Database/SQLOperation.h +++ b/src/server/shared/Database/SQLOperation.h @@ -43,17 +43,21 @@ class SQLOperation : public ACE_Method_Request MySQLConnection* m_conn; }; +typedef ACE_Future<QueryResult_AutoPtr> QueryResultFuture; /*! Raw, ad-hoc query. */ class BasicStatementTask : public SQLOperation { public: BasicStatementTask(const char* sql); + BasicStatementTask(const char* sql, QueryResultFuture result); ~BasicStatementTask(); bool Execute(); private: const char* m_sql; //- Raw query to be executed + bool m_has_result; + QueryResultFuture m_result; }; /*! Transactions */ @@ -70,14 +74,6 @@ class TransactionTask : public SQLOperation 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; @@ -94,28 +90,17 @@ class SQLQueryHolder void SetResult(size_t index, QueryResult_AutoPtr result); }; +typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture; + 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(); -}; + QueryResultHolderFuture m_result; -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); } + SQLQueryHolderTask(SQLQueryHolder *holder, QueryResultHolderFuture res) + : m_holder(holder), m_result(res){}; bool Execute(); }; diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h index d2e2c36851a..921741bbed4 100644 --- a/src/server/shared/Threading/Callback.h +++ b/src/server/shared/Threading/Callback.h @@ -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 @@ -10,377 +8,76 @@ * * 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 + * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITY_CALLBACK_H -#define TRINITY_CALLBACK_H - -/// ------------ BASE CLASSES ------------ - -namespace Trinity -{ - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class _Callback - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - ParamType4 m_param4; - void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} - _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb) - : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} - }; - - template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > - class _Callback < Class, ParamType1, ParamType2, ParamType3 > - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} - _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb) - : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class _Callback < Class, ParamType1, ParamType2 > - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - void _Execute() { (m_object->*m_method)(m_param1, m_param2); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} - _Callback(_Callback < Class, ParamType1, ParamType2 > const& cb) - : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} - }; - - template < class Class, typename ParamType1 > - class _Callback < Class, ParamType1 > - { - protected: - typedef void (Class::*Method)(ParamType1); - Class *m_object; - Method m_method; - ParamType1 m_param1; - void _Execute() { (m_object->*m_method)(m_param1); } - public: - _Callback(Class *object, Method method, ParamType1 param1) - : m_object(object), m_method(method), m_param1(param1) {} - _Callback(_Callback < Class, ParamType1 > const& cb) - : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1) {} - }; - - template < class Class > - class _Callback < Class > - { - protected: - typedef void (Class::*Method)(); - Class *m_object; - Method m_method; - void _Execute() { (m_object->*m_method)(); } - public: - _Callback(Class *object, Method method) - : m_object(object), m_method(method) {} - _Callback(_Callback < Class > const& cb) - : m_object(cb.m_object), m_method(cb.m_method) {} - }; - - /// ---- Statics ---- - - template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class _SCallback - { - protected: - typedef void (*Method)(ParamType1, ParamType2, ParamType3, ParamType4); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - ParamType4 m_param4; - void _Execute() { (*m_method)(m_param1, m_param2, m_param3, m_param4); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} - _SCallback(_SCallback < ParamType1, ParamType2, ParamType3, ParamType4> const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} - }; - - template < typename ParamType1, typename ParamType2, typename ParamType3 > - class _SCallback < ParamType1, ParamType2, ParamType3 > - { - protected: - typedef void (*Method)(ParamType1, ParamType2, ParamType3); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - void _Execute() { (*m_method)(m_param1, m_param2, m_param3); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3) {} - _SCallback(_SCallback < ParamType1, ParamType2, ParamType3 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} - }; - - template < typename ParamType1, typename ParamType2 > - class _SCallback < ParamType1, ParamType2 > - { - protected: - typedef void (*Method)(ParamType1, ParamType2); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - void _Execute() { (*m_method)(m_param1, m_param2); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2) - : m_method(method), m_param1(param1), m_param2(param2) {} - _SCallback(_SCallback < ParamType1, ParamType2 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} - }; - - template < typename ParamType1 > - class _SCallback < ParamType1 > - { - protected: - typedef void (*Method)(ParamType1); - Method m_method; - ParamType1 m_param1; - void _Execute() { (*m_method)(m_param1); } - public: - _SCallback(Method method, ParamType1 param1) - : m_method(method), m_param1(param1) {} - _SCallback(_SCallback < ParamType1 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1) {} - }; - - template < > - class _SCallback < > - { - protected: - typedef void (*Method)(); - Method m_method; - void _Execute() { (*m_method)(); } - public: - _SCallback(Method method) - : m_method(method) {} - _SCallback(_SCallback <> const& cb) - : m_method(cb.m_method) {} - }; -} - -/// --------- GENERIC CALLBACKS ---------- - -namespace Trinity -{ - class ICallback - { - public: - virtual void Execute() = 0; - virtual ~ICallback() {} - }; - - template < class CB > - class _ICallback : public CB, public ICallback - { - public: - _ICallback(CB const& cb) : CB(cb) {} - void Execute() { CB::_Execute(); } - }; - - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class Callback : - public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > C4; - public: - Callback(Class *object, typename C4::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : _ICallback< C4 >(C4(object, method, param1, param2, param3, param4)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > - class Callback < Class, ParamType1, ParamType2, ParamType3 > : - public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2, ParamType3 > C3; - public: - Callback(Class *object, typename C3::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _ICallback< C3 >(C3(object, method, param1, param2, param3)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class Callback < Class, ParamType1, ParamType2 > : - public _ICallback< _Callback < Class, ParamType1, ParamType2 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2 > C2; - public: - Callback(Class *object, typename C2::Method method, ParamType1 param1, ParamType2 param2) - : _ICallback< C2 >(C2(object, method, param1, param2)) {} - }; - - template < class Class, typename ParamType1 > - class Callback < Class, ParamType1 > : - public _ICallback< _Callback < Class, ParamType1 > > - { - private: - typedef _Callback < Class, ParamType1 > C1; - public: - Callback(Class *object, typename C1::Method method, ParamType1 param1) - : _ICallback< C1 >(C1(object, method, param1)) {} - }; +#ifndef _CALLBACK_H +#define _CALLBACK_H - template < class Class > - class Callback < Class > : public _ICallback< _Callback < Class > > - { - private: - typedef _Callback < Class > C0; - public: - Callback(Class *object, typename C0::Method method) - : _ICallback< C0 >(C0(object, method)) {} - }; -} +#include <ace/Future.h> +#include <ace/Future_Set.h> -/// ---------- QUERY CALLBACKS ----------- +#include "DatabaseEnv.h" -#include "QueryResult.h" -class QueryResult; +typedef ACE_Future<QueryResult_AutoPtr> QueryResultFuture; -namespace Trinity +/*! A simple template using ACE_Future to manage callbacks from the thread and object that + issued the request. <ParamType> is variable type of parameter that is used as parameter + for the callback function. +*/ +template <typename ParamType> +class QueryCallback { - class IQueryCallback - { - public: - virtual void Execute() = 0; - virtual ~IQueryCallback() {} - virtual void SetResult(QueryResult_AutoPtr result) = 0; - virtual QueryResult_AutoPtr GetResult() = 0; - }; - - template < class CB > - class _IQueryCallback : public CB, public IQueryCallback - { - public: - _IQueryCallback(CB const& cb) : CB(cb) {} - void Execute() { CB::_Execute(); } - void SetResult(QueryResult_AutoPtr result) { CB::m_param1 = result; } - QueryResult_AutoPtr GetResult() { return CB::m_param1; } - }; - - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > - class QueryCallback : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; - public: - QueryCallback(Class *object, typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class QueryCallback < Class, ParamType1, ParamType2 > : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; - public: - QueryCallback(Class *object, typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) - : _IQueryCallback< QC2 >(QC2(object, method, result, param1, param2)) {} - }; - - template < class Class, typename ParamType1 > - class QueryCallback < Class, ParamType1 > : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1 > QC1; - public: - QueryCallback(Class *object, typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) - : _IQueryCallback< QC1 >(QC1(object, method, result, param1)) {} - }; - - template < class Class > - class QueryCallback < Class > : public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr > QC0; - public: - QueryCallback(Class *object, typename QC0::Method method, QueryResult_AutoPtr result) - : _IQueryCallback< QC0 >(QC0(object, method, result)) {} - }; - - /// ---- Statics ---- - - template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > - class SQueryCallback : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; - public: - SQueryCallback(typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _IQueryCallback< QC3 >(QC3(method, result, param1, param2, param3)) {} - }; - - template < typename ParamType1, typename ParamType2 > - class SQueryCallback < ParamType1, ParamType2 > : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; - public: - SQueryCallback(typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) - : _IQueryCallback< QC2 >(QC2(method, result, param1, param2)) {} - }; - - template < typename ParamType1 > - class SQueryCallback < ParamType1 > : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1 > QC1; - public: - SQueryCallback(typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) - : _IQueryCallback< QC1 >(QC1(method, result, param1)) {} - }; - - template < > - class SQueryCallback < > : public _IQueryCallback< _SCallback < QueryResult_AutoPtr > > - { - private: - typedef _SCallback < QueryResult_AutoPtr > QC0; - public: - SQueryCallback(QC0::Method method, QueryResult_AutoPtr result) - : _IQueryCallback< QC0 >(QC0(method, result)) {} - }; -} - -#endif - + public: + QueryCallback() {} + + void SetFutureResult(QueryResultFuture value) + { + result = value; + } + + QueryResultFuture GetFutureResult() + { + return result; + } + + int IsReady() + { + return result.ready(); + } + + void GetResult(QueryResult_AutoPtr res) + { + result.get(res); + } + + void FreeResult() + { + result.cancel(); + } + + void SetParam(ParamType value) + { + param = value; + } + + ParamType GetParam() + { + return param; + } + + private: + QueryResultFuture result; + ParamType param; +}; + +/*! ACE_Future_Set to store a bunch of unique async queries with callbacks. + (ie name queries) +*/ +typedef ACE_Future_Set<QueryResult_AutoPtr> QueryResultFutureSet; +#endif
\ No newline at end of file diff --git a/src/server/worldserver/WorldThread/WorldRunnable.cpp b/src/server/worldserver/WorldThread/WorldRunnable.cpp index 555f174b6c8..7f29710c3e8 100644 --- a/src/server/worldserver/WorldThread/WorldRunnable.cpp +++ b/src/server/worldserver/WorldThread/WorldRunnable.cpp @@ -65,8 +65,6 @@ void WorldRunnable::run() if (needInit) MySQL::Thread_Init(); - sWorld.InitResultQueue(); - uint32 realCurrTime = 0; uint32 realPrevTime = getMSTime(); |