]> granicus.if.org Git - icinga2/commitdiff
Improve the performance for ApiListener::SyncRelayMessage (part 2)
authorGunnar Beutner <gunnar@beutner.name>
Wed, 27 Jan 2016 11:18:16 +0000 (12:18 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Wed, 27 Jan 2016 11:18:16 +0000 (12:18 +0100)
refs #11014

lib/remote/apilistener.cpp
lib/remote/apilistener.hpp
lib/remote/zone.cpp
lib/remote/zone.hpp

index 92d42ac24160ad05a64b67f9aca42f607b248f12..de9f1047d673b76c9c59e024288b994d42ba9b79 100644 (file)
@@ -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<Endpoint::Ptr> skippedEndpoints;
-       std::set<Zone::Ptr> allZones;
-       std::set<Zone::Ptr> finishedZones;
-       std::set<Zone::Ptr> finishedLogZones;
 
-       BOOST_FOREACH(const Endpoint::Ptr& endpoint, ConfigType::GetObjectsByType<Endpoint>()) {
+       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<Zone>(secobj);
+               else
+                       target_zone = static_pointer_cast<Zone>(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)
index 3b02a3bb032f1f9a636eeaa6da5bcce1e3f7f61e..5fcbea3b1548576b10bde53f0d75bf48b56365e5 100644 (file)
@@ -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);
 
index 311b11ccac989cb3fe77e731e38a33676ab90c3b..f58930c43c1c337b737b171eacced4e21f0ffd1a 100644 (file)
@@ -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<Endpoint::Ptr> Zone::GetEndpoints(void) const
        return result;
 }
 
+std::vector<Zone::Ptr> Zone::GetAllParents(void) const
+{
+       return m_AllParents;
+}
+
 bool Zone::CanAccessObject(const ConfigObject::Ptr& object)
 {
        Zone::Ptr object_zone;
index 5de8a225b23e6336eee8231b7a678bc153b071ba..4d00a514a76a06d4e9cc3dd2cb7b37395626636f 100644 (file)
@@ -40,6 +40,7 @@ public:
 
        Zone::Ptr GetParent(void) const;
        std::set<Endpoint::Ptr> GetEndpoints(void) const;
+       std::vector<Zone::Ptr> 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<Zone::Ptr> m_AllParents;
 };
 
 }