From ad5256588dc08e1f53ae284dba9ef0061b46e151 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 24 Jan 2013 13:21:35 +0100 Subject: [PATCH] Implemented ServiceGroup::GetMembers() and HostGroup::GetMembers(). --- components/compat/compatcomponent.cpp | 75 ++++++--------------------- components/compat/compatcomponent.h | 16 +++++- lib/icinga/host.cpp | 16 ++++-- lib/icinga/host.h | 5 +- lib/icinga/hostgroup.cpp | 54 +++++++++++++++++++ lib/icinga/hostgroup.h | 9 ++++ lib/icinga/service.cpp | 6 ++- lib/icinga/servicegroup.cpp | 54 +++++++++++++++++++ lib/icinga/servicegroup.h | 9 ++++ 9 files changed, 179 insertions(+), 65 deletions(-) diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp index a461818b6..4bef9e2cb 100644 --- a/components/compat/compatcomponent.cpp +++ b/components/compat/compatcomponent.cpp @@ -237,11 +237,11 @@ void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host) << "\t" << "active_checks_enabled" << "\t" << 1 << "\n" << "\t" << "passive_checks_enabled" << "\t" << 1 << "\n"; - set parents = host->GetParents(); + set parents = host->GetParents(); if (!parents.empty()) { fp << "\t" << "parents" << "\t"; - DumpStringList(fp, parents); + DumpNameList(fp, parents); fp << "\n"; } @@ -370,90 +370,49 @@ void CompatComponent::StatusTimerHandler(void) << "# This file is auto-generated. Do not modify this file." << "\n" << "\n"; - map > hostgroups; - DynamicObject::Ptr object; BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) { const Host::Ptr& host = static_pointer_cast(object); - Dictionary::Ptr dict; - dict = host->GetGroups(); - - if (dict) { - Value hostgroup; - BOOST_FOREACH(tie(tuples::ignore, hostgroup), dict) { - hostgroups[hostgroup].push_back(host->GetName()); - } - } - DumpHostStatus(statusfp, host); DumpHostObject(objectfp, host); } - pair > hgt; - BOOST_FOREACH(hgt, hostgroups) { - const String& name = hgt.first; - const vector& hosts = hgt.second; + BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("HostGroup")->GetObjects()) { + const HostGroup::Ptr& hg = static_pointer_cast(object); objectfp << "define hostgroup {" << "\n" - << "\t" << "hostgroup_name" << "\t" << name << "\n"; - - if (HostGroup::Exists(name)) { - HostGroup::Ptr hg = HostGroup::GetByName(name); - objectfp << "\t" << "alias" << "\t" << hg->GetAlias() << "\n" - << "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n" - << "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n"; - } + << "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n" + << "\t" << "alias" << "\t" << hg->GetAlias() << "\n" + << "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n" + << "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n"; objectfp << "\t" << "members" << "\t"; - - DumpStringList(objectfp, hosts); - + DumpNameList(objectfp, hg->GetMembers()); objectfp << "\n" << "}" << "\n"; } - map > servicegroups; - BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { - Service::Ptr service = static_pointer_cast(object); - - Dictionary::Ptr dict; - - dict = service->GetGroups(); - - if (dict) { - Value servicegroup; - BOOST_FOREACH(tie(tuples::ignore, servicegroup), dict) { - servicegroups[servicegroup].push_back(service); - } - } + const Service::Ptr& service = static_pointer_cast(object); DumpServiceStatus(statusfp, service); DumpServiceObject(objectfp, service); } - pair > sgt; - BOOST_FOREACH(sgt, servicegroups) { - const String& name = sgt.first; - const vector& services = sgt.second; + BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("ServiceGroup")->GetObjects()) { + const ServiceGroup::Ptr& sg = static_pointer_cast(object); objectfp << "define servicegroup {" << "\n" - << "\t" << "servicegroup_name" << "\t" << name << "\n"; - - if (ServiceGroup::Exists(name)) { - ServiceGroup::Ptr sg = ServiceGroup::GetByName(name); - objectfp << "\t" << "alias" << "\t" << sg->GetAlias() << "\n" - << "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n" - << "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n"; - } + << "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n" + << "\t" << "alias" << "\t" << sg->GetAlias() << "\n" + << "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n" + << "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n"; objectfp << "\t" << "members" << "\t"; vector sglist; - vector::iterator vt; - - BOOST_FOREACH(const Service::Ptr& service, services) { + BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) { sglist.push_back(service->GetHost()->GetName()); sglist.push_back(service->GetAlias()); } diff --git a/components/compat/compatcomponent.h b/components/compat/compatcomponent.h index 07486b6cc..1f645dc6c 100644 --- a/components/compat/compatcomponent.h +++ b/components/compat/compatcomponent.h @@ -49,6 +49,21 @@ private: void DumpHostStatus(ofstream& fp, const Host::Ptr& host); void DumpHostObject(ofstream& fp, const Host::Ptr& host); + template + void DumpNameList(ofstream& fp, const T& list) + { + typename T::const_iterator it; + bool first = true; + for (it = list.begin(); it != list.end(); it++) { + if (!first) + fp << ","; + else + first = false; + + fp << (*it)->GetName(); + } + } + template void DumpStringList(ofstream& fp, const T& list) { @@ -64,7 +79,6 @@ private: } } - void DumpServiceStatus(ofstream& fp, const Service::Ptr& service); void DumpServiceObject(ofstream& fp, const Service::Ptr& service); diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index a289252d7..284d8801f 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -39,6 +39,8 @@ Host::Host(const Dictionary::Ptr& properties) m_InitializerDone = true; } + + HostGroup::InvalidateMembersCache(); } String Host::GetAlias(void) const @@ -70,9 +72,9 @@ Dictionary::Ptr Host::GetGroups(void) const return Get("hostgroups"); } -set Host::GetParents(void) +set Host::GetParents(void) { - set parents; + set parents; Dictionary::Ptr dependencies = Get("dependencies"); if (dependencies) { @@ -82,10 +84,10 @@ set Host::GetParents(void) BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) { Service::Ptr service = Service::GetByName(dependency); - String parent = service->GetHost()->GetName(); + Host::Ptr parent = service->GetHost(); /* ignore ourselves */ - if (parent == GetName()) + if (parent->GetName() == GetName()) continue; parents.insert(parent); @@ -273,3 +275,9 @@ void Host::ObjectRemovedHandler(const ConfigItem::Ptr& item) } } +void Host::OnAttributeChanged(const String& name, const Value& oldValue) +{ + if (name == "hostgroups") + HostGroup::InvalidateMembersCache(); +} + diff --git a/lib/icinga/host.h b/lib/icinga/host.h index a8990b178..971059c5d 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -41,12 +41,15 @@ public: String GetAlias(void) const; Dictionary::Ptr GetGroups(void) const; - set GetParents(void); + set GetParents(void); Dictionary::Ptr GetMacros(void) const; bool IsReachable(void); bool IsUp(void); +protected: + void OnAttributeChanged(const String& name, const Value& oldValue); + private: static bool m_InitializerDone; diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index 0838ef764..56a300aa4 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -21,6 +21,9 @@ using namespace icinga; +map > HostGroup::m_MembersCache; +bool HostGroup::m_MembersCacheValid = true; + static AttributeDescription hostGroupAttributes[] = { { "alias", Attribute_Config }, { "notes_url", Attribute_Config }, @@ -64,3 +67,54 @@ HostGroup::Ptr HostGroup::GetByName(const String& name) return dynamic_pointer_cast(configObject); } +set HostGroup::GetMembers(void) const +{ + set hosts; + + ValidateMembersCache(); + + BOOST_FOREACH(const String& hst, m_MembersCache[GetName()]) { + if (!Host::Exists(hst)) + continue; + + Host::Ptr host = Host::GetByName(hst); + hosts.insert(host); + } + + return hosts; +} + +void HostGroup::InvalidateMembersCache(void) +{ + m_MembersCacheValid = false; + m_MembersCache.clear(); +} + +void HostGroup::ValidateMembersCache(void) +{ + if (m_MembersCacheValid) + return; + + m_MembersCache.clear(); + + DynamicObject::Ptr object; + BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) { + const Host::Ptr& host = static_pointer_cast(object); + + Dictionary::Ptr dict; + dict = host->GetGroups(); + + if (dict) { + Value hostgroup; + BOOST_FOREACH(tie(tuples::ignore, hostgroup), dict) { + if (!HostGroup::Exists(hostgroup)) + Logger::Write(LogWarning, "icinga", "Host group '" + hostgroup + "' used but not defined."); + + m_MembersCache[hostgroup].push_back(host->GetName()); + } + } + } + + m_MembersCacheValid = true; +} + diff --git a/lib/icinga/hostgroup.h b/lib/icinga/hostgroup.h index b0e854103..9f921cf0b 100644 --- a/lib/icinga/hostgroup.h +++ b/lib/icinga/hostgroup.h @@ -44,6 +44,15 @@ public: String GetAlias(void) const; String GetNotesUrl(void) const; String GetActionUrl(void) const; + + set GetMembers(void) const; + static void InvalidateMembersCache(void); + +private: + static map > m_MembersCache; + static bool m_MembersCacheValid; + + static void ValidateMembersCache(void); }; } diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index c33d4e600..ce67b6925 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -62,7 +62,9 @@ boost::signal Service::OnNextCheckChan Service::Service(const Dictionary::Ptr& serializedObject) : DynamicObject(serializedObject) -{ } +{ + ServiceGroup::InvalidateMembersCache(); +} String Service::GetAlias(void) const { @@ -583,6 +585,8 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue) OnCheckerChanged(GetSelf(), oldValue); else if (name == "next_check") OnNextCheckChanged(GetSelf(), oldValue); + else if (name == "servicegroups") + ServiceGroup::InvalidateMembersCache(); } void Service::BeginExecuteCheck(const function& callback) diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index 31b413fc4..316eb1bfd 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -21,6 +21,9 @@ using namespace icinga; +map > ServiceGroup::m_MembersCache; +bool ServiceGroup::m_MembersCacheValid; + static AttributeDescription serviceGroupAttributes[] = { { "alias", Attribute_Config }, { "notes_url", Attribute_Config }, @@ -64,3 +67,54 @@ ServiceGroup::Ptr ServiceGroup::GetByName(const String& name) return dynamic_pointer_cast(configObject); } +set ServiceGroup::GetMembers(void) const +{ + set services; + + ValidateMembersCache(); + + BOOST_FOREACH(const String& svc, m_MembersCache[GetName()]) { + if (!Service::Exists(svc)) + continue; + + Service::Ptr service = Service::GetByName(svc); + services.insert(service); + } + + return services; +} + +void ServiceGroup::InvalidateMembersCache(void) +{ + m_MembersCacheValid = false; + m_MembersCache.clear(); +} + +void ServiceGroup::ValidateMembersCache(void) +{ + if (m_MembersCacheValid) + return; + + m_MembersCache.clear(); + + DynamicObject::Ptr object; + BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) { + const Service::Ptr& service = static_pointer_cast(object); + + Dictionary::Ptr dict; + dict = service->GetGroups(); + + if (dict) { + Value servicegroup; + BOOST_FOREACH(tie(tuples::ignore, servicegroup), dict) { + if (!ServiceGroup::Exists(servicegroup)) + Logger::Write(LogWarning, "icinga", "Service group '" + servicegroup + "' used but not defined."); + + m_MembersCache[servicegroup].push_back(service->GetName()); + } + } + } + + m_MembersCacheValid = true; +} + diff --git a/lib/icinga/servicegroup.h b/lib/icinga/servicegroup.h index 48f2c4f6e..6798c69c6 100644 --- a/lib/icinga/servicegroup.h +++ b/lib/icinga/servicegroup.h @@ -44,6 +44,15 @@ public: String GetAlias(void) const; String GetNotesUrl(void) const; String GetActionUrl(void) const; + + set GetMembers(void) const; + static void InvalidateMembersCache(void); + +private: + static map > m_MembersCache; + static bool m_MembersCacheValid; + + static void ValidateMembersCache(void); }; }