libpldmresponder: construct BMC PDRs lazily

BMC's PDRs were constructed when the pldm daemon starts up. However, the
pldm daemon might rely on other services to start in order to create
PDRs. To solve this problem, construct the PDRs when the first GetPDR
call comes in. From a practical timing perspective, this ensures the
pldm daemon and the services it needs to build PDRs are all up and
running.

An alternative would be to add 'After' directives in pldm's service
file, however that can get complex when some of the services are not
present on all platforms.

Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: Id6ac9fd47b293f7e84e3837432b32b0e3c3f8a5a
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 6801566..211ff65 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -135,6 +135,12 @@
 
 Response Handler::getPDR(const pldm_msg* request, size_t payloadLength)
 {
+    if (!pdrCreated)
+    {
+        generate(*dBusIntf, pdrJsonsDir, pdrRepo);
+        pdrCreated = true;
+    }
+
     // Build FRU table if not built, since entity association PDR's are built
     // when the FRU table is constructed.
     if (fruHandler)
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index c79a2ed..1ff6bc4 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -56,16 +56,21 @@
 class Handler : public CmdHandler
 {
   public:
-    Handler(const pldm::utils::DBusHandler& dBusIntf,
+    Handler(const pldm::utils::DBusHandler* dBusIntf,
             const std::string& pdrJsonsDir, const std::string& eventsJsonsDir,
             pldm_pdr* repo, HostPDRHandler* hostPDRHandler,
-            fru::Handler* fruHandler,
+            fru::Handler* fruHandler, bool buildPDRLazily = false,
             const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
         pdrRepo(repo),
         hostPDRHandler(hostPDRHandler), stateSensorHandler(eventsJsonsDir),
-        fruHandler(fruHandler)
+        fruHandler(fruHandler), dBusIntf(dBusIntf), pdrJsonsDir(pdrJsonsDir),
+        pdrCreated(false)
     {
-        generate(dBusIntf, pdrJsonsDir, pdrRepo);
+        if (!buildPDRLazily)
+        {
+            generate(*dBusIntf, pdrJsonsDir, pdrRepo);
+            pdrCreated = true;
+        }
 
         handlers.emplace(PLDM_GET_PDR,
                          [this](const pldm_msg* request, size_t payloadLength) {
@@ -404,6 +409,9 @@
     HostPDRHandler* hostPDRHandler;
     events::StateSensorHandler stateSensorHandler;
     fru::Handler* fruHandler;
+    const pldm::utils::DBusHandler* dBusIntf;
+    std::string pdrJsonsDir;
+    bool pdrCreated;
 };
 
 } // namespace platform
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index 5215589..192112e 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -174,7 +174,7 @@
     std::unique_ptr<HostPDRHandler> hostPDRHandler;
     std::unique_ptr<pldm::host_effecters::HostEffecterParser>
         hostEffecterParser;
-    DBusHandler dbusHandler;
+    auto dbusHandler = std::make_unique<DBusHandler>();
     auto hostEID = pldm::utils::readHostEID();
     if (hostEID)
     {
@@ -183,7 +183,7 @@
             dbusImplReq);
         hostEffecterParser =
             std::make_unique<pldm::host_effecters::HostEffecterParser>(
-                &dbusImplReq, sockfd, pdrRepo.get(), &dbusHandler,
+                &dbusImplReq, sockfd, pdrRepo.get(), dbusHandler.get(),
                 HOST_JSONS_DIR, verbose);
     }
 
@@ -197,9 +197,9 @@
     // Platform handler.
     invoker.registerHandler(PLDM_PLATFORM,
                             std::make_unique<platform::Handler>(
-                                dbusHandler, PDR_JSONS_DIR, EVENTS_JSONS_DIR,
-                                pdrRepo.get(), hostPDRHandler.get(),
-                                fruHandler.get()));
+                                dbusHandler.get(), PDR_JSONS_DIR,
+                                EVENTS_JSONS_DIR, pdrRepo.get(),
+                                hostPDRHandler.get(), fruHandler.get(), true));
     invoker.registerHandler(PLDM_FRU, std::move(fruHandler));
 
 #ifdef OEM_IBM
diff --git a/test/libpldmresponder_pdr_effecter_test.cpp b/test/libpldmresponder_pdr_effecter_test.cpp
index e0a54bf..60181d6 100644
--- a/test/libpldmresponder_pdr_effecter_test.cpp
+++ b/test/libpldmresponder_pdr_effecter_test.cpp
@@ -27,7 +27,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -126,7 +126,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good", "",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", "",
                     inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_NUMERIC_EFFECTER_PDR);
@@ -172,7 +172,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -193,7 +193,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto inPDRRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good", "",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", "",
                     inPDRRepo, nullptr, nullptr);
     uint16_t entityType = 33;
     uint16_t entityInstance = 0;
diff --git a/test/libpldmresponder_platform_test.cpp b/test/libpldmresponder_platform_test.cpp
index 22ededa..4183a0a 100644
--- a/test/libpldmresponder_platform_test.cpp
+++ b/test/libpldmresponder_platform_test.cpp
@@ -38,7 +38,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto pdrRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", pdrRepo, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
@@ -75,7 +75,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto pdrRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", pdrRepo, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
@@ -106,7 +106,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto pdrRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", pdrRepo, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
@@ -135,7 +135,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto pdrRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", pdrRepo, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
@@ -166,7 +166,7 @@
         .WillRepeatedly(Return("foo.bar"));
 
     auto pdrRepo = pldm_pdr_init();
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", pdrRepo, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
@@ -223,7 +223,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -263,7 +263,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good",
                     "./event_jsons/good", inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -307,7 +307,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto numericEffecterPdrRepo = pldm_pdr_init();
     Repo numericEffecterPDRs(numericEffecterPdrRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good", "",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", "",
                     inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
@@ -349,7 +349,7 @@
     auto inPDRRepo = pldm_pdr_init();
     auto numericEffecterPdrRepo = pldm_pdr_init();
     Repo numericEffecterPDRs(numericEffecterPdrRepo);
-    Handler handler(mockedUtils, "./pdr_jsons/state_effecter/good", "",
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", "",
                     inPDRRepo, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);