From: Gunnar Beutner Date: Wed, 27 Jan 2016 11:18:16 +0000 (+0100) Subject: Improve the performance for ApiListener::SyncRelayMessage (part 2) X-Git-Tag: v2.5.0~583 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8c05003101b1587bf8c04aec7d5398f5bb7b76ff;p=icinga2 Improve the performance for ApiListener::SyncRelayMessage (part 2) refs #11014 --- diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index 92d42ac24..de9f1047d 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -613,54 +613,41 @@ void ApiListener::SyncSendMessage(const Endpoint::Ptr& endpoint, const Dictionar } } - -void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin, - const ConfigObject::Ptr& secobj, const Dictionary::Ptr& message, bool log) +bool ApiListener::RelayMessageOne(const Zone::Ptr& targetZone, const MessageOrigin::Ptr& origin, const Dictionary::Ptr& message) { - double ts = Utility::GetTime(); - message->Set("ts", ts); - - Log(LogNotice, "ApiListener") - << "Relaying '" << message->Get("method") << "' message"; - - if (origin && origin->FromZone) - message->Set("originZone", origin->FromZone->GetName()); + ASSERT(targetZone); bool is_master = IsMaster(); Endpoint::Ptr master = GetMaster(); - Zone::Ptr my_zone = Zone::GetLocalZone(); + Zone::Ptr myZone = Zone::GetLocalZone(); + + /* only relay the message to a) the same zone, b) the parent zone and c) direct child zones */ + if (targetZone != myZone && targetZone != myZone->GetParent() && targetZone->GetParent() != myZone) + return true; std::vector skippedEndpoints; - std::set allZones; - std::set finishedZones; - std::set finishedLogZones; - BOOST_FOREACH(const Endpoint::Ptr& endpoint, ConfigType::GetObjectsByType()) { + bool relayed = false, log_needed = false, log_done = false; + + BOOST_FOREACH(const Endpoint::Ptr& endpoint, targetZone->GetEndpoints()) { /* don't relay messages to ourselves */ if (endpoint == GetLocalEndpoint()) continue; - Zone::Ptr target_zone = endpoint->GetZone(); - - - /* only relay messages to zones which have access to the object */ - if (!target_zone->CanAccessObject(secobj)) - continue; - - allZones.insert(target_zone); + log_needed = true; /* don't relay messages to disconnected endpoints */ if (!endpoint->GetConnected()) { - if (target_zone == my_zone) - finishedLogZones.erase(target_zone); + if (targetZone == myZone) + log_done = false; continue; } - finishedLogZones.insert(target_zone); + log_done = true; /* don't relay the message to the zone through more than one endpoint unless this is our own zone */ - if (finishedZones.find(target_zone) != finishedZones.end() && target_zone != my_zone) { + if (relayed && targetZone != myZone) { skippedEndpoints.push_back(endpoint); continue; } @@ -672,7 +659,7 @@ void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin, } /* don't relay messages back to the zone which we got the message from */ - if (origin && origin->FromZone && target_zone == origin->FromZone) { + if (origin && origin->FromZone && targetZone == origin->FromZone) { skippedEndpoints.push_back(endpoint); continue; } @@ -683,23 +670,54 @@ void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin, continue; } - /* only relay the message to a) the same zone, b) the parent zone and c) direct child zones */ - if (target_zone != my_zone && target_zone != my_zone->GetParent() && - secobj->GetZoneName() != target_zone->GetName()) { - skippedEndpoints.push_back(endpoint); - continue; - } - - finishedZones.insert(target_zone); + relayed = true; SyncSendMessage(endpoint, message); } - if (log && allZones.size() != finishedLogZones.size()) - PersistMessage(message, secobj); + if (!skippedEndpoints.empty()) { + double ts = message->Get("ts"); + + BOOST_FOREACH(const Endpoint::Ptr& endpoint, skippedEndpoints) + endpoint->SetLocalLogPosition(ts); + } + + return !log_needed || log_done; +} - BOOST_FOREACH(const Endpoint::Ptr& endpoint, skippedEndpoints) - endpoint->SetLocalLogPosition(ts); +void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin, + const ConfigObject::Ptr& secobj, const Dictionary::Ptr& message, bool log) +{ + double ts = Utility::GetTime(); + message->Set("ts", ts); + + Log(LogNotice, "ApiListener") + << "Relaying '" << message->Get("method") << "' message"; + + if (origin && origin->FromZone) + message->Set("originZone", origin->FromZone->GetName()); + + Zone::Ptr target_zone; + + if (secobj) { + if (secobj->GetReflectionType() == Zone::TypeInstance) + target_zone = static_pointer_cast(secobj); + else + target_zone = static_pointer_cast(secobj->GetZone()); + } + + if (!target_zone) + target_zone = Zone::GetLocalZone(); + + bool need_log = !RelayMessageOne(target_zone, origin, message); + + BOOST_FOREACH(const Zone::Ptr& zone, target_zone->GetAllParents()) { + if (!RelayMessageOne(zone, origin, message)) + need_log = true; + } + + if (log && need_log) + PersistMessage(message, secobj); } String ApiListener::GetApiDir(void) diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 3b02a3bb0..5fcbea3b1 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -128,6 +128,7 @@ private: Stream::Ptr m_LogFile; size_t m_LogMessageCount; + bool RelayMessageOne(const Zone::Ptr& zone, const MessageOrigin::Ptr& origin, const Dictionary::Ptr& message); void SyncRelayMessage(const MessageOrigin::Ptr& origin, const ConfigObject::Ptr& secobj, const Dictionary::Ptr& message, bool log); void PersistMessage(const Dictionary::Ptr& message, const ConfigObject::Ptr& secobj); diff --git a/lib/remote/zone.cpp b/lib/remote/zone.cpp index 311b11cca..f58930c43 100644 --- a/lib/remote/zone.cpp +++ b/lib/remote/zone.cpp @@ -30,6 +30,14 @@ REGISTER_TYPE(Zone); void Zone::OnAllConfigLoaded(void) { m_Parent = Zone::GetByName(GetParentRaw()); + + Zone::Ptr zone = m_Parent; + + while (zone) { + m_AllParents.push_back(zone); + + zone = Zone::GetByName(zone->GetParentRaw()); + } } Zone::Ptr Zone::GetParent(void) const @@ -59,6 +67,11 @@ std::set Zone::GetEndpoints(void) const return result; } +std::vector Zone::GetAllParents(void) const +{ + return m_AllParents; +} + bool Zone::CanAccessObject(const ConfigObject::Ptr& object) { Zone::Ptr object_zone; diff --git a/lib/remote/zone.hpp b/lib/remote/zone.hpp index 5de8a225b..4d00a514a 100644 --- a/lib/remote/zone.hpp +++ b/lib/remote/zone.hpp @@ -40,6 +40,7 @@ public: Zone::Ptr GetParent(void) const; std::set GetEndpoints(void) const; + std::vector GetAllParents(void) const; bool CanAccessObject(const ConfigObject::Ptr& object); bool IsChildOf(const Zone::Ptr& zone); @@ -49,6 +50,7 @@ public: private: Zone::Ptr m_Parent; + std::vector m_AllParents; }; }