blob: 352db9be477ec9b20a0fb3eafa6af27645328065 [file] [log] [blame]
Andrew Geisslera80a3af2019-02-04 14:01:49 -06001#include "associations.hpp"
2
3void removeAssociation(const std::string& sourcePath, const std::string& owner,
4 sdbusplus::asio::object_server& server,
5 AssociationOwnersType& assocOwners,
6 AssociationInterfaces& assocInterfaces)
7{
8 // Use associationOwners to find the association paths and endpoints
9 // that the passed in object path and service own. Remove all of
10 // these endpoints from the actual association D-Bus objects, and if
11 // the endpoints property is then empty, the whole association object
12 // can be removed. Note there can be multiple services that own an
13 // association, and also that sourcePath is the path of the object
14 // that contains the org.openbmc.Associations interface and not the
15 // association path itself.
16
17 // Find the services that have associations for this object path
18 auto owners = assocOwners.find(sourcePath);
19 if (owners == assocOwners.end())
20 {
21 return;
22 }
23
24 // Find the association paths and endpoints owned by this object
25 // path for this service.
26 auto assocs = owners->second.find(owner);
27 if (assocs == owners->second.end())
28 {
29 return;
30 }
31
32 for (const auto& [assocPath, endpointsToRemove] : assocs->second)
33 {
Andrew Geissler5629ae82019-02-21 12:59:09 -060034 removeAssociationEndpoints(server, assocPath, endpointsToRemove,
35 assocInterfaces);
Andrew Geisslera80a3af2019-02-04 14:01:49 -060036 }
37
38 // Remove the associationOwners entries for this owning path/service.
39 owners->second.erase(assocs);
40 if (owners->second.empty())
41 {
42 assocOwners.erase(owners);
43 }
44}
Andrew Geisslerff5ce922019-02-21 12:43:09 -060045
46void removeAssociationEndpoints(
47 sdbusplus::asio::object_server& objectServer, const std::string& assocPath,
48 const boost::container::flat_set<std::string>& endpointsToRemove,
49 AssociationInterfaces& assocInterfaces)
50{
51 auto assoc = assocInterfaces.find(assocPath);
52 if (assoc == assocInterfaces.end())
53 {
54 return;
55 }
56
57 auto& endpointsInDBus = std::get<endpointsPos>(assoc->second);
58
59 for (const auto& endpointToRemove : endpointsToRemove)
60 {
61 auto e = std::find(endpointsInDBus.begin(), endpointsInDBus.end(),
62 endpointToRemove);
63
64 if (e != endpointsInDBus.end())
65 {
66 endpointsInDBus.erase(e);
67 }
68 }
69
70 if (endpointsInDBus.empty())
71 {
72 objectServer.remove_interface(std::get<ifacePos>(assoc->second));
73 std::get<ifacePos>(assoc->second) = nullptr;
74 std::get<endpointsPos>(assoc->second).clear();
75 }
76 else
77 {
78 std::get<ifacePos>(assoc->second)
79 ->set_property("endpoints", endpointsInDBus);
80 }
81}
Andrew Geissler7f1c44d2019-02-21 13:44:16 -060082
83void checkAssociationEndpointRemoves(
84 const std::string& sourcePath, const std::string& owner,
85 const AssociationPaths& newAssociations,
86 sdbusplus::asio::object_server& objectServer,
87 AssociationOwnersType& assocOwners, AssociationInterfaces& assocInterfaces)
88{
89 // Find the services that have associations on this path.
90 auto originalOwners = assocOwners.find(sourcePath);
91 if (originalOwners == assocOwners.end())
92 {
93 return;
94 }
95
96 // Find the associations for this service
97 auto originalAssociations = originalOwners->second.find(owner);
98 if (originalAssociations == originalOwners->second.end())
99 {
100 return;
101 }
102
103 // Compare the new endpoints versus the original endpoints, and
104 // remove any of the original ones that aren't in the new list.
105 for (const auto& [originalAssocPath, originalEndpoints] :
106 originalAssociations->second)
107 {
108 // Check if this source even still has each association that
109 // was there previously, and if not, remove all of its endpoints
110 // from the D-Bus endpoints property which will cause the whole
111 // association path to be removed if no endpoints remain.
112 auto newEndpoints = newAssociations.find(originalAssocPath);
113 if (newEndpoints == newAssociations.end())
114 {
115 removeAssociationEndpoints(objectServer, originalAssocPath,
116 originalEndpoints, assocInterfaces);
117 }
118 else
119 {
120 // The association is still there. Check if the endpoints
121 // changed.
122 boost::container::flat_set<std::string> toRemove;
123
124 for (auto& originalEndpoint : originalEndpoints)
125 {
126 if (std::find(newEndpoints->second.begin(),
127 newEndpoints->second.end(),
128 originalEndpoint) == newEndpoints->second.end())
129 {
130 toRemove.emplace(originalEndpoint);
131 }
132 }
133 if (!toRemove.empty())
134 {
135 removeAssociationEndpoints(objectServer, originalAssocPath,
136 toRemove, assocInterfaces);
137 }
138 }
139 }
140}