From f41f9b085d911cf2ff32795f1dce32bab6d286a8 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 4 Mar 2015 12:03:35 +0100 Subject: [PATCH] Implement support for the 'Limit' column in Livestatus fixes #8529 --- lib/livestatus/commandstable.cpp | 11 ++++++++--- lib/livestatus/commentstable.cpp | 12 ++++++++---- lib/livestatus/contactgroupstable.cpp | 3 ++- lib/livestatus/contactstable.cpp | 3 ++- lib/livestatus/downtimestable.cpp | 12 ++++++++---- lib/livestatus/endpointstable.cpp | 3 ++- lib/livestatus/hostgroupstable.cpp | 3 ++- lib/livestatus/hoststable.cpp | 6 ++++-- lib/livestatus/livestatusquery.cpp | 6 ++++-- lib/livestatus/livestatusquery.hpp | 1 + lib/livestatus/servicegroupstable.cpp | 3 ++- lib/livestatus/servicestable.cpp | 9 ++++++--- lib/livestatus/statehisttable.cpp | 3 ++- lib/livestatus/table.cpp | 12 +++++++++--- lib/livestatus/table.hpp | 6 +++--- lib/livestatus/timeperiodstable.cpp | 3 ++- 16 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/livestatus/commandstable.cpp b/lib/livestatus/commandstable.cpp index b36a8bd0d..349d6068b 100644 --- a/lib/livestatus/commandstable.cpp +++ b/lib/livestatus/commandstable.cpp @@ -61,13 +61,18 @@ String CommandsTable::GetPrefix(void) const void CommandsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjectsByType()) { - addRowFn(object, LivestatusGroupByNone, Empty); + if (!addRowFn(object, LivestatusGroupByNone, Empty)) + return; } + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjectsByType()) { - addRowFn(object, LivestatusGroupByNone, Empty); + if (!addRowFn(object, LivestatusGroupByNone, Empty)) + return; } + BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjectsByType()) { - addRowFn(object, LivestatusGroupByNone, Empty); + if (!addRowFn(object, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/commentstable.cpp b/lib/livestatus/commentstable.cpp index 4feb6b534..a9b297864 100644 --- a/lib/livestatus/commentstable.cpp +++ b/lib/livestatus/commentstable.cpp @@ -73,8 +73,10 @@ void CommentsTable::FetchRows(const AddRowFunction& addRowFn) String id; Comment::Ptr comment; BOOST_FOREACH(tie(id, comment), comments) { - if (Host::GetOwnerByCommentID(id) == host) - addRowFn(comment, LivestatusGroupByNone, Empty); + if (Host::GetOwnerByCommentID(id) == host) { + if (!addRowFn(comment, LivestatusGroupByNone, Empty)) + return; + } } } @@ -86,8 +88,10 @@ void CommentsTable::FetchRows(const AddRowFunction& addRowFn) String id; Comment::Ptr comment; BOOST_FOREACH(tie(id, comment), comments) { - if (Service::GetOwnerByCommentID(id) == service) - addRowFn(comment, LivestatusGroupByNone, Empty); + if (Service::GetOwnerByCommentID(id) == service) { + if (!addRowFn(comment, LivestatusGroupByNone, Empty)) + return; + } } } } diff --git a/lib/livestatus/contactgroupstable.cpp b/lib/livestatus/contactgroupstable.cpp index 604aa73b7..c1f9b6c03 100644 --- a/lib/livestatus/contactgroupstable.cpp +++ b/lib/livestatus/contactgroupstable.cpp @@ -50,7 +50,8 @@ String ContactGroupsTable::GetPrefix(void) const void ContactGroupsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const UserGroup::Ptr& ug, DynamicType::GetObjectsByType()) { - addRowFn(ug, LivestatusGroupByNone, Empty); + if (!addRowFn(ug, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/contactstable.cpp b/lib/livestatus/contactstable.cpp index e6400e5ee..e557ae89f 100644 --- a/lib/livestatus/contactstable.cpp +++ b/lib/livestatus/contactstable.cpp @@ -71,7 +71,8 @@ String ContactsTable::GetPrefix(void) const void ContactsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const User::Ptr& user, DynamicType::GetObjectsByType()) { - addRowFn(user, LivestatusGroupByNone, Empty); + if (!addRowFn(user, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/downtimestable.cpp b/lib/livestatus/downtimestable.cpp index 49bdd3933..e9b8ed7c9 100644 --- a/lib/livestatus/downtimestable.cpp +++ b/lib/livestatus/downtimestable.cpp @@ -73,8 +73,10 @@ void DowntimesTable::FetchRows(const AddRowFunction& addRowFn) String id; Downtime::Ptr downtime; BOOST_FOREACH(boost::tie(id, downtime), downtimes) { - if (Host::GetOwnerByDowntimeID(id) == host) - addRowFn(downtime, LivestatusGroupByNone, Empty); + if (Host::GetOwnerByDowntimeID(id) == host) { + if (!addRowFn(downtime, LivestatusGroupByNone, Empty)) + return; + } } } @@ -86,8 +88,10 @@ void DowntimesTable::FetchRows(const AddRowFunction& addRowFn) String id; Downtime::Ptr downtime; BOOST_FOREACH(boost::tie(id, downtime), downtimes) { - if (Service::GetOwnerByDowntimeID(id) == service) - addRowFn(downtime, LivestatusGroupByNone, Empty); + if (Service::GetOwnerByDowntimeID(id) == service) { + if (!addRowFn(downtime, LivestatusGroupByNone, Empty)) + return; + } } } } diff --git a/lib/livestatus/endpointstable.cpp b/lib/livestatus/endpointstable.cpp index be546685f..a5cece345 100644 --- a/lib/livestatus/endpointstable.cpp +++ b/lib/livestatus/endpointstable.cpp @@ -61,7 +61,8 @@ String EndpointsTable::GetPrefix(void) const void EndpointsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjectsByType()) { - addRowFn(endpoint, LivestatusGroupByNone, Empty); + if (!addRowFn(endpoint, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/hostgroupstable.cpp b/lib/livestatus/hostgroupstable.cpp index ee1f6c4c0..01782aa9a 100644 --- a/lib/livestatus/hostgroupstable.cpp +++ b/lib/livestatus/hostgroupstable.cpp @@ -74,7 +74,8 @@ String HostGroupsTable::GetPrefix(void) const void HostGroupsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const HostGroup::Ptr& hg, DynamicType::GetObjectsByType()) { - addRowFn(hg, LivestatusGroupByNone, Empty); + if (!addRowFn(hg, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/hoststable.cpp b/lib/livestatus/hoststable.cpp index f99549034..bff1b7de0 100644 --- a/lib/livestatus/hoststable.cpp +++ b/lib/livestatus/hoststable.cpp @@ -190,12 +190,14 @@ void HostsTable::FetchRows(const AddRowFunction& addRowFn) BOOST_FOREACH(const HostGroup::Ptr& hg, DynamicType::GetObjectsByType()) { BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) { /* the caller must know which groupby type and value are set for this row */ - addRowFn(host, LivestatusGroupByHostGroup, hg); + if (!addRowFn(host, LivestatusGroupByHostGroup, hg)) + return; } } } else { BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjectsByType()) { - addRowFn(host, LivestatusGroupByNone, Empty); + if (!addRowFn(host, LivestatusGroupByNone, Empty)) + return; } } } diff --git a/lib/livestatus/livestatusquery.cpp b/lib/livestatus/livestatusquery.cpp index 70c707f3b..9d904805e 100644 --- a/lib/livestatus/livestatusquery.cpp +++ b/lib/livestatus/livestatusquery.cpp @@ -84,7 +84,7 @@ static void InitScriptFrameCleanup(void) INITIALIZE_ONCE(InitScriptFrameCleanup); LivestatusQuery::LivestatusQuery(const std::vector& lines, const String& compat_log_path) - : m_KeepAlive(false), m_OutputFormat("csv"), m_ColumnHeaders(true), m_ErrorCode(0), + : m_KeepAlive(false), m_OutputFormat("csv"), m_ColumnHeaders(true), m_Limit(-1), m_ErrorCode(0), m_LogTimeFrom(0), m_LogTimeUntil(static_cast(Utility::GetTime())) { if (lines.size() == 0) { @@ -182,6 +182,8 @@ LivestatusQuery::LivestatusQuery(const std::vector& lines, const String& m_Separators[3] = String(1, static_cast(Convert::ToLong(separators[3]))); } else if (header == "ColumnHeaders") m_ColumnHeaders = (params == "on"); + else if (header == "Limit") + m_Limit = Convert::ToLong(params); else if (header == "Filter") { Filter::Ptr filter = ParseFilter(params, m_LogTimeFrom, m_LogTimeUntil); @@ -495,7 +497,7 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream) return; } - std::vector objects = table->FilterRows(m_Filter); + std::vector objects = table->FilterRows(m_Filter, m_Limit); std::vector columns; if (m_Columns.size() > 0) diff --git a/lib/livestatus/livestatusquery.hpp b/lib/livestatus/livestatusquery.hpp index a7f991637..9b5c4ad09 100644 --- a/lib/livestatus/livestatusquery.hpp +++ b/lib/livestatus/livestatusquery.hpp @@ -81,6 +81,7 @@ private: String m_OutputFormat; bool m_ColumnHeaders; + int m_Limit; String m_ResponseHeader; diff --git a/lib/livestatus/servicegroupstable.cpp b/lib/livestatus/servicegroupstable.cpp index a7c4ac64c..c1f81af2b 100644 --- a/lib/livestatus/servicegroupstable.cpp +++ b/lib/livestatus/servicegroupstable.cpp @@ -65,7 +65,8 @@ String ServiceGroupsTable::GetPrefix(void) const void ServiceGroupsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const ServiceGroup::Ptr& sg, DynamicType::GetObjectsByType()) { - addRowFn(sg, LivestatusGroupByNone, Empty); + if (!addRowFn(sg, LivestatusGroupByNone, Empty)) + return; } } diff --git a/lib/livestatus/servicestable.cpp b/lib/livestatus/servicestable.cpp index b4576c527..729141143 100644 --- a/lib/livestatus/servicestable.cpp +++ b/lib/livestatus/servicestable.cpp @@ -170,7 +170,8 @@ void ServicesTable::FetchRows(const AddRowFunction& addRowFn) BOOST_FOREACH(const ServiceGroup::Ptr& sg, DynamicType::GetObjectsByType()) { BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) { /* the caller must know which groupby type and value are set for this row */ - addRowFn(service, LivestatusGroupByServiceGroup, sg); + if (!addRowFn(service, LivestatusGroupByServiceGroup, sg)) + return; } } } else if (GetGroupByType() == LivestatusGroupByHostGroup) { @@ -180,13 +181,15 @@ void ServicesTable::FetchRows(const AddRowFunction& addRowFn) ObjectLock ylock(host); BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) { /* the caller must know which groupby type and value are set for this row */ - addRowFn(service, LivestatusGroupByHostGroup, hg); + if (!addRowFn(service, LivestatusGroupByHostGroup, hg)) + return; } } } } else { BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType()) { - addRowFn(service, LivestatusGroupByNone, Empty); + if (!addRowFn(service, LivestatusGroupByNone, Empty)) + return; } } } diff --git a/lib/livestatus/statehisttable.cpp b/lib/livestatus/statehisttable.cpp index a9008512c..e0fd0659b 100644 --- a/lib/livestatus/statehisttable.cpp +++ b/lib/livestatus/statehisttable.cpp @@ -271,7 +271,8 @@ void StateHistTable::FetchRows(const AddRowFunction& addRowFn) BOOST_FOREACH(boost::tie(checkable, boost::tuples::ignore), m_CheckablesCache) { BOOST_FOREACH(const Dictionary::Ptr& state_hist_bag, m_CheckablesCache[checkable]) { /* pass a dictionary from state history array */ - addRowFn(state_hist_bag, LivestatusGroupByNone, Empty); + if (!addRowFn(state_hist_bag, LivestatusGroupByNone, Empty)) + return; } } } diff --git a/lib/livestatus/table.cpp b/lib/livestatus/table.cpp index 15e5e3c38..0f8e0408f 100644 --- a/lib/livestatus/table.cpp +++ b/lib/livestatus/table.cpp @@ -124,17 +124,20 @@ std::vector Table::GetColumnNames(void) const return names; } -std::vector Table::FilterRows(const Filter::Ptr& filter) +std::vector Table::FilterRows(const Filter::Ptr& filter, int limit) { std::vector rs; - FetchRows(boost::bind(&Table::FilteredAddRow, this, boost::ref(rs), filter, _1, _2, _3)); + FetchRows(boost::bind(&Table::FilteredAddRow, this, boost::ref(rs), filter, limit, _1, _2, _3)); return rs; } -void Table::FilteredAddRow(std::vector& rs, const Filter::Ptr& filter, const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject) +bool Table::FilteredAddRow(std::vector& rs, const Filter::Ptr& filter, int limit, const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject) { + if (limit != -1 && rs.size() == limit) + return false; + if (!filter || filter->Apply(this, row)) { LivestatusRowValue rval; rval.Row = row; @@ -142,7 +145,10 @@ void Table::FilteredAddRow(std::vector& rs, const Filter::Pt rval.GroupByObject = groupByObject; rs.push_back(rval); + } + + return true; } Value Table::ZeroAccessor(const Value&) diff --git a/lib/livestatus/table.hpp b/lib/livestatus/table.hpp index ee86bbd84..e69cdc21b 100644 --- a/lib/livestatus/table.hpp +++ b/lib/livestatus/table.hpp @@ -36,7 +36,7 @@ struct LivestatusRowValue { }; -typedef boost::function AddRowFunction; +typedef boost::function AddRowFunction; class Filter; @@ -53,7 +53,7 @@ public: virtual String GetName(void) const = 0; virtual String GetPrefix(void) const = 0; - std::vector FilterRows(const intrusive_ptr& filter); + std::vector FilterRows(const intrusive_ptr& filter, int limit = -1); void AddColumn(const String& name, const Column& column); Column GetColumn(const String& name) const; @@ -78,7 +78,7 @@ protected: private: std::map m_Columns; - void FilteredAddRow(std::vector& rs, const intrusive_ptr& filter, const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject); + bool FilteredAddRow(std::vector& rs, const intrusive_ptr& filter, int limit, const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject); }; } diff --git a/lib/livestatus/timeperiodstable.cpp b/lib/livestatus/timeperiodstable.cpp index 66de70bb2..31e1ed5ab 100644 --- a/lib/livestatus/timeperiodstable.cpp +++ b/lib/livestatus/timeperiodstable.cpp @@ -55,7 +55,8 @@ String TimePeriodsTable::GetPrefix(void) const void TimePeriodsTable::FetchRows(const AddRowFunction& addRowFn) { BOOST_FOREACH(const TimePeriod::Ptr& tp, DynamicType::GetObjectsByType()) { - addRowFn(tp, LivestatusGroupByNone, Empty); + if (!addRowFn(tp, LivestatusGroupByNone, Empty)) + return; } }