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_finder.cpp b/occ_finder.cpp
new file mode 100644
index 0000000..a533067
--- /dev/null
+++ b/occ_finder.cpp
@@ -0,0 +1,82 @@
+#include <algorithm>
+#include <iterator>
+#include <experimental/filesystem>
+#include <sdbusplus/server.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+#include "occ_finder.hpp"
+#include "config.h"
+
+namespace open_power
+{
+namespace occ
+{
+namespace finder
+{
+
+using namespace phosphor::logging;
+
+constexpr auto toChar(size_t c)
+{
+    constexpr auto map = "0123456789abcdef";
+    return map[c];
+}
+
+std::vector<std::string> get()
+{
+    namespace fs = std::experimental::filesystem;
+    using Path = std::string;
+    using Service = std::string;
+    using Interface = std::string;
+    using Interfaces = std::vector<Interface>;
+
+    auto bus = sdbusplus::bus::new_default();
+    auto mapper =
+        bus.new_method_call(
+            "xyz.openbmc_project.ObjectMapper",
+            "/xyz/openbmc_project/object_mapper",
+            "xyz.openbmc_project.ObjectMapper",
+            "GetSubTree");
+
+    auto depth = 0;
+    Path path = CPU_SUBPATH;
+    Interfaces interfaces{INVENTORY_ITEM_INTERFACE};
+    mapper.append(path);
+    mapper.append(depth);
+    mapper.append(interfaces);
+
+    auto result = bus.call(mapper);
+    if (result.is_method_error())
+    {
+        // It's okay to not have inventory, for example at BMC standby
+        return {};
+    }
+
+    using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
+    MapperResponse response;
+    result.read(response);
+    if (response.empty())
+    {
+        // It's okay to not have inventory, for example at BMC standby
+        return {};
+    }
+
+    std::vector<std::string> occs;
+    for (auto count = 0; count < MAX_CPUS; ++count)
+    {
+        fs::path p(path);
+        p /= std::string(CPU_NAME) + toChar(count);
+        if (response.end() != response.find(p.string()))
+        {
+            occs.emplace_back(std::string(OCC_NAME) +
+                              toChar(count));
+        }
+    }
+
+    return occs;
+}
+
+} // namespace finder
+} // namespace occ
+} // namespace open_power