diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-10-11 22:42:03 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-10-11 22:42:03 +0200 |
commit | 644af37f96cc852f2ea7377d2600246cebac49b8 (patch) | |
tree | e95b351e40cca0dfcb9b56345f40f633864f1a2d /src | |
parent | b09bd8d702abd23150a8a92aadeaae8a3dd34d21 (diff) |
Core/Realms: Made realmlist threadsafe
Diffstat (limited to 'src')
-rw-r--r-- | src/server/shared/Realm/RealmList.cpp | 101 | ||||
-rw-r--r-- | src/server/shared/Realm/RealmList.h | 7 |
2 files changed, 64 insertions, 44 deletions
diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index 66346614278..2135c1f26b8 100644 --- a/src/server/shared/Realm/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -29,10 +29,13 @@ #include "RealmList.pb.h" #include <boost/asio/deadline_timer.hpp> #include <boost/asio/ip/tcp.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/shared_mutex.hpp> #include <zlib.h> RealmList::RealmList() : _updateInterval(0) { + _realmsMutex = Trinity::make_unique<boost::shared_mutex>(); } RealmList::~RealmList() @@ -61,14 +64,11 @@ void RealmList::Close() _updateTimer->cancel(); } -void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name, +void RealmList::UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name, boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population) { - // Create new if not exist or update existed - Realm& realm = _realms[id]; - realm.Id = id; realm.Build = build; if (realm.Name != name) @@ -101,7 +101,8 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) for (auto const& p : _realms) existingRealms[p.first] = p.second.Name; - _realms.clear(); + std::unordered_set<std::string> newSubRegions; + RealmMap newRealms; // Circle through results and add them to the realm map if (result) @@ -163,10 +164,10 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) Battlenet::RealmHandle id{ region, battlegroup, realmId }; - UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag, - timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); + UpdateRealm(newRealms[id], id, build, name, externalAddress, localAddress, localSubmask, port, icon, + flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); - _subRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString()); + newSubRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString()); if (!existingRealms.count(id)) TC_LOG_INFO("realmlist", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); @@ -187,6 +188,13 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr) TC_LOG_INFO("realmlist", "Removed realm \"%s\".", itr->second.c_str()); + { + std::unique_lock<boost::shared_mutex> lock(*_realmsMutex); + + _subRegions.swap(newSubRegions); + _realms.swap(newRealms); + } + if (_updateInterval) { _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); @@ -196,6 +204,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const { + boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex); auto itr = _realms.find(id); if (itr != _realms.end()) return &itr->second; @@ -237,13 +246,15 @@ RealmBuildInfo const* RealmList::GetBuildInfo(uint32 build) const void RealmList::WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const { - for (std::string const& subRegion : GetSubRegions()) + boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex); + for (std::string const& subRegion : _subRegions) response->add_attribute_value()->set_string_value(subRegion); } std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const { std::vector<uint8> compressed; + boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex); if (Realm const* realm = GetRealm(id)) { if (!(realm->Flags & REALM_FLAG_OFFLINE) && realm->Build == build) @@ -276,6 +287,8 @@ std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id realmEntry.set_cfgconfigsid(realm->GetConfigId()); realmEntry.set_cfglanguagesid(1); + lock.unlock(); + std::string json = "JamJSONRealmEntry:" + JSON::Serialize(realmEntry); uLong compressedLength = compressBound(uLong(json.length())); @@ -295,44 +308,47 @@ std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subRegion) const { JSON::RealmList::RealmListUpdates realmList; - for (auto const& realm : _realms) { - if (realm.second.Id.GetSubRegionAddress() != subRegion) - continue; + boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex); + for (auto const& realm : _realms) + { + if (realm.second.Id.GetSubRegionAddress() != subRegion) + continue; - uint32 flag = realm.second.Flags; - if (realm.second.Build != build) - flag |= REALM_FLAG_VERSION_MISMATCH; + uint32 flag = realm.second.Flags; + if (realm.second.Build != build) + flag |= REALM_FLAG_VERSION_MISMATCH; - JSON::RealmList::RealmState* state = realmList.add_updates(); - state->mutable_update()->set_wowrealmaddress(realm.second.Id.GetAddress()); - state->mutable_update()->set_cfgtimezonesid(1); - state->mutable_update()->set_populationstate((realm.second.Flags & REALM_FLAG_OFFLINE) ? 0u : std::max(uint32(realm.second.PopulationLevel), 1u)); - state->mutable_update()->set_cfgcategoriesid(realm.second.Timezone); + JSON::RealmList::RealmState* state = realmList.add_updates(); + state->mutable_update()->set_wowrealmaddress(realm.second.Id.GetAddress()); + state->mutable_update()->set_cfgtimezonesid(1); + state->mutable_update()->set_populationstate((realm.second.Flags & REALM_FLAG_OFFLINE) ? 0u : std::max(uint32(realm.second.PopulationLevel), 1u)); + state->mutable_update()->set_cfgcategoriesid(realm.second.Timezone); - JSON::RealmList::ClientVersion* version = state->mutable_update()->mutable_version(); - if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm.second.Build)) - { - version->set_versionmajor(buildInfo->MajorVersion); - version->set_versionminor(buildInfo->MinorVersion); - version->set_versionrevision(buildInfo->BugfixVersion); - version->set_versionbuild(buildInfo->Build); - } - else - { - version->set_versionmajor(6); - version->set_versionminor(2); - version->set_versionrevision(4); - version->set_versionbuild(realm.second.Build); - } + JSON::RealmList::ClientVersion* version = state->mutable_update()->mutable_version(); + if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm.second.Build)) + { + version->set_versionmajor(buildInfo->MajorVersion); + version->set_versionminor(buildInfo->MinorVersion); + version->set_versionrevision(buildInfo->BugfixVersion); + version->set_versionbuild(buildInfo->Build); + } + else + { + version->set_versionmajor(6); + version->set_versionminor(2); + version->set_versionrevision(4); + version->set_versionbuild(realm.second.Build); + } - state->mutable_update()->set_cfgrealmsid(realm.second.Id.Realm); - state->mutable_update()->set_flags(flag); - state->mutable_update()->set_name(realm.second.Name); - state->mutable_update()->set_cfgconfigsid(realm.second.GetConfigId()); - state->mutable_update()->set_cfglanguagesid(1); + state->mutable_update()->set_cfgrealmsid(realm.second.Id.Realm); + state->mutable_update()->set_flags(flag); + state->mutable_update()->set_name(realm.second.Name); + state->mutable_update()->set_cfgconfigsid(realm.second.GetConfigId()); + state->mutable_update()->set_cfglanguagesid(1); - state->set_deleting(false); + state->set_deleting(false); + } } std::string json = "JSONRealmListUpdates:" + JSON::Serialize(realmList); @@ -352,6 +368,7 @@ std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subR uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret, LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const { + boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex); if (Realm const* realm = GetRealm(Battlenet::RealmHandle(realmAddress))) { if (realm->Flags & REALM_FLAG_OFFLINE || realm->Build != build) @@ -365,6 +382,8 @@ uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip:: address->set_ip(realm->GetAddressForClient(clientAddress).to_string()); address->set_port(realm->Port); + lock.unlock(); + std::string json = "JSONRealmListServerIPAddresses:" + JSON::Serialize(serverAddresses); uLong compressedLength = compressBound(uLong(json.length())); diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h index 50609a6a900..855cc4fc428 100644 --- a/src/server/shared/Realm/RealmList.h +++ b/src/server/shared/Realm/RealmList.h @@ -36,6 +36,8 @@ struct RealmBuildInfo namespace boost { + class shared_mutex; + namespace asio { class io_service; @@ -83,11 +85,9 @@ public: void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); void Close(); - RealmMap const& GetRealms() const { return _realms; } Realm const* GetRealm(Battlenet::RealmHandle const& id) const; RealmBuildInfo const* GetBuildInfo(uint32 build) const; - std::unordered_set<std::string> const& GetSubRegions() const { return _subRegions; } void WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const; std::vector<uint8> GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const; std::vector<uint8> GetRealmList(uint32 build, std::string const& subRegion) const; @@ -98,10 +98,11 @@ private: RealmList(); void UpdateRealms(boost::system::error_code const& error); - void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name, + void UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name, boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); + std::unique_ptr<boost::shared_mutex> _realmsMutex; RealmMap _realms; std::unordered_set<std::string> _subRegions; uint32 _updateInterval; |