summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-01-09 12:39:42 -0600
committerMatt Spinler <spinler@us.ibm.com>2019-01-11 13:24:18 -0600
commita82779fb66e30b0387077c28e6aec2dc1a957a61 (patch)
tree2a664d0a05a0288ffbdb87d3310fff69c9b6c5db
parent1b4a502b77e0fa031c62b301667ec7e132e21c2f (diff)
downloadphosphor-objmgr-a82779fb66e30b0387077c28e6aec2dc1a957a61.tar.gz
phosphor-objmgr-a82779fb66e30b0387077c28e6aec2dc1a957a61.zip
mapper: Delete unecessary parent paths on removes
When any application creates a path on D-Bus, D-Bus will automatically create all of the parent paths if they don't already exist with 3 interfaces - org.freedesktop.DBus.Peer, Introspectable, and Properties. The mapper knows about those from either an introspection or from explictly adding them during an interfacesAdded signal, so now it also has to delete them out of the mapper on an interfacesRemoved signal for the path being removed. To do this, when a path is removed, it will traverse all of its parents and check for the case of where a parent path only has 3 interfaces on it with the same owner, and there are no other children remaining with that owner. For example, if /A/B/C/D/E on owner X.Y is received in the interfacesRemoved handler, then after /A/B/C/D/E is removed from the interfaces map it will now check to see if /A/B/C/D is such that: * /A/B/C/D on owner X.Y has exactly 3 interfaces * There is no remaining path on X.Y that starts with /A/B/C/D/. If those are met, then /A/B/C/D on path X.Y will be removed from the interfaces map, and then the next parent /A/B/C will be checked. As soon as a parent doesn't need to be removed, the searching will stop. Tested: Check that these 3 interface paths that had been created are properly deleted, such as /xyz/openbmc_project/logging/entry when the last error log is removed. Change-Id: Ia9b79e6905108a76ddd6b425c22104bd77aedb24 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-rw-r--r--src/main.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index b1325e1..d0282db 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -529,6 +529,68 @@ void addObjectMapResult(
}
}
+// Remove parents of the passed in path that:
+// 1) Only have the 3 default interfaces on them
+// - Means D-Bus created these, not application code,
+// with the Properties, Introspectable, and Peer ifaces
+// 2) Have no other child for this owner
+void removeUnneededParents(const std::string& objectPath,
+ const std::string& owner,
+ interface_map_type& interface_map)
+{
+ auto parent = objectPath;
+
+ while (true)
+ {
+ auto pos = parent.find_last_of('/');
+ if ((pos == std::string::npos) || (pos == 0))
+ {
+ break;
+ }
+ parent = parent.substr(0, pos);
+
+ auto parent_it = interface_map.find(parent);
+ if (parent_it == interface_map.end())
+ {
+ break;
+ }
+
+ auto ifaces_it = parent_it->second.find(owner);
+ if (ifaces_it == parent_it->second.end())
+ {
+ break;
+ }
+
+ if (ifaces_it->second.size() != 3)
+ {
+ break;
+ }
+
+ auto child_path = parent + '/';
+
+ // Remove this parent if there isn't a remaining child on this owner
+ auto child = std::find_if(
+ interface_map.begin(), interface_map.end(),
+ [&owner, &child_path](const auto& entry) {
+ return boost::starts_with(entry.first, child_path) &&
+ (entry.second.find(owner) != entry.second.end());
+ });
+
+ if (child == interface_map.end())
+ {
+ parent_it->second.erase(ifaces_it);
+ if (parent_it->second.empty())
+ {
+ interface_map.erase(parent_it);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
int main(int argc, char** argv)
{
auto options = ArgumentParser(argc, argv);
@@ -776,6 +838,8 @@ int main(int argc, char** argv)
{
interface_map.erase(connection_map);
}
+
+ removeUnneededParents(obj_path.str, sender, interface_map);
};
sdbusplus::bus::match::match interfacesRemoved(
OpenPOWER on IntegriCloud