From a16ef350e21a47be286eb34463425dd97a77e6d0 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 9 Apr 2014 12:22:23 +0200 Subject: [PATCH] Avoid unnecessary copies for DynamicType::GetObjects. Fixes #5987 --- components/cluster/clusterlistener.cpp | 6 +-- components/livestatus/statustable.cpp | 4 +- lib/base/dynamictype.cpp | 15 ++---- lib/base/dynamictype.h | 69 ++++++++++++++++++++------ lib/config/configitem.cpp | 5 +- lib/db_ido/dbconnection.cpp | 8 +-- 6 files changed, 72 insertions(+), 35 deletions(-) diff --git a/components/cluster/clusterlistener.cpp b/components/cluster/clusterlistener.cpp index 90ec07cc1..43a1a7ac8 100644 --- a/components/cluster/clusterlistener.cpp +++ b/components/cluster/clusterlistener.cpp @@ -1570,7 +1570,7 @@ bool ClusterListener::SupportsChecks(void) if (!type) return false; - return !type->GetObjects().empty() && IcingaApplication::GetInstance()->GetEnableChecks(); + return std::distance(type->GetObjects().first, type->GetObjects().second) > 0 && IcingaApplication::GetInstance()->GetEnableChecks(); } bool ClusterListener::SupportsNotifications(void) @@ -1580,7 +1580,7 @@ bool ClusterListener::SupportsNotifications(void) if (!type) return false; - return !type->GetObjects().empty() && IcingaApplication::GetInstance()->GetEnableNotifications(); + return std::distance(type->GetObjects().first, type->GetObjects().second) > 0 && IcingaApplication::GetInstance()->GetEnableNotifications(); } bool ClusterListener::SupportsFeature(const String& name) @@ -1590,7 +1590,7 @@ bool ClusterListener::SupportsFeature(const String& name) if (!type) return false; - return !type->GetObjects().empty(); + return std::distance(type->GetObjects().first, type->GetObjects().second) > 0; } std::pair ClusterListener::GetClusterStatus(void) diff --git a/components/livestatus/statustable.cpp b/components/livestatus/statustable.cpp index 77a27f381..63e1d299b 100644 --- a/components/livestatus/statustable.cpp +++ b/components/livestatus/statustable.cpp @@ -184,12 +184,12 @@ Value StatusTable::ProgramStartAccessor(const Value&) Value StatusTable::NumHostsAccessor(const Value&) { - return static_cast(DynamicType::GetObjects().size()); + return std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second); } Value StatusTable::NumServicesAccessor(const Value&) { - return static_cast(DynamicType::GetObjects().size()); + return std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second); } Value StatusTable::ProgramVersionAccessor(const Value&) diff --git a/lib/base/dynamictype.cpp b/lib/base/dynamictype.cpp index 0b955c6ad..5524d3b0b 100644 --- a/lib/base/dynamictype.cpp +++ b/lib/base/dynamictype.cpp @@ -73,17 +73,12 @@ DynamicType::TypeVector DynamicType::GetTypes(void) return InternalGetTypeVector(); /* Making a copy of the vector here. */ } -std::vector DynamicType::GetObjects(const String& type) +std::pair, DynamicTypeIterator > DynamicType::GetObjects(void) { - DynamicType::Ptr dt = GetByName(type); - return dt->GetObjects(); -} - -std::vector DynamicType::GetObjects(void) const -{ - ObjectLock olock(this); - - return m_ObjectVector; /* Making a copy of the vector here. */ + return std::make_pair( + DynamicTypeIterator(GetSelf(), 0), + DynamicTypeIterator(GetSelf(), -1) + ); } String DynamicType::GetName(void) const diff --git a/lib/base/dynamictype.h b/lib/base/dynamictype.h index cbd1117b7..13312c804 100644 --- a/lib/base/dynamictype.h +++ b/lib/base/dynamictype.h @@ -24,13 +24,18 @@ #include "base/registry.h" #include "base/dynamicobject.h" #include "base/debug.h" +#include "base/objectlock.h" #include #include #include +# include namespace icinga { +template +class I2_BASE_API DynamicTypeIterator; + class I2_BASE_API DynamicType : public Object { public: @@ -48,25 +53,21 @@ public: void RegisterObject(const DynamicObject::Ptr& object); static std::vector GetTypes(void); - std::vector GetObjects(void) const; + std::pair, DynamicTypeIterator > GetObjects(void); template - static std::vector > GetObjects(void) + static std::pair, DynamicTypeIterator > GetObjects(void) { - std::vector > objects; - - BOOST_FOREACH(const DynamicObject::Ptr& object, GetObjects(T::GetTypeName())) { - shared_ptr tobject = static_pointer_cast(object); - - ASSERT(tobject); - - objects.push_back(tobject); - } - - return objects; + DynamicType::Ptr type = GetByName(T::GetTypeName()); + return std::make_pair( + DynamicTypeIterator(type, 0), + DynamicTypeIterator(type, -1) + ); } private: + template friend class DynamicTypeIterator; + String m_Name; typedef std::map ObjectMap; @@ -81,8 +82,48 @@ private: static TypeMap& InternalGetTypeMap(void); static TypeVector& InternalGetTypeVector(void); static boost::mutex& GetStaticMutex(void); +}; - static std::vector GetObjects(const String& type); +template +class I2_BASE_API DynamicTypeIterator : public boost::iterator_facade, const shared_ptr, boost::forward_traversal_tag> +{ +public: + DynamicTypeIterator(const DynamicType::Ptr& type, int index) + : m_Type(type), m_Index(index) + { } + +private: + friend class boost::iterator_core_access; + + DynamicType::Ptr m_Type; + int m_Index; + mutable shared_ptr m_Current; + + void increment(void) { + m_Index++; + } + + bool equal(const DynamicTypeIterator& other) const + { + ASSERT(other.m_Type == m_Type); + + { + ObjectLock olock(m_Type); + + if ((other.m_Index == -1 || other.m_Index >= other.m_Type->m_ObjectVector.size()) && + (m_Index == -1 || m_Index >= m_Type->m_ObjectVector.size())) + return true; + } + + return (other.m_Index == m_Index); + } + + const shared_ptr& dereference(void) const + { + ObjectLock olock(m_Type); + m_Current = static_pointer_cast(*(m_Type->m_ObjectVector.begin() + m_Index)); + return m_Current; + } }; } diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 4d58a753e..9b976383c 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -341,8 +341,9 @@ bool ConfigItem::ActivateItems(ValidationType validate) if (validate != ValidateNone) { /* log stats for external parsers */ BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { - if (type->GetObjects().size() > 0) - Log(LogInformation, "config", "Checked " + Convert::ToString(type->GetObjects().size()) + " " + type->GetName() + "(s)."); + int count = std::distance(type->GetObjects().first, type->GetObjects().second); + if (count > 0) + Log(LogInformation, "config", "Checked " + Convert::ToString(count) + " " + type->GetName() + "(s)."); } } diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index b80e87c6a..444194a18 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -111,10 +111,10 @@ void DbConnection::ProgramStatusHandler(void) query3.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */ DbObject::OnQuery(query3); - InsertRuntimeVariable("total_services", static_cast(DynamicType::GetObjects().size())); - InsertRuntimeVariable("total_scheduled_services", static_cast(DynamicType::GetObjects().size())); - InsertRuntimeVariable("total_hosts", static_cast(DynamicType::GetObjects().size())); - InsertRuntimeVariable("total_scheduled_hosts", static_cast(DynamicType::GetObjects().size())); + InsertRuntimeVariable("total_services", std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second)); + InsertRuntimeVariable("total_scheduled_services", std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second)); + InsertRuntimeVariable("total_hosts", std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second)); + InsertRuntimeVariable("total_scheduled_hosts", std::distance(DynamicType::GetObjects().first, DynamicType::GetObjects().second)); Dictionary::Ptr vars = IcingaApplication::GetInstance()->GetVars();