Update json_utility APIs with error codes

This commit updates API getVPDOffset and getInventoryObjPathFromJson to
set error codes in case of errors/exceptions. This helps caller of the
APIs to take action based on the error code returned from the API.

Change-Id: Icfe2640ee311d61e83ca302e5199ce4dd1057c8b
Signed-off-by: Rekha Aparna <vrekhaaparna@ibm.com>
diff --git a/vpd-manager/include/error_codes.hpp b/vpd-manager/include/error_codes.hpp
index 42b010a..161e747 100644
--- a/vpd-manager/include/error_codes.hpp
+++ b/vpd-manager/include/error_codes.hpp
@@ -19,7 +19,7 @@
 static constexpr auto FRU_PATH_NOT_FOUND = 2004;
 
 // Generic errors.
-static constexpr auto INVALID_INPUT_PARAMATER = 3001;
+static constexpr auto INVALID_INPUT_PARAMETER = 3001;
 
 const std::unordered_map<int, std::string> errorCodeMap = {
     {FILE_NOT_FOUND, "File does not exist."},
@@ -30,7 +30,7 @@
     {MISSING_ACTION_TAG,
      "JSON is missing the action tag to be performed for the FRU."},
     {FRU_PATH_NOT_FOUND, "The FRU path is not found in the JSON."},
-    {INVALID_INPUT_PARAMATER,
+    {INVALID_INPUT_PARAMETER,
      "Either one of the input parameter is invalid or empty."}};
 } // namespace error_code
 } // namespace vpd
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
index dad346e..e30d1f6 100644
--- a/vpd-manager/include/utility/json_utility.hpp
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "error_codes.hpp"
 #include "event_logger.hpp"
 #include "exceptions.hpp"
 #include "logger.hpp"
@@ -50,14 +51,17 @@
  *
  * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
  * @param[in] i_vpdFilePath - VPD file path.
+ * @param[in] o_errCode - To set error code in case of error.
  * @return VPD offset if found in JSON, 0 otherwise.
  */
 inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
-                           const std::string& i_vpdFilePath)
+                           const std::string& i_vpdFilePath,
+                           uint16_t& o_errCode)
 {
     if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
         (!i_sysCfgJsonObj.contains("frus")))
     {
+        o_errCode = error_code::INVALID_INPUT_PARAMETER;
         return 0;
     }
 
@@ -135,6 +139,7 @@
  *
  * @param[in] i_sysCfgJsonObj - System config JSON object
  * @param[in] i_vpdPath - Path to where VPD is stored.
+ * @param[in] o_errCode - To set error code in case of error.
  *
  * @return On success a valid path is returned, on failure an empty string is
  * returned.
@@ -142,55 +147,47 @@
  * Note: Caller has to handle it in case an empty string is received.
  */
 inline std::string getInventoryObjPathFromJson(
-    const nlohmann::json& i_sysCfgJsonObj,
-    const std::string& i_vpdPath) noexcept
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath,
+    uint16_t& o_errCode) noexcept
 {
-    try
+    if (i_vpdPath.empty())
     {
-        if (i_vpdPath.empty())
-        {
-            throw std::runtime_error("Path parameter is empty.");
-        }
-
-        if (!i_sysCfgJsonObj.contains("frus"))
-        {
-            throw std::runtime_error("Missing frus tag in system config JSON.");
-        }
-
-        // check if given path is FRU path
-        if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
-        {
-            return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
-                "inventoryPath", "");
-        }
-
-        const nlohmann::json& l_fruList =
-            i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
-
-        for (const auto& l_fru : l_fruList.items())
-        {
-            const auto l_fruPath = l_fru.key();
-            const auto l_invObjPath =
-                i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
-                                                               "");
-
-            // check if given path is redundant FRU path or inventory path
-            if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
-                                 "redundantEeprom", "") ||
-                (i_vpdPath == l_invObjPath))
-            {
-                return l_invObjPath;
-            }
-        }
-    }
-    catch (const std::exception& l_ex)
-    {
-        logging::logMessage(
-            "Failed to get inventory object path from json, error: " +
-            std::string(l_ex.what()));
+        o_errCode = error_code::INVALID_INPUT_PARAMETER;
+        return std::string{};
     }
 
-    return std::string();
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        o_errCode = error_code::INVALID_JSON;
+        return std::string{};
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+            "inventoryPath", "");
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+        const auto l_invObjPath =
+            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath", "");
+
+        // check if given path is redundant FRU path or inventory path
+        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                             "redundantEeprom", "") ||
+            (i_vpdPath == l_invObjPath))
+        {
+            return l_invObjPath;
+        }
+    }
+
+    return std::string{};
 }
 
 /**
@@ -392,10 +389,13 @@
         l_errMsg += l_ex.what();
         l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
 
+        uint16_t l_errCode = 0;
+
         // ToDo -- Update Internal Rc code.
         EventLogger::createAsyncPelWithInventoryCallout(
             EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
-            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
+            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath,
+                                          l_errCode),
               types::CalloutPriority::High}},
             std::source_location::current().file_name(),
             std::source_location::current().function_name(), 0, l_errMsg,
@@ -490,12 +490,14 @@
             l_errMsg += l_ex.what();
             l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
 
+            uint16_t l_errCode = 0;
+
             // ToDo -- Update Internal RC code
             EventLogger::createAsyncPelWithInventoryCallout(
                 EventLogger::getErrorType(l_ex),
                 types::SeverityType::Informational,
-                {{getInventoryObjPathFromJson(i_parsedConfigJson,
-                                              i_vpdFilePath),
+                {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath,
+                                              l_errCode),
                   types::CalloutPriority::High}},
                 std::source_location::current().file_name(),
                 std::source_location::current().function_name(), 0, l_errMsg,
@@ -884,9 +886,11 @@
             {
                 io_vpdPath = l_fruPath;
 
+                uint16_t l_errCode = 0;
+
                 // Get inventory object path from system config JSON
                 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
-                    i_sysCfgJsonObj, l_fruPath);
+                    i_sysCfgJsonObj, l_fruPath, l_errCode);
 
                 // Get redundant hardware path if present in system config JSON
                 l_redundantFruPath =
diff --git a/vpd-manager/oem-handler/ibm_handler.cpp b/vpd-manager/oem-handler/ibm_handler.cpp
index 277b499..4b077f5 100644
--- a/vpd-manager/oem-handler/ibm_handler.cpp
+++ b/vpd-manager/oem-handler/ibm_handler.cpp
@@ -212,12 +212,21 @@
 
         // The utility method will handle emty JSON case. No explicit
         // handling required here.
+        uint16_t l_errCode = 0;
         auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
-            l_sysCfgJsonObj, l_fruPath);
+            l_sysCfgJsonObj, l_fruPath, l_errCode);
 
         // Mark it as failed if inventory path not found in JSON.
         if (l_inventoryPath.empty())
         {
+            if (l_errCode)
+            {
+                logging::logMessage(
+                    "Failed to get inventory object path from JSON for FRU [" +
+                    l_fruPath + "], error : " +
+                    vpdSpecificUtility::getErrCodeMsg(l_errCode));
+            }
+
             o_failedPathList.push_back(l_fruPath);
             continue;
         }
diff --git a/vpd-manager/src/backup_restore.cpp b/vpd-manager/src/backup_restore.cpp
index 6c31eac..61d5ba5 100644
--- a/vpd-manager/src/backup_restore.cpp
+++ b/vpd-manager/src/backup_restore.cpp
@@ -162,14 +162,38 @@
         return;
     }
 
-    const std::string l_srcInvPath =
-        jsonUtility::getInventoryObjPathFromJson(m_sysCfgJsonObj, i_srcPath);
-    const std::string l_dstInvPath =
-        jsonUtility::getInventoryObjPathFromJson(m_sysCfgJsonObj, i_dstPath);
-    if (l_srcInvPath.empty() || l_dstInvPath.empty())
+    uint16_t l_errCode = 0;
+    const std::string l_srcInvPath = jsonUtility::getInventoryObjPathFromJson(
+        m_sysCfgJsonObj, i_srcPath, l_errCode);
+
+    if (l_srcInvPath.empty())
     {
-        logging::logMessage(
-            "Couldn't find either source or destination inventory path.");
+        if (l_errCode)
+        {
+            logging::logMessage(
+                "Couldn't find source inventory path. Error : " +
+                vpdSpecificUtility::getErrCodeMsg(l_errCode));
+            return;
+        }
+
+        logging::logMessage("Couldn't find  source inventory path.");
+        return;
+    }
+
+    const std::string l_dstInvPath = jsonUtility::getInventoryObjPathFromJson(
+        m_sysCfgJsonObj, i_dstPath, l_errCode);
+
+    if (l_dstInvPath.empty())
+    {
+        if (l_errCode)
+        {
+            logging::logMessage(
+                "Couldn't find destination inventory path. Error : " +
+                vpdSpecificUtility::getErrCodeMsg(l_errCode));
+            return;
+        }
+
+        logging::logMessage("Couldn't find destination inventory path.");
         return;
     }
 
diff --git a/vpd-manager/src/event_logger.cpp b/vpd-manager/src/event_logger.cpp
index 900361a..a9ba077 100644
--- a/vpd-manager/src/event_logger.cpp
+++ b/vpd-manager/src/event_logger.cpp
@@ -8,6 +8,7 @@
 #include <systemd/sd-bus.h>
 
 #include <utility/json_utility.hpp>
+#include <utility/vpd_specific_utility.hpp>
 
 #include <filesystem>
 
@@ -339,6 +340,8 @@
         // Path to hold callout inventory path.
         std::string l_calloutInvPath;
 
+        uint16_t l_errCode = 0;
+
         // check if callout path is a valid inventory path. if not, get the JSON
         // object to get inventory path.
         if (std::get<0>(i_callouts[0])
@@ -353,7 +356,7 @@
                 {
                     l_calloutInvPath = jsonUtility::getInventoryObjPathFromJson(
                         jsonUtility::getParsedJson(INVENTORY_JSON_SYM_LINK),
-                        std::get<0>(i_callouts[0]));
+                        std::get<0>(i_callouts[0]), l_errCode);
                 }
                 else
                 {
@@ -366,6 +369,14 @@
         if (l_calloutInvPath.empty())
         {
             l_calloutInvPath = std::get<0>(i_callouts[0]);
+
+            if (l_errCode)
+            {
+                logging::logMessage(
+                    "Failed to get inventory object path from JSON for FRU [" +
+                    std::get<0>(i_callouts[0]) + "], error : " +
+                    vpdSpecificUtility::getErrCodeMsg(l_errCode));
+            }
         }
 
         const std::map<std::string, std::string> l_additionalData{
diff --git a/vpd-manager/src/gpio_monitor.cpp b/vpd-manager/src/gpio_monitor.cpp
index 2b02c9d..d758c90 100644
--- a/vpd-manager/src/gpio_monitor.cpp
+++ b/vpd-manager/src/gpio_monitor.cpp
@@ -1,10 +1,12 @@
 #include "gpio_monitor.hpp"
 
 #include "constants.hpp"
+#include "error_codes.hpp"
 #include "logger.hpp"
 #include "types.hpp"
 #include "utility/dbus_utility.hpp"
 #include "utility/json_utility.hpp"
+#include "utility/vpd_specific_utility.hpp"
 
 #include <boost/asio.hpp>
 #include <boost/bind/bind.hpp>
@@ -42,8 +44,18 @@
         }
         else
         {
-            m_worker->deleteFruVpd(jsonUtility::getInventoryObjPathFromJson(
-                m_worker->getSysCfgJsonObj(), m_fruPath));
+            uint16_t l_errCode = 0;
+            std::string l_invPath = jsonUtility::getInventoryObjPathFromJson(
+                m_worker->getSysCfgJsonObj(), m_fruPath, l_errCode);
+
+            if (l_errCode)
+            {
+                throw std::runtime_error(
+                    "Failed to get inventory path from JSON, error : " +
+                    vpdSpecificUtility::getErrCodeMsg(l_errCode));
+            }
+
+            m_worker->deleteFruVpd(l_invPath);
         }
     }
     catch (std::exception& l_ex)
diff --git a/vpd-manager/src/parser.cpp b/vpd-manager/src/parser.cpp
index 7658011..a32d155 100644
--- a/vpd-manager/src/parser.cpp
+++ b/vpd-manager/src/parser.cpp
@@ -34,7 +34,17 @@
     // Read VPD offset if applicable.
     if (!m_parsedJson.empty())
     {
-        m_vpdStartOffset = jsonUtility::getVPDOffset(m_parsedJson, vpdFilePath);
+        uint16_t l_errorCode = 0;
+
+        m_vpdStartOffset =
+            jsonUtility::getVPDOffset(m_parsedJson, vpdFilePath, l_errorCode);
+
+        if (l_errorCode)
+        {
+            logging::logMessage(
+                "Failed to get vpd offset for path [" + m_vpdFilePath +
+                "], error: " + vpdSpecificUtility::getErrCodeMsg(l_errorCode));
+        }
     }
 }
 
diff --git a/vpd-manager/src/worker.cpp b/vpd-manager/src/worker.cpp
index 179e7ec..5f8d888 100644
--- a/vpd-manager/src/worker.cpp
+++ b/vpd-manager/src/worker.cpp
@@ -1369,10 +1369,12 @@
         m_activeCollectionThreadCount++;
         m_mutex.unlock();
 
-        // Set collection Status as InProgress. Since it's an intermediate state
+        uint16_t l_errCode = 0;
+
+        // Set CollectionStatus as InProgress. Since it's an intermediate state
         // D-bus set-property call is good enough to update the status.
         l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
-            m_parsedJson, i_vpdFilePath);
+            m_parsedJson, i_vpdFilePath, l_errCode);
 
         if (!l_inventoryPath.empty())
         {
@@ -1391,6 +1393,12 @@
                     i_vpdFilePath + ". Error : " + "DBus write failed");
             }
         }
+        else if (l_errCode)
+        {
+            logging::logMessage(
+                "Failed to get inventory path for FRU [" + i_vpdFilePath +
+                "], error : " + vpdSpecificUtility::getErrCodeMsg(l_errCode));
+        }
 
         const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
         if (!std::holds_alternative<std::monostate>(parsedVpdMap))
@@ -1429,15 +1437,25 @@
         // based on status of execution.
         if (typeid(ex) == std::type_index(typeid(DataException)))
         {
+            uint16_t l_errCode = 0;
             // In case of pass1 planar, VPD can be corrupted on PCIe cards. Skip
             // logging error for these cases.
             if (vpdSpecificUtility::isPass1Planar())
             {
+                std::string l_invPath =
+                    jsonUtility::getInventoryObjPathFromJson(
+                        m_parsedJson, i_vpdFilePath, l_errCode);
+
+                if (l_errCode != 0)
+                {
+                    logging::logMessage(
+                        "Failed to get inventory object path from JSON for FRU [" +
+                        i_vpdFilePath + "], error: " +
+                        vpdSpecificUtility::getErrCodeMsg(l_errCode));
+                }
+
                 const std::string& l_invPathLeafValue =
-                    sdbusplus::message::object_path(
-                        jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
-                                                                 i_vpdFilePath))
-                        .filename();
+                    sdbusplus::message::object_path(l_invPath).filename();
 
                 if ((l_invPathLeafValue.find("pcie_card", 0) !=
                      std::string::npos))
@@ -1499,11 +1517,22 @@
             return true;
         }
 
+        uint16_t l_errCode = 0;
+        std::string l_invPath = jsonUtility::getInventoryObjPathFromJson(
+            m_parsedJson, i_vpdFilePath, l_errCode);
+
+        if (l_errCode)
+        {
+            logging::logMessage(
+                "Failed to get inventory path from JSON for FRU [" +
+                i_vpdFilePath +
+                "], error : " + vpdSpecificUtility::getErrCodeMsg(l_errCode));
+
+            return false;
+        }
+
         const std::string& l_invPathLeafValue =
-            sdbusplus::message::object_path(
-                jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
-                                                         i_vpdFilePath))
-                .filename();
+            sdbusplus::message::object_path(l_invPath).filename();
 
         if ((l_invPathLeafValue.find("pcie_card", 0) != std::string::npos))
         {