]> granicus.if.org Git - icinga2/commitdiff
Implement attribute filters.
authorGunnar Beutner <gunnar@beutner.name>
Sun, 10 Mar 2013 14:11:32 +0000 (15:11 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Sun, 10 Mar 2013 14:11:32 +0000 (15:11 +0100)
20 files changed:
components/livestatus/andfilter.cpp
components/livestatus/andfilter.h
components/livestatus/attributefilter.cpp [new file with mode: 0644]
components/livestatus/attributefilter.h [new file with mode: 0644]
components/livestatus/combinerfilter.cpp [new file with mode: 0644]
components/livestatus/combinerfilter.h [new file with mode: 0644]
components/livestatus/filter.h
components/livestatus/i2-livestatus.h
components/livestatus/livestatus.vcxproj
components/livestatus/livestatus.vcxproj.filters
components/livestatus/negatefilter.cpp [new file with mode: 0644]
components/livestatus/negatefilter.h [new file with mode: 0644]
components/livestatus/orfilter.cpp
components/livestatus/orfilter.h
components/livestatus/query.cpp
components/livestatus/query.h
components/livestatus/table.cpp
components/livestatus/table.h
lib/base/qstring.cpp
lib/base/qstring.h

index 4e56fb533763a374d07fab0b60d1a48cbc6ee9fd..087f0d3d0e898ede64a50850ea67d24403f24906 100644 (file)
@@ -25,17 +25,12 @@ using namespace livestatus;
 AndFilter::AndFilter(void)
 { }
 
-bool AndFilter::Apply(const Object::Ptr& object)
+bool AndFilter::Apply(const Table::Ptr& table, const Object::Ptr& object)
 {
        BOOST_FOREACH(const Filter::Ptr& filter, m_Filters) {
-               if (!filter->Apply(object))
+               if (!filter->Apply(table, object))
                        return false;
        }
 
        return true;
 }
-
-void AndFilter::AddSubFilter(const Filter::Ptr& filter)
-{
-       m_Filters.push_back(filter);
-}
\ No newline at end of file
index dac34afc8aa732cabbc084bd6f6fe6457ba1ff9e..748ef85f155c442669ff2575a9e9072a8904331c 100644 (file)
@@ -26,7 +26,7 @@ namespace livestatus
 /**
  * @ingroup livestatus
  */
-class AndFilter : public Filter
+class AndFilter : public CombinerFilter
 {
 public:
        typedef shared_ptr<AndFilter> Ptr;
@@ -34,12 +34,7 @@ public:
 
        AndFilter(void);
 
-       virtual bool Apply(const Object::Ptr& object);
-
-       void AddSubFilter(const Filter::Ptr& filter);
-
-private:
-       vector<Filter::Ptr> m_Filters;
+       virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object);
 };
 
 }
diff --git a/components/livestatus/attributefilter.cpp b/components/livestatus/attributefilter.cpp
new file mode 100644 (file)
index 0000000..cc6e93d
--- /dev/null
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-livestatus.h"
+
+using namespace icinga;
+using namespace livestatus;
+
+AttributeFilter::AttributeFilter(const String& column, const String& op, const String& operand)
+       : m_Column(column), m_Operator(op), m_Operand(operand)
+{ }
+
+bool AttributeFilter::Apply(const Table::Ptr& table, const Object::Ptr& object)
+{
+       Table::ColumnAccessor accessor = table->GetColumn(m_Column);
+
+       if (accessor.empty())
+               BOOST_THROW_EXCEPTION(invalid_argument("Filter expression uses unknown column '" + m_Column + "'"));
+
+       Value value = accessor(object);
+
+       if (value.IsObjectType<Array>()) {
+               if (m_Operator == ">=") {
+                       Array::Ptr array = value;
+                       BOOST_FOREACH(const String& item, array) {
+                               if (item == m_Operand)
+                                       return true; /* Item found in list. */
+                       }
+
+                       return false; /* Item not found in list. */
+               } else {
+                       BOOST_THROW_EXCEPTION(invalid_argument("Invalid operator for column '" + m_Column + "': " + m_Operator + " (expected '>=')."));
+               }
+       } else {
+               if (m_Operator == "=") {
+                       if (value.GetType() == ValueNumber)
+                               return (static_cast<double>(value) == Convert::ToDouble(m_Operand));
+                       else
+                               return (static_cast<String>(value) == m_Operand);
+               } else if (m_Operator == "~") {
+
+               } else if (m_Operator == "=~") {
+                       return string_iless()(value, m_Operand);
+               } else if (m_Operator == "~~") {
+
+               } else if (m_Operator == "<") {
+                       if (value.GetType() == ValueNumber)
+                               return (static_cast<double>(value) < Convert::ToDouble(m_Operand));
+                       else
+                               return (static_cast<String>(value) < m_Operand);
+               } else if (m_Operator == ">") {
+                       if (value.GetType() == ValueNumber)
+                               return (static_cast<double>(value) > Convert::ToDouble(m_Operand));
+                       else
+                               return (static_cast<String>(value) > m_Operand);
+               } else if (m_Operator == "<=") {
+                       if (value.GetType() == ValueNumber)
+                               return (static_cast<double>(value) <= Convert::ToDouble(m_Operand));
+                       else
+                               return (static_cast<String>(value) <= m_Operand);
+               } else if (m_Operator == ">=") {
+                       if (value.GetType() == ValueNumber)
+                               return (static_cast<double>(value) >= Convert::ToDouble(m_Operand));
+                       else
+                               return (static_cast<String>(value) >= m_Operand);
+               } else {
+                       BOOST_THROW_EXCEPTION(invalid_argument("Unknown operator for column '" + m_Column + "': " + m_Operator));
+               }
+       }
+
+       return false;
+}
diff --git a/components/livestatus/attributefilter.h b/components/livestatus/attributefilter.h
new file mode 100644 (file)
index 0000000..eb508dc
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef ATTRIBUTEFILTER_H
+#define ATTRIBUTEFILTER_H
+
+namespace livestatus
+{
+
+/**
+ * @ingroup livestatus
+ */
+class AttributeFilter : public Filter
+{
+public:
+       typedef shared_ptr<AttributeFilter> Ptr;
+       typedef weak_ptr<AttributeFilter> WeakPtr;
+
+       AttributeFilter(const String& column, const String& op, const String& operand);
+
+       virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object);
+
+protected:
+       String m_Column;
+       String m_Operator;
+       String m_Operand;
+};
+
+}
+
+#endif /* FILTER_H */
diff --git a/components/livestatus/combinerfilter.cpp b/components/livestatus/combinerfilter.cpp
new file mode 100644 (file)
index 0000000..ce83580
--- /dev/null
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-livestatus.h"
+
+using namespace icinga;
+using namespace livestatus;
+
+CombinerFilter::CombinerFilter(void)
+{ }
+
+void CombinerFilter::AddSubFilter(const Filter::Ptr& filter)
+{
+       m_Filters.push_back(filter);
+}
\ No newline at end of file
diff --git a/components/livestatus/combinerfilter.h b/components/livestatus/combinerfilter.h
new file mode 100644 (file)
index 0000000..0e92ade
--- /dev/null
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef COMBINERFILTER_H
+#define COMBINERFILTER_H
+
+namespace livestatus
+{
+
+/**
+ * @ingroup livestatus
+ */
+class CombinerFilter : public Filter
+{
+public:
+       typedef shared_ptr<CombinerFilter> Ptr;
+       typedef weak_ptr<CombinerFilter> WeakPtr;
+
+       CombinerFilter(void);
+
+       void AddSubFilter(const Filter::Ptr& filter);
+
+protected:
+       vector<Filter::Ptr> m_Filters;
+};
+
+}
+
+#endif /* COMBINERFILTER_H */
index 0146534219f73d66ba508700e4a565bde08ff8dd..d60612075487c0c486c863fa55e0fc06f6ca2cd8 100644 (file)
@@ -32,7 +32,7 @@ public:
        typedef shared_ptr<Filter> Ptr;
        typedef weak_ptr<Filter> WeakPtr;
 
-       virtual bool Apply(const Object::Ptr& object) = 0;
+       virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object) = 0;
 
 protected:
        Filter(void);
index 73ebd466330a139ef2ef5d9e5246a603d822b552..4c7a2fdb654693cdf7f243e198f9983a595d9547 100644 (file)
 using namespace icinga;
 
 #include "connection.h"
-#include "query.h"
+#include "table.h"
 #include "filter.h"
+#include "combinerfilter.h"
 #include "orfilter.h"
 #include "andfilter.h"
-#include "table.h"
+#include "negatefilter.h"
+#include "attributefilter.h"
+#include "query.h"
 #include "statustable.h"
 #include "contactgroupstable.h"
 #include "contactstable.h"
index ff9c42e56885c4735605051c9c1d64c3be4fe04f..2e6c91f97611143f598b724d932c07b6fd3ff8f9 100644 (file)
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="andfilter.h" />
+    <ClInclude Include="attributefilter.h" />
+    <ClInclude Include="combinerfilter.h" />
     <ClInclude Include="contactgroupstable.h" />
     <ClInclude Include="contactstable.h" />
     <ClInclude Include="filter.h" />
     <ClInclude Include="i2-livestatus.h" />
     <ClInclude Include="component.h" />
     <ClInclude Include="connection.h" />
+    <ClInclude Include="negatefilter.h" />
     <ClInclude Include="orfilter.h" />
     <ClInclude Include="query.h" />
     <ClInclude Include="statustable.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="andfilter.cpp" />
+    <ClCompile Include="attributefilter.cpp" />
+    <ClCompile Include="combinerfilter.cpp" />
     <ClCompile Include="component.cpp" />
     <ClCompile Include="connection.cpp" />
     <ClCompile Include="contactgroupstable.cpp" />
     <ClCompile Include="contactstable.cpp" />
     <ClCompile Include="filter.cpp" />
+    <ClCompile Include="negatefilter.cpp" />
     <ClCompile Include="orfilter.cpp" />
     <ClCompile Include="query.cpp" />
     <ClCompile Include="statustable.cpp" />
index 327e12117ba5dea9f47b800804a94f43128ce7c2..69c5274cac7fd2cca4a38a0c596aca1e38c73f72 100644 (file)
     <ClInclude Include="andfilter.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="attributefilter.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="negatefilter.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="combinerfilter.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="component.cpp">
     <ClCompile Include="andfilter.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="attributefilter.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="negatefilter.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="combinerfilter.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/components/livestatus/negatefilter.cpp b/components/livestatus/negatefilter.cpp
new file mode 100644 (file)
index 0000000..ee02a4d
--- /dev/null
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-livestatus.h"
+
+using namespace icinga;
+using namespace livestatus;
+
+NegateFilter::NegateFilter(const Filter::Ptr& inner)
+       : m_Inner(inner)
+{ }
+
+bool NegateFilter::Apply(const Table::Ptr& table, const Object::Ptr& object)
+{
+       return !m_Inner->Apply(table, object);
+}
diff --git a/components/livestatus/negatefilter.h b/components/livestatus/negatefilter.h
new file mode 100644 (file)
index 0000000..f321789
--- /dev/null
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef NEGATEFILTER_H
+#define NEGATEFILTER_H
+
+namespace livestatus
+{
+
+/**
+ * @ingroup livestatus
+ */
+class NegateFilter : public Filter
+{
+public:
+       typedef shared_ptr<NegateFilter> Ptr;
+       typedef weak_ptr<NegateFilter> WeakPtr;
+
+       NegateFilter(const Filter::Ptr& inner);
+
+       virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object);
+
+private:
+       Filter::Ptr m_Inner;
+};
+
+}
+
+#endif /* NEGATEFILTER_H */
index 5989610d31e12127842540a107ba1046122e00ce..a05bdf3076457ff56a3f10e0fbc08983371af431 100644 (file)
@@ -25,20 +25,15 @@ using namespace livestatus;
 OrFilter::OrFilter(void)
 { }
 
-bool OrFilter::Apply(const Object::Ptr& object)
+bool OrFilter::Apply(const Table::Ptr& table, const Object::Ptr& object)
 {
        if (m_Filters.empty())
                return true;
 
        BOOST_FOREACH(const Filter::Ptr& filter, m_Filters) {
-               if (filter->Apply(object))
+               if (filter->Apply(table, object))
                        return true;
        }
 
        return false;
 }
-
-void OrFilter::AddSubFilter(const Filter::Ptr& filter)
-{
-       m_Filters.push_back(filter);
-}
\ No newline at end of file
index 0433354e1916c5d00f82ce560612bba4763ad4e1..95ff502f5c80b14f75ca37a1bdf3770ba033014f 100644 (file)
@@ -26,7 +26,7 @@ namespace livestatus
 /**
  * @ingroup livestatus
  */
-class OrFilter : public Filter
+class OrFilter : public CombinerFilter
 {
 public:
        typedef shared_ptr<OrFilter> Ptr;
@@ -34,12 +34,7 @@ public:
 
        OrFilter(void);
 
-       virtual bool Apply(const Object::Ptr& object);
-
-       void AddSubFilter(const Filter::Ptr& filter);
-
-private:
-       vector<Filter::Ptr> m_Filters;
+       virtual bool Apply(const Table::Ptr& table, const Object::Ptr& object);
 };
 
 }
index 70ffa964f3ffce370958fe8effec04bcca38e459..8e372cde22220a43b7badce699f9212d7eb9f45b 100644 (file)
@@ -42,10 +42,15 @@ Query::Query(const vector<String>& lines)
        } else if (m_Verb == "GET") {
                m_Table = target;
        } else {
-               BOOST_THROW_EXCEPTION(runtime_error("Unknown livestatus verb: " + m_Verb));
+               m_Verb = "ERROR";
+               m_ErrorCode = 452;
+               m_ErrorMessage = "Unknown livestatus verb: " + m_Verb;
+               return;
        }
 
-       for (int i = 1; i < lines.size(); i++) {
+       deque<Filter::Ptr> filters, stats;
+
+       for (unsigned int i = 1; i < lines.size(); i++) {
                line = lines[i];
 
                size_t col_index = line.FindFirstOf(":");
@@ -58,12 +63,66 @@ Query::Query(const vector<String>& lines)
                        m_OutputFormat = params;
                else if (header == "Columns")
                        m_Columns = params.Split(is_any_of(" "));
+               else if (header == "ColumnHeaders")
+                       m_ColumnHeaders = (params == "on");
+               else if (header == "Filter") {
+                       vector<String> tokens = params.Split(is_any_of(" "));
+
+                       if (tokens.size() < 3) {
+                               m_Verb = "ERROR";
+                               m_ErrorCode = 452;
+                               m_ErrorMessage = "Expected 3 parameters in the filter specification.";
+                               return;
+                       }
+
+                       String op = tokens[1];
+                       bool negate = false;
+
+                       if (op == "!=") {
+                               op = "=";
+                               negate = true;
+                       } else if (op == "!~") {
+                               op = "~";
+                               negate = true;
+                       } else if (op == "!=~") {
+                               op = "=~";
+                               negate = true;
+                       } else if (op == "!~~") {
+                               op = "~~";
+                               negate = true;
+                       }
+
+                       Filter::Ptr filter = boost::make_shared<AttributeFilter>(tokens[0], op, tokens[2]);
+
+                       if (negate)
+                               filter = boost::make_shared<NegateFilter>(filter);
+
+                       filters.push_back(filter);
+               } else if (header == "Or" || header == "And") {
+                       int num = Convert::ToLong(params);
+                       CombinerFilter::Ptr filter;
+
+                       if (header == "Or")
+                               filter = boost::make_shared<OrFilter>();
+                       else
+                               filter = boost::make_shared<AndFilter>();
+
+                       while (!filters.empty() && num--) {
+                               filter->AddSubFilter(filters.back());
+                               filters.pop_back();
+                       }
+
+                       filters.push_back(filter);
+               }
        }
+
+       m_Filters.swap(filters);
+       m_Stats.swap(stats);
 }
 
 void Query::PrintResultSet(ostream& fp, const vector<String>& columns, const Array::Ptr& rs)
 {
-       if (m_OutputFormat == "csv" && m_Columns.size() == 0) {
+       if (m_OutputFormat == "csv" && m_Columns.size() == 0 && m_ColumnHeaders) {
                bool first = true;
 
                BOOST_FOREACH(const String& column, columns) {
@@ -113,7 +172,15 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream)
                return;
        }
 
-       vector<Object::Ptr> objects = table->FilterRows(Filter::Ptr());
+       if (m_Filters.size() > 1)
+               SendResponse(stream, 452, "There must not be more than one top-level filter expression.");
+
+       Filter::Ptr filter;
+
+       if (!m_Filters.empty())
+               filter = m_Filters[0];
+
+       vector<Object::Ptr> objects = table->FilterRows(filter);
        vector<String> columns;
        
        if (m_Columns.size() > 0)
@@ -149,13 +216,9 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream)
 
 void Query::ExecuteCommandHelper(const Stream::Ptr& stream)
 {
-       try {
-               Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command);
-               ExternalCommandProcessor::Execute(m_Command);
-               SendResponse(stream, 200, "");
-       } catch (const std::exception& ex) {
-               SendResponse(stream, 452, diagnostic_information(ex));
-       }
+       Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command);
+       ExternalCommandProcessor::Execute(m_Command);
+       SendResponse(stream, 200, "");
 }
 
 void Query::ExecuteErrorHelper(const Stream::Ptr& stream)
@@ -185,6 +248,7 @@ void Query::PrintFixed16(const Stream::Ptr& stream, int code, const String& data
 
 void Query::Execute(const Stream::Ptr& stream)
 {
+       try {
        Logger::Write(LogInformation, "livestatus", "Executing livestatus query: " + m_Verb);
 
        if (m_Verb == "GET")
@@ -195,6 +259,9 @@ void Query::Execute(const Stream::Ptr& stream)
                ExecuteErrorHelper(stream);
        else
                BOOST_THROW_EXCEPTION(runtime_error("Invalid livestatus query verb."));
+       } catch (const std::exception& ex) {
+               SendResponse(stream, 452, boost::diagnostic_information(ex));
+       }
 
        if (!m_KeepAlive)
                stream->Close();
index 940a80884326a3d16dfc9d421e96175c3e50a48d..247812632151fddc15e477aa5f63b7032c5eb295 100644 (file)
@@ -45,6 +45,9 @@ private:
        String m_Table;
        vector<String> m_Columns;
 
+       deque<Filter::Ptr> m_Filters;
+       deque<Filter::Ptr> m_Stats;
+
        String m_OutputFormat;
        bool m_ColumnHeaders;
        int m_Limit;
index 518c9c9ca9d2faf7b0eb5d8435d9373852a5bb90..6fd00ab9e412888277ff294cb4418a70bd895e30 100644 (file)
@@ -68,14 +68,14 @@ vector<Object::Ptr> Table::FilterRows(const Filter::Ptr& filter)
 {
        vector<Object::Ptr> rs;
 
-       FetchRows(boost::bind(&Table::FilteredAddRow, boost::ref(rs), filter, _1));
+       FetchRows(boost::bind(&Table::FilteredAddRow, this, boost::ref(rs), filter, _1));
 
        return rs;
 }
 
 void Table::FilteredAddRow(vector<Object::Ptr>& rs, const Filter::Ptr& filter, const Object::Ptr& object)
 {
-       if (!filter || filter->Apply(object))
+       if (!filter || filter->Apply(GetSelf(), object))
                rs.push_back(object);
 }
 
index 82a9f9ce50df1947503ce385f43b65e4aa19ede1..3f7b0cca747527033716b0aaab36c145b2936881 100644 (file)
@@ -23,6 +23,8 @@
 namespace livestatus
 {
 
+class Filter;
+
 /**
  * @ingroup livestatus
  */
@@ -38,7 +40,7 @@ public:
        
        virtual String GetName(void) const = 0;
 
-       vector<Object::Ptr> FilterRows(const Filter::Ptr& filter);
+       vector<Object::Ptr> FilterRows(const shared_ptr<Filter>& filter);
 
        ColumnAccessor GetColumn(const String& name) const;
        vector<String> GetColumnNames(void) const;
@@ -59,7 +61,7 @@ protected:
 private:
        map<String, ColumnAccessor> m_Columns;
 
-       static void FilteredAddRow(vector<Object::Ptr>& rs, const Filter::Ptr& filter, const Object::Ptr& object);
+       void FilteredAddRow(vector<Object::Ptr>& rs, const shared_ptr<Filter>& filter, const Object::Ptr& object);
 };
 
 }
index e87846086f5f8111415108837fbebb96a7513019..883fe9f5c0508c7db045db30397e8dcdb377158a 100644 (file)
@@ -212,39 +212,74 @@ bool icinga::operator==(const char *lhs, const String& rhs)
        return lhs == static_cast<std::string>(rhs);
 }
 
-bool icinga::operator!=(const String& lhs, const String& rhs)
+bool icinga::operator<(const String& lhs, const char *rhs)
 {
-       return static_cast<std::string>(lhs) != static_cast<std::string>(rhs);
+       return static_cast<std::string>(lhs) < rhs;
 }
 
-bool icinga::operator!=(const String& lhs, const char *rhs)
+bool icinga::operator<(const char *lhs, const String& rhs)
 {
-       return static_cast<std::string>(lhs) != rhs;
+       return lhs < static_cast<std::string>(rhs);
 }
 
-bool icinga::operator!=(const char *lhs, const String& rhs)
+bool icinga::operator>(const String& lhs, const String& rhs)
 {
-       return lhs != static_cast<std::string>(rhs);
+       return static_cast<std::string>(lhs) > static_cast<std::string>(rhs);
 }
 
-bool icinga::operator<(const String& lhs, const char *rhs)
+bool icinga::operator>(const String& lhs, const char *rhs)
 {
-       return static_cast<std::string>(lhs) < rhs;
+       return static_cast<std::string>(lhs) > rhs;
 }
 
-bool icinga::operator<(const char *lhs, const String& rhs)
+bool icinga::operator>(const char *lhs, const String& rhs)
 {
-       return lhs < static_cast<std::string>(rhs);
+       return lhs > static_cast<std::string>(rhs);
 }
 
-bool icinga::operator>(const String& lhs, const char *rhs)
+bool icinga::operator<=(const String& lhs, const String& rhs)
 {
-       return static_cast<std::string>(lhs) > rhs;
+       return static_cast<std::string>(lhs) <= static_cast<std::string>(rhs);
 }
 
-bool icinga::operator>(const char *lhs, const String& rhs)
+bool icinga::operator<=(const String& lhs, const char *rhs)
 {
-       return lhs > static_cast<std::string>(rhs);
+       return static_cast<std::string>(lhs) <= rhs;
+}
+
+bool icinga::operator<=(const char *lhs, const String& rhs)
+{
+       return lhs <= static_cast<std::string>(rhs);
+}
+
+bool icinga::operator>=(const String& lhs, const String& rhs)
+{
+       return static_cast<std::string>(lhs) >= static_cast<std::string>(rhs);
+}
+
+bool icinga::operator>=(const String& lhs, const char *rhs)
+{
+       return static_cast<std::string>(lhs) >= rhs;
+}
+
+bool icinga::operator>=(const char *lhs, const String& rhs)
+{
+       return lhs >= static_cast<std::string>(rhs);
+}
+
+bool icinga::operator!=(const String& lhs, const String& rhs)
+{
+       return static_cast<std::string>(lhs) != static_cast<std::string>(rhs);
+}
+
+bool icinga::operator!=(const String& lhs, const char *rhs)
+{
+       return static_cast<std::string>(lhs) != rhs;
+}
+
+bool icinga::operator!=(const char *lhs, const String& rhs)
+{
+       return lhs != static_cast<std::string>(rhs);
 }
 
 String::Iterator icinga::range_begin(String& x)
index 4465a2104e8ac2d0a0dcf678aa8c1b7facb8805b..2afd6180481e1608182943b19201beca0736b4a1 100644 (file)
@@ -122,9 +122,19 @@ I2_BASE_API bool operator!=(const char *lhs, const String& rhs);
 
 I2_BASE_API bool operator<(const String& lhs, const char *rhs);
 I2_BASE_API bool operator<(const char *lhs, const String& rhs);
+
+I2_BASE_API bool operator>(const String& lhs, const String& rhs);
 I2_BASE_API bool operator>(const String& lhs, const char *rhs);
 I2_BASE_API bool operator>(const char *lhs, const String& rhs);
 
+I2_BASE_API bool operator<=(const String& lhs, const String& rhs);
+I2_BASE_API bool operator<=(const String& lhs, const char *rhs);
+I2_BASE_API bool operator<=(const char *lhs, const String& rhs);
+
+I2_BASE_API bool operator>=(const String& lhs, const String& rhs);
+I2_BASE_API bool operator>=(const String& lhs, const char *rhs);
+I2_BASE_API bool operator>=(const char *lhs, const String& rhs);
+
 I2_BASE_API String::Iterator range_begin(String& x);
 I2_BASE_API String::ConstIterator range_begin(const String& x);
 I2_BASE_API String::Iterator range_end(String& x);