Add item group monitoring data type framework

Include supported data types for item groups:
--Start event trigger
--Signal event trigger
--A countAtOrAbove condition
--A log_error action

Change-Id: I1ae5ba60e4d9c06155885d52d98a44b31fd73207
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/src/actions.hpp b/src/actions.hpp
new file mode 100644
index 0000000..e1f53ad
--- /dev/null
+++ b/src/actions.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+namespace action
+{
+
+using namespace phosphor::logging;
+
+inline auto log_error(const char* msg)
+{
+    return [=](auto&, auto&)
+    {
+        log<level::ERR>(msg);
+    };
+}
+
+} // namespace action
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/conditions.hpp b/src/conditions.hpp
new file mode 100644
index 0000000..54a6dc6
--- /dev/null
+++ b/src/conditions.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <algorithm>
+#include "data_types.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+namespace condition
+{
+
+template <typename T>
+auto countAtOrAbove(Group& items, const char* path, size_t count, T&& value)
+{
+    return [&items,
+            path,
+            count,
+            value = std::forward<T>(value)](T&& arg)
+    {
+        Group::iterator it =
+            std::find_if(items.begin(),
+                         items.end(),
+                         [&path](auto const& item)
+                         {
+                             return std::get<0>(item) == path;
+                         });
+        if (it != std::end(items))
+        {
+            std::get<1>(*it) = arg;
+        }
+        size_t condCount =
+            std::count_if(items.begin(),
+                          items.end(),
+                          [&value](auto const& item)
+                          {
+                              return std::get<1>(item) >= value;
+                          });
+        return condCount >= count;
+    };
+}
+
+} // namespace condition
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/data_types.hpp b/src/data_types.hpp
new file mode 100644
index 0000000..49406ea
--- /dev/null
+++ b/src/data_types.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <functional>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+class Monitor;
+
+using Value = int64_t;
+
+using Group = std::vector<std::tuple<std::string, Value>>;
+
+using Condition = std::function<bool(sdbusplus::bus::bus&,
+                                     sdbusplus::message::message&,
+                                     Monitor&)>;
+
+using Action = std::function<void(sdbusplus::bus::bus&,
+                                  Monitor&)>;
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/events.hpp b/src/events.hpp
new file mode 100644
index 0000000..b6de8de
--- /dev/null
+++ b/src/events.hpp
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "data_types.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+class Event : public std::vector<Condition>
+{
+    public:
+        enum class Trigger
+        {
+            START,
+            SIGNAL
+        };
+
+        Event() = delete;
+        Event(const Event&) = delete;
+        Event(Event&&) = delete;
+        Event& operator=(const Event&) = delete;
+        Event& operator=(Event&&) = delete;
+        virtual ~Event() = default;
+
+        Event(const std::vector<Condition>& conditions,
+              Trigger t) :
+                  std::vector<Condition>(conditions),
+                  trigger(t)
+        {
+            // Nothing to do here
+        }
+
+        Trigger trigger;
+};
+
+class StartEvent : public Event
+{
+    public:
+        StartEvent() = delete;
+        StartEvent(const StartEvent&) = delete;
+        StartEvent(StartEvent&&) = delete;
+        StartEvent& operator=(const StartEvent&) = delete;
+        StartEvent& operator=(StartEvent&&) = delete;
+        ~StartEvent() = default;
+
+        explicit StartEvent(const std::vector<Condition>& conditions) :
+            Event(conditions, Trigger::START)
+        {
+            // Nothing to do here
+        }
+};
+
+class SignalEvent : public Event
+{
+    public:
+        SignalEvent() = delete;
+        SignalEvent(const SignalEvent&) = delete;
+        SignalEvent(SignalEvent&&) = delete;
+        SignalEvent& operator=(const SignalEvent&) = delete;
+        SignalEvent& operator=(SignalEvent&&) = delete;
+        ~SignalEvent() = default;
+
+        SignalEvent(const char* signature,
+                    const std::vector<Condition>& conditions) :
+                        Event(conditions, Trigger::SIGNAL),
+                        signature(signature)
+        {
+            // Nothing to do here
+        }
+
+        const char* signature;
+};
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/functor.hpp b/src/functor.hpp
new file mode 100644
index 0000000..9353763
--- /dev/null
+++ b/src/functor.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "data_types.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+class Monitor;
+
+template <typename T>
+auto make_condition(T&& condition)
+{
+    return Condition(std::forward<T>(condition));
+}
+
+template <typename T>
+auto make_action(T&& action)
+{
+    return Action(std::forward<T>(action));
+}
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor