settings: handle multiple objects/interfaces

Handle the fact that a settings object can now implement multiple
interfaces, and also the fact that multiple settings objects
can implement the same interface.

Change-Id: Icf55b08fe2d355a10f7007489dfddb128e05d90e
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index bb6d5c2..de22d80 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -734,7 +734,7 @@
     using namespace chassis::internal::cache;
     using namespace power_policy;
 
-    const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf);
+    const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
     auto method =
         dbus.new_method_call(
             objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
@@ -1096,7 +1096,7 @@
         using namespace chassis::internal;
         using namespace chassis::internal::cache;
 
-        const auto& bootSourceSetting = objects.map.at(bootSourceIntf);
+        const auto& bootSourceSetting = objects.map.at(bootSourceIntf).front();
         auto method =
             dbus.new_method_call(
                  objects.service(bootSourceSetting, bootSourceIntf).c_str(),
@@ -1117,7 +1117,7 @@
         auto bootSource =
             Source::convertSourcesFromString(result.get<std::string>());
 
-        const auto& bootModeSetting = objects.map.at(bootModeIntf);
+        const auto& bootModeSetting = objects.map.at(bootModeIntf).front();
         method = dbus.new_method_call(
                       objects.service(bootModeSetting, bootModeIntf).c_str(),
                       bootModeSetting.c_str(),
@@ -1235,7 +1235,7 @@
             sdbusplus::message::variant<std::string> property =
                 convertForMessage(sourceItr->second);
             const auto& bootSourceSetting =
-                objects.map.at(bootSourceIntf);
+                objects.map.at(bootSourceIntf).front();
             auto method =
                 dbus.new_method_call(
                      objects.service(bootSourceSetting, bootSourceIntf).c_str(),
@@ -1257,7 +1257,7 @@
         {
             sdbusplus::message::variant<std::string> property =
                 convertForMessage(modeItr->second);
-            const auto& bootModeSetting = objects.map.at(bootModeIntf);
+            const auto& bootModeSetting = objects.map.at(bootModeIntf).front();
             auto method =
                 dbus.new_method_call(
                      objects.service(bootModeSetting, bootModeIntf).c_str(),
diff --git a/ipmid.cpp b/ipmid.cpp
index 6e24bce..f6ab2fd 100644
--- a/ipmid.cpp
+++ b/ipmid.cpp
@@ -308,7 +308,7 @@
     using namespace internal::cache;
     sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
     const auto& restrictionModeSetting =
-        objects->map.at(restrictionModeIntf);
+        objects->map.at(restrictionModeIntf).front();
     auto method = dbus.new_method_call(
                       objects->service(restrictionModeSetting,
                           restrictionModeIntf).c_str(),
@@ -596,7 +596,8 @@
         sdbusplus::bus::match_t restrictedModeMatch(
             dbus,
             sdbusRule::propertiesChanged(
-                objects->map.at(restrictionModeIntf), restrictionModeIntf),
+                objects->map.at(restrictionModeIntf).front(),
+                restrictionModeIntf),
             handle_restricted_mode_change);
 
         for (;;) {
diff --git a/settings.cpp b/settings.cpp
index cb86d99..59f9f33 100644
--- a/settings.cpp
+++ b/settings.cpp
@@ -46,8 +46,19 @@
     for (auto& iter : result)
     {
         const auto& path = iter.first;
-        auto& interface = iter.second.begin()->second[0];
-        map.emplace(std::move(interface), path);
+        for (auto& interface : iter.second.begin()->second)
+        {
+            auto found = map.find(interface);
+            if (map.end() != found)
+            {
+                auto& paths = found->second;
+                paths.push_back(path);
+            }
+            else
+            {
+                map.emplace(std::move(interface), std::vector<Path>({path}));
+            }
+        }
     }
 }
 
diff --git a/settings.hpp b/settings.hpp
index 60ee4d4..ec1d913 100644
--- a/settings.hpp
+++ b/settings.hpp
@@ -42,12 +42,8 @@
          */
         Service service(const Path& path, const Interface& interface) const;
 
-        // TODO openbmc/openbmc#2058 - This will break when multiple settings,
-        // or in general multiple objects implement a single setting interface.
-        // For instance this will break for a 2-blade server, because we'd have
-        // 2 sets of settings objects. Need to revisit and fix this.
         /** @brief map of settings objects */
-        std::map<Interface, Path> map;
+        std::map<Interface, std::vector<Path>> map;
 
         /** @brief The Dbus bus object */
         sdbusplus::bus::bus& bus;