blob: 317836c9d54903b5681a78b8bb0ac3f66dec99f5 [file] [log] [blame]
Andrew Geisslera80a3af2019-02-04 14:01:49 -06001#include "associations.hpp"
2
Andrew Geissler4511b332019-02-21 15:40:40 -06003#include <iostream>
4
Andrew Geisslera80a3af2019-02-04 14:01:49 -06005void removeAssociation(const std::string& sourcePath, const std::string& owner,
6 sdbusplus::asio::object_server& server,
Matt Spinlere2359fb2019-04-05 14:11:33 -05007 AssociationMaps& assocMaps)
Andrew Geisslera80a3af2019-02-04 14:01:49 -06008{
9 // Use associationOwners to find the association paths and endpoints
10 // that the passed in object path and service own. Remove all of
11 // these endpoints from the actual association D-Bus objects, and if
12 // the endpoints property is then empty, the whole association object
13 // can be removed. Note there can be multiple services that own an
14 // association, and also that sourcePath is the path of the object
15 // that contains the org.openbmc.Associations interface and not the
16 // association path itself.
17
18 // Find the services that have associations for this object path
Matt Spinlere2359fb2019-04-05 14:11:33 -050019 auto owners = assocMaps.owners.find(sourcePath);
20 if (owners == assocMaps.owners.end())
Andrew Geisslera80a3af2019-02-04 14:01:49 -060021 {
22 return;
23 }
24
25 // Find the association paths and endpoints owned by this object
26 // path for this service.
27 auto assocs = owners->second.find(owner);
28 if (assocs == owners->second.end())
29 {
30 return;
31 }
32
33 for (const auto& [assocPath, endpointsToRemove] : assocs->second)
34 {
Andrew Geissler5629ae82019-02-21 12:59:09 -060035 removeAssociationEndpoints(server, assocPath, endpointsToRemove,
Matt Spinlere2359fb2019-04-05 14:11:33 -050036 assocMaps);
Andrew Geisslera80a3af2019-02-04 14:01:49 -060037 }
38
39 // Remove the associationOwners entries for this owning path/service.
40 owners->second.erase(assocs);
41 if (owners->second.empty())
42 {
Matt Spinlere2359fb2019-04-05 14:11:33 -050043 assocMaps.owners.erase(owners);
Andrew Geisslera80a3af2019-02-04 14:01:49 -060044 }
45}
Andrew Geisslerff5ce922019-02-21 12:43:09 -060046
47void removeAssociationEndpoints(
48 sdbusplus::asio::object_server& objectServer, const std::string& assocPath,
49 const boost::container::flat_set<std::string>& endpointsToRemove,
Matt Spinlere2359fb2019-04-05 14:11:33 -050050 AssociationMaps& assocMaps)
Andrew Geisslerff5ce922019-02-21 12:43:09 -060051{
Matt Spinlere2359fb2019-04-05 14:11:33 -050052 auto assoc = assocMaps.ifaces.find(assocPath);
53 if (assoc == assocMaps.ifaces.end())
Andrew Geisslerff5ce922019-02-21 12:43:09 -060054 {
55 return;
56 }
57
58 auto& endpointsInDBus = std::get<endpointsPos>(assoc->second);
59
60 for (const auto& endpointToRemove : endpointsToRemove)
61 {
62 auto e = std::find(endpointsInDBus.begin(), endpointsInDBus.end(),
63 endpointToRemove);
64
65 if (e != endpointsInDBus.end())
66 {
67 endpointsInDBus.erase(e);
68 }
69 }
70
71 if (endpointsInDBus.empty())
72 {
73 objectServer.remove_interface(std::get<ifacePos>(assoc->second));
74 std::get<ifacePos>(assoc->second) = nullptr;
75 std::get<endpointsPos>(assoc->second).clear();
76 }
77 else
78 {
79 std::get<ifacePos>(assoc->second)
80 ->set_property("endpoints", endpointsInDBus);
81 }
82}
Andrew Geissler7f1c44d2019-02-21 13:44:16 -060083
84void checkAssociationEndpointRemoves(
85 const std::string& sourcePath, const std::string& owner,
86 const AssociationPaths& newAssociations,
Matt Spinlere2359fb2019-04-05 14:11:33 -050087 sdbusplus::asio::object_server& objectServer, AssociationMaps& assocMaps)
Andrew Geissler7f1c44d2019-02-21 13:44:16 -060088{
89 // Find the services that have associations on this path.
Matt Spinlere2359fb2019-04-05 14:11:33 -050090 auto originalOwners = assocMaps.owners.find(sourcePath);
91 if (originalOwners == assocMaps.owners.end())
Andrew Geissler7f1c44d2019-02-21 13:44:16 -060092 {
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,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500116 originalEndpoints, assocMaps);
Andrew Geissler7f1c44d2019-02-21 13:44:16 -0600117 }
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,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500136 toRemove, assocMaps);
Andrew Geissler7f1c44d2019-02-21 13:44:16 -0600137 }
138 }
139 }
140}
Andrew Geissler4511b332019-02-21 15:40:40 -0600141
142void associationChanged(sdbusplus::asio::object_server& objectServer,
143 const std::vector<Association>& associations,
144 const std::string& path, const std::string& owner,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500145 AssociationMaps& assocMaps)
Andrew Geissler4511b332019-02-21 15:40:40 -0600146{
147 AssociationPaths objects;
148
149 for (const Association& association : associations)
150 {
151 std::string forward;
152 std::string reverse;
153 std::string endpoint;
154 std::tie(forward, reverse, endpoint) = association;
155
Andrew Geissler0a560a52019-03-22 10:59:07 -0500156 if (endpoint.empty())
157 {
158 std::cerr << "Found invalid association on path " << path << "\n";
159 continue;
160 }
Andrew Geissler4511b332019-02-21 15:40:40 -0600161 if (forward.size())
162 {
163 objects[path + "/" + forward].emplace(endpoint);
164 }
165 if (reverse.size())
166 {
Andrew Geissler4511b332019-02-21 15:40:40 -0600167 objects[endpoint + "/" + reverse].emplace(path);
168 }
169 }
170 for (const auto& object : objects)
171 {
172 // the mapper exposes the new association interface but intakes
173 // the old
174
Matt Spinlere2359fb2019-04-05 14:11:33 -0500175 auto& iface = assocMaps.ifaces[object.first];
Andrew Geissler4511b332019-02-21 15:40:40 -0600176 auto& i = std::get<ifacePos>(iface);
177 auto& endpoints = std::get<endpointsPos>(iface);
178
179 // Only add new endpoints
180 for (auto& e : object.second)
181 {
182 if (std::find(endpoints.begin(), endpoints.end(), e) ==
183 endpoints.end())
184 {
185 endpoints.push_back(e);
186 }
187 }
188
189 // If the interface already exists, only need to update
190 // the property value, otherwise create it
191 if (i)
192 {
193 i->set_property("endpoints", endpoints);
194 }
195 else
196 {
197 i = objectServer.add_interface(object.first,
198 XYZ_ASSOCIATION_INTERFACE);
199 i->register_property("endpoints", endpoints);
200 i->initialize();
201 }
202 }
203
204 // Check for endpoints being removed instead of added
205 checkAssociationEndpointRemoves(path, owner, objects, objectServer,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500206 assocMaps);
Andrew Geissler4511b332019-02-21 15:40:40 -0600207
208 // Update associationOwners with the latest info
Matt Spinlere2359fb2019-04-05 14:11:33 -0500209 auto a = assocMaps.owners.find(path);
210 if (a != assocMaps.owners.end())
Andrew Geissler4511b332019-02-21 15:40:40 -0600211 {
212 auto o = a->second.find(owner);
213 if (o != a->second.end())
214 {
215 o->second = std::move(objects);
216 }
217 else
218 {
219 a->second.emplace(owner, std::move(objects));
220 }
221 }
222 else
223 {
224 boost::container::flat_map<std::string, AssociationPaths> owners;
225 owners.emplace(owner, std::move(objects));
Matt Spinlere2359fb2019-04-05 14:11:33 -0500226 assocMaps.owners.emplace(path, owners);
Andrew Geissler4511b332019-02-21 15:40:40 -0600227 }
228}