Revamped code for VPD parser

The commit removes all the pre-existing code from the branch
and pushes the revamped code.

Major modification includes:
- Movement from multi exe to single daemon model.
- Multithreaded approach to parse FRU VPD.
- Better error handling.
- Refactored code for performance optimization.

Note: This code supports all the existing functionalities as it is.

Change-Id: I1ddce1f0725ac59020b72709689a1013643bda8b
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-manager/src/event_logger.cpp b/vpd-manager/src/event_logger.cpp
new file mode 100644
index 0000000..11861d1
--- /dev/null
+++ b/vpd-manager/src/event_logger.cpp
@@ -0,0 +1,294 @@
+#include "event_logger.hpp"
+
+#include "logger.hpp"
+
+#include <systemd/sd-bus.h>
+
+namespace vpd
+{
+const std::unordered_map<types::SeverityType, std::string>
+    EventLogger::m_severityMap = {
+        {types::SeverityType::Notice,
+         "xyz.openbmc_project.Logging.Entry.Level.Notice"},
+        {types::SeverityType::Informational,
+         "xyz.openbmc_project.Logging.Entry.Level.Informational"},
+        {types::SeverityType::Debug,
+         "xyz.openbmc_project.Logging.Entry.Level.Debug"},
+        {types::SeverityType::Warning,
+         "xyz.openbmc_project.Logging.Entry.Level.Warning"},
+        {types::SeverityType::Critical,
+         "xyz.openbmc_project.Logging.Entry.Level.Critical"},
+        {types::SeverityType::Emergency,
+         "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
+        {types::SeverityType::Alert,
+         "xyz.openbmc_project.Logging.Entry.Level.Alert"},
+        {types::SeverityType::Error,
+         "xyz.openbmc_project.Logging.Entry.Level.Error"}};
+
+const std::unordered_map<types::ErrorType, std::string>
+    EventLogger::m_errorMsgMap = {
+        {types::ErrorType::DefaultValue, "com.ibm.VPD.Error.DefaultValue"},
+        {types::ErrorType::InvalidVpdMessage, "com.ibm.VPD.Error.InvalidVPD"},
+        {types::ErrorType::VpdMismatch, "com.ibm.VPD.Error.Mismatch"},
+        {types::ErrorType::InvalidEeprom,
+         "com.ibm.VPD.Error.InvalidEepromPath"},
+        {types::ErrorType::EccCheckFailed, "com.ibm.VPD.Error.EccCheckFailed"},
+        {types::ErrorType::JsonFailure, "com.ibm.VPD.Error.InvalidJson"},
+        {types::ErrorType::DbusFailure, "com.ibm.VPD.Error.DbusFailure"},
+        {types::ErrorType::InvalidSystem,
+         "com.ibm.VPD.Error.UnknownSystemType"},
+        {types::ErrorType::EssentialFru,
+         "com.ibm.VPD.Error.RequiredFRUMissing"},
+        {types::ErrorType::GpioError, "com.ibm.VPD.Error.GPIOError"}};
+
+const std::unordered_map<types::CalloutPriority, std::string>
+    EventLogger::m_priorityMap = {
+        {types::CalloutPriority::High, "H"},
+        {types::CalloutPriority::Medium, "M"},
+        {types::CalloutPriority::MediumGroupA, "A"},
+        {types::CalloutPriority::MediumGroupB, "B"},
+        {types::CalloutPriority::MediumGroupC, "C"},
+        {types::CalloutPriority::Low, "L"}};
+
+void EventLogger::createAsyncPelWithInventoryCallout(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::vector<types::InventoryCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+
+    try
+    {
+        if (i_callouts.empty())
+        {
+            logging::logMessage("Callout information is missing to create PEL");
+            // TODO: Revisit this instead of simpley returning.
+            return;
+        }
+
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error(
+                "Error type not found in the error message map to create PEL");
+            // TODO: Need to handle, instead of throwing exception. Create
+            // default message in message_registry.json.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        std::string l_description =
+            (!i_description.empty() ? i_description : "VPD generic error");
+
+        std::string l_userData1 = (i_userData1) ? (*i_userData1) : "";
+
+        std::string l_userData2 = (i_userData2) ? (*i_userData2) : "";
+
+        const types::InventoryCalloutData& l_invCallout = i_callouts[0];
+        // TODO: Need to handle multiple inventory path callout's, when multiple
+        // callout's is supported by "Logging" service.
+
+        const types::CalloutPriority& l_priorityEnum = get<1>(l_invCallout);
+
+        const std::string& l_priority =
+            (m_priorityMap.find(l_priorityEnum) != m_priorityMap.end()
+                 ? m_priorityMap.at(l_priorityEnum)
+                 : m_priorityMap.at(types::CalloutPriority::Low));
+
+        sd_bus* l_sdBus = nullptr;
+        sd_bus_default(&l_sdBus);
+
+        const uint8_t l_additionalDataCount = 8;
+        auto l_rc = sd_bus_call_method_async(
+            l_sdBus, NULL, constants::eventLoggingServiceName,
+            constants::eventLoggingObjectPath, constants::eventLoggingInterface,
+            "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
+            l_severity.c_str(), l_additionalDataCount, "FileName",
+            i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
+            "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
+            l_description.c_str(), "UserData1", l_userData1.c_str(),
+            "UserData2", l_userData2.c_str(), "CALLOUT_INVENTORY_PATH",
+            get<0>(l_invCallout).c_str(), "CALLOUT_PRIORITY",
+            l_priority.c_str());
+
+        if (l_rc < 0)
+        {
+            logging::logMessage(
+                "Error calling sd_bus_call_method_async, Message = " +
+                std::string(strerror(-l_rc)));
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "Create PEL failed with error: " + std::string(l_ex.what()));
+    }
+}
+
+void EventLogger::createAsyncPelWithI2cDeviceCallout(
+    const types::ErrorType i_errorType, const types::SeverityType i_severity,
+    const std::vector<types::DeviceCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc,
+    const std::optional<std::pair<std::string, std::string>> i_userData1,
+    const std::optional<std::pair<std::string, std::string>> i_userData2)
+{
+    // TODO, implementation needs to be added.
+    (void)i_errorType;
+    (void)i_severity;
+    (void)i_callouts;
+    (void)i_fileName;
+    (void)i_funcName;
+    (void)i_internalRc;
+    (void)i_userData1;
+    (void)i_userData2;
+}
+
+void EventLogger::createAsyncPelWithI2cBusCallout(
+    const types::ErrorType i_errorType, const types::SeverityType i_severity,
+    const std::vector<types::I2cBusCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc,
+    const std::optional<std::pair<std::string, std::string>> i_userData1,
+    const std::optional<std::pair<std::string, std::string>> i_userData2)
+{
+    // TODO, implementation needs to be added.
+    (void)i_errorType;
+    (void)i_severity;
+    (void)i_callouts;
+    (void)i_fileName;
+    (void)i_funcName;
+    (void)i_internalRc;
+    (void)i_userData1;
+    (void)i_userData2;
+}
+
+void EventLogger::createAsyncPel(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+    try
+    {
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error("Unsupported error type received");
+            // TODO: Need to handle, instead of throwing an exception.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        const std::string l_description =
+            ((!i_description.empty() ? i_description : "VPD generic error"));
+
+        const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
+
+        const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
+
+        sd_bus* l_sdBus = nullptr;
+        sd_bus_default(&l_sdBus);
+
+        // VALUE_6 represents the additional data pair count passing to create
+        // PEL. If there any change in additional data, we need to pass the
+        // correct number.
+        auto l_rc = sd_bus_call_method_async(
+            l_sdBus, NULL, constants::eventLoggingServiceName,
+            constants::eventLoggingObjectPath, constants::eventLoggingInterface,
+            "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
+            l_severity.c_str(), constants::VALUE_6, "FileName",
+            i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
+            "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
+            l_description.c_str(), "UserData1", l_userData1.c_str(),
+            "UserData2", l_userData2.c_str());
+
+        if (l_rc < 0)
+        {
+            logging::logMessage(
+                "Error calling sd_bus_call_method_async, Message = " +
+                std::string(strerror(-l_rc)));
+        }
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage("Async PEL creation failed with an error: " +
+                            std::string(l_ex.what()));
+    }
+}
+
+void EventLogger::createSyncPel(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+    try
+    {
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error("Unsupported error type received");
+            // TODO: Need to handle, instead of throwing an exception.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        const std::string l_description =
+            ((!i_description.empty() ? i_description : "VPD generic error"));
+
+        const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
+
+        const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
+
+        std::map<std::string, std::string> l_additionalData{
+            {"FileName", i_fileName},
+            {"FunctionName", i_funcName},
+            {"DESCRIPTION", l_description},
+            {"InteranlRc", std::to_string(i_internalRc)},
+            {"UserData1", l_userData1.c_str()},
+            {"UserData2", l_userData2.c_str()}};
+
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method =
+            l_bus.new_method_call(constants::eventLoggingServiceName,
+                                  constants::eventLoggingObjectPath,
+                                  constants::eventLoggingInterface, "Create");
+        l_method.append(l_message, l_severity, l_additionalData);
+        l_bus.call(l_method);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage("Sync PEL creation failed with an error: " +
+                            std::string(l_ex.what()));
+    }
+}
+} // namespace vpd