summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-01-03 14:48:33 -0600
committerMatt Spinler <spinler@us.ibm.com>2019-01-11 13:24:12 -0600
commit1b4a502b77e0fa031c62b301667ec7e132e21c2f (patch)
tree212cca4557c1c8b8f82da504839294c9004e8fde
parent8ce2ddd93c15d8a9358b4e62d2810869a413d3c0 (diff)
downloadphosphor-objmgr-1b4a502b77e0fa031c62b301667ec7e132e21c2f.tar.gz
phosphor-objmgr-1b4a502b77e0fa031c62b301667ec7e132e21c2f.zip
mapper: Add missing parent paths in ifaces-added
On an InterfacesAdded signal, a new path may have just been created with 2 or more new path segments. For example /A/B/C/D was just created and only /A/B exists so far. In this case, the current code never adds /A/B/C to the mapper, so trying to call GetObject or GetSubTree on that path would fail. To fix that, in the signal handler, check if all of the parent paths are already in the interface map, and add them if they aren't. It will take a shortcut and just add the three org.freedesktop.DBus interfaces Introspectable, Peer, and Properties, instead of calling the D-Bus introspect method since that is all it would find anyway. A big usecase of this is the REST server, where people try to do things like GET /xyz/openbmc_project/logging/entry/enumerate, which will fail if no logs existed when the mapper started since nothing explicitly created that exact path. Resolves openbmc/openbmc#3450 Tested: Created /xyz/openbmc_project/logging/entry/1, when previously only /xyz/openbmc_project/logging existed. Verify calling GetObject and GetSubTree now work on the /xyz/openbmc_project/logging/entry path. Change-Id: Id24f78beef9a34245d88de25a65006745fbda992 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-rw-r--r--src/main.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index bcf52e1..b1325e1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -678,6 +678,52 @@ int main(int argc, char** argv)
addAssociation(server, associations, obj_path.str);
}
}
+
+ // To handle the case where an object path is being created
+ // with 2 or more new path segments, check if the parent paths
+ // of this path are already in the interface map, and add them
+ // if they aren't with just the default freedesktop interfaces.
+ // This would be done via introspection if they would have
+ // already existed at startup. While we could also introspect
+ // them now to do the work, we know there aren't any other
+ // interfaces or we would have gotten signals for them as well,
+ // so take a shortcut to speed things up.
+ //
+ // This is all needed so that mapper operations can be done
+ // on the new parent paths.
+ using iface_map_iterator = interface_map_type::iterator;
+ using iface_map_value_type = boost::container::flat_map<
+ std::string, boost::container::flat_set<std::string>>;
+ using name_map_iterator = iface_map_value_type::iterator;
+
+ static const boost::container::flat_set<std::string>
+ default_ifaces{"org.freedesktop.DBus.Introspectable",
+ "org.freedesktop.DBus.Peer",
+ "org.freedesktop.DBus.Properties"};
+
+ std::string parent = obj_path.str;
+ auto pos = parent.find_last_of('/');
+
+ while (pos != std::string::npos)
+ {
+ parent = parent.substr(0, pos);
+
+ std::pair<iface_map_iterator, bool> parentEntry =
+ interface_map.insert(
+ std::make_pair(parent, iface_map_value_type{}));
+
+ std::pair<name_map_iterator, bool> ifaceEntry =
+ parentEntry.first->second.insert(
+ std::make_pair(well_known, default_ifaces));
+
+ if (!ifaceEntry.second)
+ {
+ // Entry was already there for this name so done.
+ break;
+ }
+
+ pos = parent.find_last_of('/');
+ }
}
};
OpenPOWER on IntegriCloud