Capture dump when an error with the name InternalFailure is logged

Change-Id: I2a362b674022dbe1ea8bfe16876d0416f87d0af1
Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 638cb0f..f2bec7c 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,8 @@
 	dump_internal.hpp \
 	dump_manager.hpp \
 	dump_utils.hpp \
-	watch.hpp
+	watch.hpp \
+	elog_watch.hpp
 
 nobase_nodist_include_HEADERS = \
 	xyz/openbmc_project/Dump/Internal/Create/server.hpp
@@ -21,7 +22,8 @@
 	dump_entry.cpp \
 	dump_manager.cpp \
 	watch.cpp \
-	xyz/openbmc_project/Dump/Internal/Create/server.cpp
+	xyz/openbmc_project/Dump/Internal/Create/server.cpp \
+	elog_watch.cpp
 
 phosphor_dump_monitor_SOURCES = \
 	watch.cpp \
diff --git a/configure.ac b/configure.ac
index 3423f65..00a76bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,5 +75,7 @@
 AS_IF([test x$BMC_DUMP_TOTAL_SIZE == x], [BMC_DUMP_TOTAL_SIZE=1024])
 AC_DEFINE_UNQUOTED([BMC_DUMP_TOTAL_SIZE], [$BMC_DUMP_TOTAL_SIZE], [Total size of the dump in kilo bytes])
 
+AC_DEFINE(OBJ_LOGGING, "/xyz/openbmc_project/logging", [The log manager DBus object path.])
+
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
diff --git a/dump_manager.cpp b/dump_manager.cpp
index bf2e0a2..6ac636d 100644
--- a/dump_manager.cpp
+++ b/dump_manager.cpp
@@ -44,7 +44,8 @@
     //Type to dreport type  string map
     static const std::map<Type, std::string> typeMap =
                                {{Type::ApplicationCored, "core"},
-                                {Type::UserRequested, "user"}};
+                                {Type::UserRequested, "user"},
+                                {Type::InternalFailure, "elog"}};
 
     //Get Dump size.
     auto size = getAllowedSize();
diff --git a/dump_manager_main.cpp b/dump_manager_main.cpp
index ade1073..c437e7f 100644
--- a/dump_manager_main.cpp
+++ b/dump_manager_main.cpp
@@ -6,6 +6,7 @@
 #include "dump_manager.hpp"
 #include "dump_internal.hpp"
 #include "watch.hpp"
+#include "elog_watch.hpp"
 
 int main(int argc, char* argv[])
 {
@@ -36,6 +37,7 @@
         //Restore dump d-bus objects.
         manager.restore();
         phosphor::dump::internal::Manager mgr(bus, manager, OBJ_INTERNAL);
+        phosphor::dump::elog::Watch eWatch(bus, mgr);
         bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
 
         auto rc = sd_event_loop(eventP.get());
diff --git a/elog_watch.cpp b/elog_watch.cpp
new file mode 100644
index 0000000..6c7ff93
--- /dev/null
+++ b/elog_watch.cpp
@@ -0,0 +1,88 @@
+#include <phosphor-logging/elog.hpp>
+
+#include "elog_watch.hpp"
+#include "dump_internal.hpp"
+#include "xyz/openbmc_project/Dump/Create/error.hpp"
+
+namespace phosphor
+{
+namespace dump
+{
+namespace elog
+{
+
+using namespace phosphor::logging;
+constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
+constexpr auto INTERNAL_FAILURE =
+    "xyz.openbmc_project.Common.Error.InternalFailure";
+using Message = std::string;
+using Attributes = sdbusplus::message::variant<Message>;
+using AttributeName = std::string;
+using AttributeMap = std::map<AttributeName, Attributes>;
+using PropertyName = std::string;
+using PropertyMap = std::map<PropertyName, AttributeMap>;
+using LogEntryMsg = std::pair<sdbusplus::message::object_path, PropertyMap>;
+
+void Watch::callback(sdbusplus::message::message& msg)
+{
+    using Type =
+        sdbusplus::xyz::openbmc_project::Dump::Internal::server::Create::Type;
+    using QuotaExceeded =
+        sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded;
+
+    LogEntryMsg logEntry;
+    msg.read(logEntry);
+
+    std::string objectPath(std::move(logEntry.first));
+
+    std::size_t found = objectPath.find("entry");
+    if (found == std::string::npos)
+    {
+        //Not a new error entry skip
+        return;
+    }
+
+    auto iter = logEntry.second.find("xyz.openbmc_project.Logging.Entry");
+    if (iter == logEntry.second.end())
+    {
+        return;
+    }
+
+    auto attr = iter->second.find("Message");
+    if (attr == iter->second.end())
+    {
+        return;
+    }
+
+    auto& data =
+        sdbusplus::message::variant_ns::get<PropertyName>(attr->second);
+    if (data.empty())
+    {
+        //No Message skip
+        return;
+    }
+
+    if (INTERNAL_FAILURE != data)
+    {
+        //Not a InternalFailure, skip
+        return;
+    }
+
+    std::vector<std::string> fullPaths;
+    fullPaths.push_back(objectPath);
+
+    try
+    {
+        //Call internal create function to initiate dump
+        iMgr.IMgr::create(Type::InternalFailure, fullPaths);
+    }
+    catch (QuotaExceeded& e)
+    {
+        //No action now
+    }
+    return;
+}
+
+}//namespace elog
+}//namespace dump
+}//namespace phosphor
diff --git a/elog_watch.hpp b/elog_watch.hpp
new file mode 100644
index 0000000..cfdf41a
--- /dev/null
+++ b/elog_watch.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server.hpp>
+#include "config.h"
+
+#include "dump_manager.hpp"
+
+namespace phosphor
+{
+namespace dump
+{
+namespace elog
+{
+
+using IMgr = phosphor::dump::internal::Manager;
+
+/** @class Watch
+ *  @brief Adds d-bus signal based watch for elog commit.
+ *  @details This implements methods for watching for InternalFailure
+ *  type error message and call appropriate function to initiate dump
+ */
+class Watch
+{
+    public:
+        Watch() = delete;
+        ~Watch() = default;
+        Watch(const Watch&) = delete;
+        Watch& operator=(const Watch&) = delete;
+        Watch(Watch&&) = default;
+        Watch& operator=(Watch&&) = default;
+
+        /** @brief constructs watch for elog commits.
+         *  @param[in] bus -  The Dbus bus object
+         *  @param[in] intMgr - Dump internal Manager object
+         */
+        Watch(sdbusplus::bus::bus& bus, IMgr& iMgr):
+            iMgr(iMgr),
+            elogMatch(
+                bus,
+                sdbusplus::bus::match::rules::interfacesAdded() +
+                sdbusplus::bus::match::rules::path_namespace(
+                                              OBJ_LOGGING),
+                std::bind(std::mem_fn(&Watch::callback),
+                          this, std::placeholders::_1))
+        {
+            //Do nothing
+        }
+    private:
+
+        /** @brief Callback function for error log commit.
+         *  @details InternalError type error message initiates
+         *           Internal error type dump request.
+         *  @param[in] msg  - Data associated with subscribed signal
+         */
+        void callback(sdbusplus::message::message& msg);
+
+        /**  @brief Dump internal Manager object. */
+        IMgr& iMgr;
+
+        /** @brief sdbusplus signal match for elog commit */
+        sdbusplus::bus::match_t elogMatch;
+};
+
+}//namespace elog
+}//namespace dump
+}//namespace phosphor