diff --git a/lib/base/scriptutils.cpp b/lib/base/scriptutils.cpp index c19266f4c..8f9bc856b 100644 --- a/lib/base/scriptutils.cpp +++ b/lib/base/scriptutils.cpp @@ -451,8 +451,9 @@ Array::Ptr ScriptUtils::GetTemplates(const Type::Ptr& type) BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Must not be null")); ArrayData result; + auto items (ConfigItem::GetItems(type)); - for (const ConfigItem::Ptr& item : ConfigItem::GetItems(type)) { + for (auto& item : *items) { if (item->IsAbstract()) result.push_back(GetTargetForTemplate(item)); } diff --git a/lib/cli/daemonutility.cpp b/lib/cli/daemonutility.cpp index f9fb79873..b4738a146 100644 --- a/lib/cli/daemonutility.cpp +++ b/lib/cli/daemonutility.cpp @@ -225,7 +225,7 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector& configs, Type::Ptr appType = Type::GetByName(vAppType); - if (ConfigItem::GetItems(appType).empty()) { + if (ConfigItem::GetItems(appType)->empty()) { ConfigItemBuilder builder; builder.SetType(appType); builder.SetName("app"); diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 7687e50be..1ae073a28 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -33,6 +33,7 @@ using namespace icinga; std::mutex ConfigItem::m_Mutex; ConfigItem::TypeMap ConfigItem::m_Items; +std::map>> ConfigItem::m_CachedAllItemsByType; ConfigItem::TypeMap ConfigItem::m_DefaultTemplates; ConfigItem::ItemList ConfigItem::m_UnnamedItems; ConfigItem::IgnoredItemList ConfigItem::m_IgnoredItems; @@ -345,6 +346,7 @@ void ConfigItem::Register() } m_Items[m_Type][m_Name] = this; + m_CachedAllItemsByType.erase(m_Type); if (m_DefaultTmpl) m_DefaultTemplates[m_Type][m_Name] = this; @@ -364,6 +366,7 @@ void ConfigItem::Unregister() std::unique_lock lock(m_Mutex); m_UnnamedItems.erase(std::remove(m_UnnamedItems.begin(), m_UnnamedItems.end(), this), m_UnnamedItems.end()); m_Items[m_Type].erase(m_Name); + m_CachedAllItemsByType.erase(m_Type); m_DefaultTemplates[m_Type].erase(m_Name); } @@ -754,21 +757,28 @@ bool ConfigItem::RunWithActivationContext(const Function::Ptr& function) return true; } -std::vector ConfigItem::GetItems(const Type::Ptr& type) +std::shared_ptr> ConfigItem::GetItems(const Type::Ptr& type) { - std::vector items; - std::unique_lock lock(m_Mutex); + auto cached (m_CachedAllItemsByType.find(type)); + + if (cached != m_CachedAllItemsByType.end()) { + return cached->second; + } + + auto items (std::make_shared>()); + + m_CachedAllItemsByType.emplace(type, items); auto it = m_Items.find(type); if (it == m_Items.end()) return items; - items.reserve(it->second.size()); + items->reserve(it->second.size()); for (const ItemMap::value_type& kv : it->second) { - items.push_back(kv.second); + items->push_back(kv.second); } return items; diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index bd04b47f4..b007cb474 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -9,6 +9,7 @@ #include "config/activationcontext.hpp" #include "base/configobject.hpp" #include "base/workqueue.hpp" +#include namespace icinga { @@ -59,7 +60,7 @@ public: static bool RunWithActivationContext(const Function::Ptr& function); - static std::vector GetItems(const Type::Ptr& type); + static std::shared_ptr> GetItems(const Type::Ptr& type); static std::vector GetDefaultTemplates(const Type::Ptr& type); static void RemoveIgnoredItems(const String& allowedConfigPath); @@ -86,6 +87,7 @@ private: typedef std::map ItemMap; typedef std::map TypeMap; static TypeMap m_Items; /**< All registered configuration items. */ + static std::map>> m_CachedAllItemsByType; static TypeMap m_DefaultTemplates; typedef std::vector ItemList; diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index 5dbeaeafd..a44619205 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -48,7 +48,9 @@ void HostGroup::EvaluateObjectRules(const Host::Ptr& host) { CONTEXT("Evaluating group memberships for host '" << host->GetName() << "'"); - for (const ConfigItem::Ptr& group : ConfigItem::GetItems(HostGroup::TypeInstance)) + auto items (ConfigItem::GetItems(HostGroup::TypeInstance)); + + for (auto& group : *items) { if (!group->GetFilter()) continue; diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index 6e8d8f07f..857de5a36 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -51,7 +51,9 @@ void ServiceGroup::EvaluateObjectRules(const Service::Ptr& service) { CONTEXT("Evaluating group membership for service '" << service->GetName() << "'"); - for (const ConfigItem::Ptr& group : ConfigItem::GetItems(ServiceGroup::TypeInstance)) + auto items (ConfigItem::GetItems(ServiceGroup::TypeInstance)); + + for (auto& group : *items) { if (!group->GetFilter()) continue; diff --git a/lib/icinga/usergroup.cpp b/lib/icinga/usergroup.cpp index 7a0fde304..b7fa96b72 100644 --- a/lib/icinga/usergroup.cpp +++ b/lib/icinga/usergroup.cpp @@ -49,7 +49,9 @@ void UserGroup::EvaluateObjectRules(const User::Ptr& user) { CONTEXT("Evaluating group membership for user '" << user->GetName() << "'"); - for (const ConfigItem::Ptr& group : ConfigItem::GetItems(UserGroup::TypeInstance)) + auto items (ConfigItem::GetItems(UserGroup::TypeInstance)); + + for (auto& group : *items) { if (!group->GetFilter()) continue; diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp index 1aaba7906..d27aa6345 100644 --- a/lib/remote/templatequeryhandler.cpp +++ b/lib/remote/templatequeryhandler.cpp @@ -41,8 +41,9 @@ public: const std::function& addTarget) const override { Type::Ptr ptype = Type::GetByName(type); + auto items (ConfigItem::GetItems(ptype)); - for (const ConfigItem::Ptr& item : ConfigItem::GetItems(ptype)) { + for (auto& item : *items) { if (item->IsAbstract()) addTarget(GetTargetForTemplate(item)); }