Skip to content

Commit

Permalink
fix(Core/AuctionHouse): Fix AH searches with high number of auctions (a…
Browse files Browse the repository at this point in the history
…zerothcore#13467)

Fix AH searches with high number of auctions
  • Loading branch information
MikaMauger committed Jun 27, 2023
1 parent cfc15ab commit 6edcf05
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 115 deletions.
65 changes: 27 additions & 38 deletions src/server/apps/worldserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ bool LoadRealmInfo(Acore::Asio::IoContext& ioContext);
AsyncAcceptor* StartRaSocketAcceptor(Acore::Asio::IoContext& ioContext);
void ShutdownCLIThread(std::thread* cliThread);
void AuctionListingRunnable();
void ShutdownAuctionListingThread(std::thread* thread);
void WorldUpdateLoop();
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& cfg_service);

Expand Down Expand Up @@ -398,9 +397,9 @@ int main(int argc, char** argv)
cliThread.reset(new std::thread(CliThread), &ShutdownCLIThread);
}

// Launch CliRunnable thread
std::shared_ptr<std::thread> auctionLisingThread;
auctionLisingThread.reset(new std::thread(AuctionListingRunnable),
// Launch auction listing thread
std::shared_ptr<std::thread> auctionListingThread;
auctionListingThread.reset(new std::thread(AuctionListingRunnable),
[](std::thread* thr)
{
thr->join();
Expand Down Expand Up @@ -717,42 +716,41 @@ void AuctionListingRunnable()

while (!World::IsStopped())
{
if (AsyncAuctionListingMgr::IsAuctionListingAllowed())
{
uint32 diff = AsyncAuctionListingMgr::GetDiff();
AsyncAuctionListingMgr::ResetDiff();
Milliseconds diff = AsyncAuctionListingMgr::GetDiff();
AsyncAuctionListingMgr::ResetDiff();

if (AsyncAuctionListingMgr::GetTempList().size() || AsyncAuctionListingMgr::GetList().size())
if (!AsyncAuctionListingMgr::GetTempList().empty() || !AsyncAuctionListingMgr::GetList().empty())
{
{
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock());
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());

{
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
for (auto const& delayEvent: AsyncAuctionListingMgr::GetTempList())
AsyncAuctionListingMgr::GetList().emplace_back(delayEvent);

for (auto const& delayEvent : AsyncAuctionListingMgr::GetTempList())
AsyncAuctionListingMgr::GetList().emplace_back(delayEvent);
AsyncAuctionListingMgr::GetTempList().clear();
}

AsyncAuctionListingMgr::GetTempList().clear();
for (auto& itr: AsyncAuctionListingMgr::GetList())
{
if (itr._pickupTimer <= diff)
{
itr._pickupTimer = Milliseconds::zero();
}

for (auto& itr : AsyncAuctionListingMgr::GetList())
else
{
if (itr._msTimer <= diff)
itr._msTimer = 0;
else
itr._msTimer -= diff;
itr._pickupTimer -= diff;
}
}

for (std::list<AuctionListItemsDelayEvent>::iterator itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr)
{
if ((*itr)._msTimer != 0)
continue;
for (auto itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr)
{
if ((*itr)._pickupTimer != Milliseconds::zero())
continue;

if ((*itr).Execute())
AsyncAuctionListingMgr::GetList().erase(itr);
if ((*itr).Execute())
AsyncAuctionListingMgr::GetList().erase(itr);

break;
}
break;
}
}
std::this_thread::sleep_for(1ms);
Expand All @@ -761,15 +759,6 @@ void AuctionListingRunnable()
LOG_INFO("server", "Auction House Listing thread exiting without problems.");
}

void ShutdownAuctionListingThread(std::thread* thread)
{
if (thread)
{
thread->join();
delete thread;
}
}

variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& configService)
{
options_description all("Allowed options");
Expand Down
7 changes: 7 additions & 0 deletions src/server/apps/worldserver/worldserver.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3843,6 +3843,13 @@ ChangeFaction.MaxMoney = 0

Pet.RankMod.Health = 1

#
# AuctionHouse.SearchTimeout
# Description: Time (in milliseconds) after which an auction house search is discarded.
# Default: 1000 - (1 second)

AuctionHouse.SearchTimeout = 1000

#
###################################################################################################

Expand Down
11 changes: 4 additions & 7 deletions src/server/game/AuctionHouse/AuctionHouseMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder)
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout)
{
uint32 itrcounter = 0;

Expand All @@ -754,14 +754,11 @@ bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player

for (AuctionEntryMap::const_iterator itr = _auctionsMap.begin(); itr != _auctionsMap.end(); ++itr)
{
if (!AsyncAuctionListingMgr::IsAuctionListingAllowed()) // pussywizard: World::Update is waiting for us...
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
{
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
if (GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= searchTimeout) // pussywizard: stop immediately if diff is high or waiting too long
{
if (sWorldUpdateTime.GetAverageUpdateTime() >= 30 || GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= 10ms) // pussywizard: stop immediately if diff is high or waiting too long
{
return false;
}
return false;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/server/game/AuctionHouse/AuctionHouseMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class AuctionHouseObject
bool BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder);
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout);

private:
AuctionEntryMap _auctionsMap;
Expand All @@ -184,7 +184,6 @@ class AuctionHouseMgr

AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId);
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);

Item* GetAItem(ObjectGuid itemGuid)
{
Expand Down
23 changes: 12 additions & 11 deletions src/server/game/Handlers/AuctionHouseHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,23 +668,24 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
recvData >> listfrom; // not used in fact (this list does not have page control in client)

// pussywizard:
const uint32 delay = 4500;
const uint32 now = GameTime::GetGameTimeMS().count();
const Milliseconds now = GameTime::GetGameTimeMS();
if (_lastAuctionListOwnerItemsMSTime > now) // list is pending
return;
uint32 diff = getMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);

const Milliseconds delay = Milliseconds(4500);
Milliseconds diff = GetMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
if (diff > delay)
diff = delay;

_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual exectuing will change this to getMSTime of that moment
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID(), true), _player->m_Events.CalculateTime(delay - diff));
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual executing will change this to getMSTime of that moment
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID()), _player->m_Events.CalculateTime(delay.count() - diff.count()));
}

void WorldSession::HandleAuctionListOwnerItemsEvent(ObjectGuid creatureGuid)
{
LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");

_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS().count(); // pussywizard
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS(); // pussywizard

Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(creatureGuid, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
Expand Down Expand Up @@ -757,17 +758,17 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
}

// pussywizard:
const uint32 delay = 2000;
const uint32 now = GameTime::GetGameTimeMS().count();
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now);
const Milliseconds delay = 2s;
const Milliseconds now = GameTime::GetGameTimeMS();
Milliseconds diff = GetMSTimeDiff(_lastAuctionListItemsMSTime, now);
if (diff > delay)
{
diff = delay;
}
_lastAuctionListItemsMSTime = now + delay - diff;
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
AsyncAuctionListingMgr::GetTempList().push_back(AuctionListItemsDelayEvent(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder));
AsyncAuctionListingMgr::GetTempList().emplace_back(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder);
}

void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
Expand Down
21 changes: 10 additions & 11 deletions src/server/game/Misc/AsyncAuctionListing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@
#include "Player.h"
#include "SpellAuraEffects.h"

uint32 AsyncAuctionListingMgr::auctionListingDiff = 0;
bool AsyncAuctionListingMgr::auctionListingAllowed = false;
Milliseconds AsyncAuctionListingMgr::auctionListingDiff = Milliseconds::zero();
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingList;
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingListTemp;
std::mutex AsyncAuctionListingMgr::auctionListingLock;
std::mutex AsyncAuctionListingMgr::auctionListingTempLock;

bool AuctionListOwnerItemsDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
Expand Down Expand Up @@ -60,18 +58,19 @@ bool AuctionListItemsDelayEvent::Execute()

wstrToLower(wsearchedname);

uint32 searchTimeout = sWorld->getIntConfig(CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT);
bool result = auctionHouse->BuildListAuctionItems(data, plr,
wsearchedname, _listfrom, _levelmin, _levelmax, _usable,
_auctionSlotID, _auctionMainCategory, _auctionSubCategory, _quality,
count, totalcount, _getAll, _sortOrder);
count, totalcount, _getAll, _sortOrder, Milliseconds(searchTimeout));

if (!result)
return false;

data.put<uint32>(0, count);
data << (uint32) totalcount;
data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
plr->GetSession()->SendPacket(&data);
if (result)
{
data.put<uint32>(0, count);
data << (uint32) totalcount;
data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
plr->GetSession()->SendPacket(&data);
}

return true;
}
24 changes: 8 additions & 16 deletions src/server/game/Misc/AsyncAuctionListing.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,28 @@
class AuctionListOwnerItemsDelayEvent : public BasicEvent
{
public:
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid, bool o) : creatureGuid(_creatureGuid), playerguid(guid), owner(o) {}
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid) : creatureGuid(_creatureGuid), playerguid(guid) {}
~AuctionListOwnerItemsDelayEvent() override {}

bool Execute(uint64 e_time, uint32 p_time) override;
void Abort(uint64 /*e_time*/) override {}
bool getOwner() { return owner; }

private:
ObjectGuid creatureGuid;
ObjectGuid playerguid;
bool owner;
};

class AuctionListItemsDelayEvent
{
public:
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
AuctionListItemsDelayEvent(Milliseconds pickupTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
uint8 usable, uint32 auctionSlotID, uint32 auctionMainCategory, uint32 auctionSubCategory, uint32 quality, uint8 getAll, AuctionSortOrderVector sortOrder) :
_msTimer(msTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
_pickupTimer(pickupTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
_auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll), _sortOrder(sortOrder) { }

bool Execute();

uint32 _msTimer;
Milliseconds _pickupTimer;
ObjectGuid _playerguid;
ObjectGuid _creatureguid;
std::string _searchedname;
Expand All @@ -67,23 +65,17 @@ class AuctionListItemsDelayEvent
class AsyncAuctionListingMgr
{
public:
static void Update(uint32 diff) { auctionListingDiff += diff; }
static uint32 GetDiff() { return auctionListingDiff; }
static void ResetDiff() { auctionListingDiff = 0; }
static bool IsAuctionListingAllowed() { return auctionListingAllowed; }
static void SetAuctionListingAllowed(bool a) { auctionListingAllowed = a; }

static void Update(Milliseconds diff) { auctionListingDiff += diff; }
static Milliseconds GetDiff() { return auctionListingDiff; }
static void ResetDiff() { auctionListingDiff = Milliseconds::zero(); }
static std::list<AuctionListItemsDelayEvent>& GetList() { return auctionListingList; }
static std::list<AuctionListItemsDelayEvent>& GetTempList() { return auctionListingListTemp; }
static std::mutex& GetLock() { return auctionListingLock; }
static std::mutex& GetTempLock() { return auctionListingTempLock; }

private:
static uint32 auctionListingDiff;
static bool auctionListingAllowed;
static Milliseconds auctionListingDiff;
static std::list<AuctionListItemsDelayEvent> auctionListingList;
static std::list<AuctionListItemsDelayEvent> auctionListingListTemp;
static std::mutex auctionListingLock;
static std::mutex auctionListingTempLock;
};

Expand Down
4 changes: 2 additions & 2 deletions src/server/game/Server/WorldSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -1058,8 +1058,8 @@ class WorldSession
void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);

uint32 _lastAuctionListItemsMSTime;
uint32 _lastAuctionListOwnerItemsMSTime;
Milliseconds _lastAuctionListItemsMSTime;
Milliseconds _lastAuctionListOwnerItemsMSTime;

void HandleTeleportTimeout(bool updateInSessions);
bool HandleSocketClosed();
Expand Down
1 change: 1 addition & 0 deletions src/server/game/World/IWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ enum WorldIntConfigs
CONFIG_LFG_KICK_PREVENTION_TIMER,
CONFIG_CHANGE_FACTION_MAX_MONEY,
CONFIG_WATER_BREATH_TIMER,
CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT,
INT_CONFIG_VALUE_COUNT
};

Expand Down
Loading

0 comments on commit 6edcf05

Please sign in to comment.