Reconstruct OCC objects on app restart

The OCC objects would get created when corresponding CPU inventory items
get added. This doesn't cover a scenario where the OCC app restarts.

If the CPU inventory is already present when the app starts, construct
OCC objects as well.

Resolves openbmc/openbmc#1824.

Change-Id: I4994d93ba6f528ca67977604ccb1da717563092a
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/occ_manager.hpp b/occ_manager.hpp
index 4430d74..7b76703 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -5,10 +5,11 @@
 #include <experimental/filesystem>
 #include <functional>
 #include <sdbusplus/bus.hpp>
+#include <powercap.hpp>
 #include "occ_pass_through.hpp"
 #include "occ_status.hpp"
+#include "occ_finder.hpp"
 #include "config.h"
-#include <powercap.hpp>
 
 namespace sdbusRule = sdbusplus::bus::match::rules;
 
@@ -41,15 +42,29 @@
             bus(bus),
             event(event)
         {
-            for (auto id = 0; id < MAX_CPUS; ++id)
+            // Check if CPU inventory exists already.
+            auto occs = open_power::occ::finder::get();
+            if (occs.empty())
             {
-                auto path = std::string(CPU_PATH) + std::to_string(id);
-                cpuMatches.emplace_back(
-                    bus,
-                    sdbusRule::interfacesAdded() +
-                    sdbusRule::argNpath(0, path),
-                    std::bind(std::mem_fn(&Manager::cpuCreated),
-                              this, std::placeholders::_1));
+                // Need to watch for CPU inventory creation.
+                for (auto id = 0; id < MAX_CPUS; ++id)
+                {
+                    auto path = std::string(CPU_PATH) + std::to_string(id);
+                    cpuMatches.emplace_back(
+                        bus,
+                        sdbusRule::interfacesAdded() +
+                        sdbusRule::argNpath(0, path),
+                        std::bind(std::mem_fn(&Manager::cpuCreated),
+                                  this, std::placeholders::_1));
+                }
+            }
+            else
+            {
+                for (const auto& occ : occs)
+                {
+                    // CPU inventory exists already, OCC objects can be created.
+                    createObjects(occ);
+                }
             }
         }
 
@@ -67,13 +82,25 @@
             sdbusplus::message::object_path o;
             msg.read(o);
             fs::path cpuPath(std::string(std::move(o)));
-            auto cpu = cpuPath.filename();
 
-            std::string name{cpu.c_str()};
+            auto name = cpuPath.filename().string();
             auto index = name.find(CPU_NAME);
             name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
 
-            auto path = fs::path(OCC_CONTROL_ROOT) / name;
+            createObjects(name);
+
+            return 0;
+        }
+
+    private:
+        /** @brief Create child OCC objects.
+         *
+         *  @param[in] occ - the occ name, such as occ0.
+         */
+        void createObjects(const std::string& occ)
+        {
+            auto path = fs::path(OCC_CONTROL_ROOT) / occ;
+
             passThroughObjects.emplace_back(
                 std::make_unique<PassThrough>(
                     bus,
@@ -86,16 +113,14 @@
                     path.c_str()));
 
             // Create the power cap monitor object for master occ (0)
-            if(!pcap && (index == 0))
+            if (!pcap)
             {
                 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
                                                         bus,
-                                                        *statusObjects[index]);
+                                                        *statusObjects.front());
             }
-            return 0;
         }
 
-    private:
         /** @brief reference to the bus */
         sdbusplus::bus::bus& bus;