event: Handling pldmPDRRepositoryChgEvent

Added a handler to react to the "pldmPDRRepositoryChgEvent" event and
extract the data. If the eventDataFormat is "formatIsPDRHandles" then
the changeRecords are further extracted. If the eventDataOperation is
"recordAdded" then the PDRHandles are extracted from the changeEntry
data and stored in the "pdrRecordHandle" vector.

"decode_pldm_pdr_repository_chg_event_data" function will extract the
eventData and changeRecord from the pldmPDRRepositoryChgEvent class
while the "decode_pldm_pdr_repository_change_record_data" will extract
the changeEntries data from the changeRecord. Unit tests for the above
decode functions have been added.

Extracted PDR handles are used to fetch PDRs corresponding to the same
from the host.

Signed-off-by: Zahed Hossain <zahzahed@in.ibm.com>
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I32e8745e04ac82393e067c0f0ab48802809495a6
diff --git a/host_pdr_handler.cpp b/host_pdr_handler.cpp
index 1e78846..3cd7873 100644
--- a/host_pdr_handler.cpp
+++ b/host_pdr_handler.cpp
@@ -5,13 +5,28 @@
 namespace pldm
 {
 
-void HostPDRHandler::fetchPDR(const std::vector<uint32_t>& recordHandles)
+void HostPDRHandler::fetchPDR(std::vector<uint32_t>&& recordHandles)
 {
+    pdrRecordHandles.clear();
+    pdrRecordHandles = std::move(recordHandles);
+
+    // Defer the actual fetch of PDRs from the host (by queuing the call on the
+    // main event loop). That way, we can respond to the platform event msg from
+    // the host firmware.
+    pdrFetchEvent = std::make_unique<sdeventplus::source::Defer>(
+        event, std::bind(std::mem_fn(&HostPDRHandler::_fetchPDR), this,
+                         std::placeholders::_1));
+}
+
+void HostPDRHandler::_fetchPDR(sdeventplus::source::EventBase& /*source*/)
+{
+    pdrFetchEvent.reset();
+
     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
                                     PLDM_GET_PDR_REQ_BYTES);
     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
 
-    for (auto recordHandle : recordHandles)
+    for (auto recordHandle : pdrRecordHandles)
     {
         auto instanceId = requester.getInstanceId(mctp_eid);
 
@@ -21,7 +36,8 @@
         if (rc != PLDM_SUCCESS)
         {
             requester.markFree(mctp_eid, instanceId);
-            std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << "\n";
+            std::cerr << "Failed to encode_get_pdr_req, rc = " << rc
+                      << std::endl;
             return;
         }
 
@@ -36,7 +52,7 @@
         if (requesterRc != PLDM_REQUESTER_SUCCESS)
         {
             std::cerr << "Failed to send msg to fetch pdrs, rc = "
-                      << requesterRc << "\n";
+                      << requesterRc << std::endl;
             return;
         }
 
@@ -54,7 +70,8 @@
             &transferFlag, &respCount, nullptr, 0, &transferCRC);
         if (rc != PLDM_SUCCESS)
         {
-            std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc << "\n";
+            std::cerr << "Failed to decode_get_pdr_resp, rc = " << rc
+                      << std::endl;
         }
         else
         {
@@ -67,8 +84,8 @@
             {
                 std::cerr << "Failed to decode_get_pdr_resp: "
                           << "rc=" << rc
-                          << ", cc=" << static_cast<int>(completionCode)
-                          << "\n";
+                          << ", cc=" << static_cast<unsigned>(completionCode)
+                          << std::endl;
             }
             else
             {