Async request to create PEL

To avoid any deadlocks between phosphor-logging and vpd-manager
service a wrapper around request to create PEL is created
which enables vpd-manager to make async requests to create PEL.

It also implements a new exception type to throw any GPIO
related exception. This was required to throw specific
exception.

Test:
Scenario 1:
While vpd-manager logs a pel with call out to an inventory
item.
It should be checked that both the services do not enter into
a deadlock situation.

Scenario 2:
Any third process is requesting to log PEL with call out
to an inventory item in a loop.
In the mean time vpd-manager also requests to log a PEL
with or without call out to inventory item.
All the pels should be logged correctly in the system.
No deadlock should appear.

Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: I0efaf6918e679ca94808fc70d747c843a50eaf78
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index fd9713f..b625568 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -484,40 +484,50 @@
         return;
     }
 
-    if (executePreAction(json, file))
+    try
     {
-        if (json["frus"][file].at(0).find("devAddress") !=
-            json["frus"][file].at(0).end())
+        if (executePreAction(json, file))
         {
-            // Now bind the device
-            string bind = json["frus"][file].at(0).value("devAddress", "");
-            cout << "Binding device " << bind << endl;
-            string bindCmd = string("echo \"") + bind +
-                             string("\" > /sys/bus/i2c/drivers/at24/bind");
-            cout << bindCmd << endl;
-            executeCmd(bindCmd);
-
-            // Check if device showed up (test for file)
-            if (!fs::exists(file))
+            if (json["frus"][file].at(0).find("devAddress") !=
+                json["frus"][file].at(0).end())
             {
-                cerr << "EEPROM " << file
-                     << " does not exist. Take failure action" << endl;
-                // If not, then take failure postAction
+                // Now bind the device
+                string bind = json["frus"][file].at(0).value("devAddress", "");
+                cout << "Binding device " << bind << endl;
+                string bindCmd = string("echo \"") + bind +
+                                 string("\" > /sys/bus/i2c/drivers/at24/bind");
+                cout << bindCmd << endl;
+                executeCmd(bindCmd);
+
+                // Check if device showed up (test for file)
+                if (!fs::exists(file))
+                {
+                    cerr << "EEPROM " << file
+                         << " does not exist. Take failure action" << endl;
+                    // If not, then take failure postAction
+                    executePostFailAction(json, file);
+                }
+            }
+            else
+            {
+                // missing required informations
+                cerr << "VPD inventory JSON missing basic informations of "
+                        "preAction "
+                        "for this FRU : ["
+                     << file << "]. Executing executePostFailAction." << endl;
+
+                // Take failure postAction
                 executePostFailAction(json, file);
+                return;
             }
         }
-        else
-        {
-            // missing required informations
-            cerr
-                << "VPD inventory JSON missing basic informations of preAction "
-                   "for this FRU : ["
-                << file << "]. Executing executePostFailAction." << endl;
-
-            // Take failure postAction
-            executePostFailAction(json, file);
-            return;
-        }
+    }
+    catch (const GpioException& e)
+    {
+        PelAdditionalData additionalData{};
+        additionalData.emplace("DESCRIPTION", e.what());
+        createPEL(additionalData, PelSeverity::WARNING, errIntfForGpioError,
+                  nullptr);
     }
 }
 
@@ -755,7 +765,7 @@
         PelAdditionalData additionalData{};
         additionalData.emplace("DESCRIPTION", err);
         createPEL(additionalData, PelSeverity::WARNING,
-                  errIntfForInvalidSystemType);
+                  errIntfForInvalidSystemType, nullptr);
         exit(-1);
     }
 
@@ -859,7 +869,7 @@
                                 additionalData.emplace("DESCRIPTION", errMsg);
 
                                 createPEL(additionalData, PelSeverity::WARNING,
-                                          errIntfForInvalidVPD);
+                                          errIntfForInvalidVPD, nullptr);
                             }
                         }
                         else
@@ -902,7 +912,7 @@
 
                         // log PEL TODO: Block IPL
                         createPEL(additionalData, PelSeverity::ERROR,
-                                  errIntfForBlankSystemVPD);
+                                  errIntfForBlankSystemVPD, nullptr);
                         continue;
                     }
                 }
@@ -1436,7 +1446,7 @@
     {
         additionalData.emplace("JSON_PATH", ex.getJsonPath());
         additionalData.emplace("DESCRIPTION", ex.what());
-        createPEL(additionalData, pelSeverity, errIntfForJsonFailure);
+        createPEL(additionalData, pelSeverity, errIntfForJsonFailure, nullptr);
 
         cerr << ex.what() << "\n";
         rc = -1;
@@ -1446,7 +1456,7 @@
         additionalData.emplace("DESCRIPTION", "ECC check failed");
         additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                INVENTORY_PATH + baseFruInventoryPath);
-        createPEL(additionalData, pelSeverity, errIntfForEccCheckFail);
+        createPEL(additionalData, pelSeverity, errIntfForEccCheckFail, nullptr);
         dumpBadVpd(file, vpdVector);
         cerr << ex.what() << "\n";
         rc = -1;
@@ -1475,7 +1485,8 @@
             additionalData.emplace("DESCRIPTION", errorMsg);
             additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                    INVENTORY_PATH + baseFruInventoryPath);
-            createPEL(additionalData, pelSeverity, errIntfForInvalidVPD);
+            createPEL(additionalData, pelSeverity, errIntfForInvalidVPD,
+                      nullptr);
 
             rc = -1;
         }