blob: 0f84d1e344dc82ccd867306941935b4c80e8adc8 [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 Spinlere0b0e3a2019-04-08 10:39:23 -0500145 const interface_map_type& interfaceMap,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500146 AssociationMaps& assocMaps)
Andrew Geissler4511b332019-02-21 15:40:40 -0600147{
148 AssociationPaths objects;
149
150 for (const Association& association : associations)
151 {
152 std::string forward;
153 std::string reverse;
154 std::string endpoint;
155 std::tie(forward, reverse, endpoint) = association;
156
Andrew Geissler0a560a52019-03-22 10:59:07 -0500157 if (endpoint.empty())
158 {
159 std::cerr << "Found invalid association on path " << path << "\n";
160 continue;
161 }
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500162
163 // Can't create this association if the endpoint isn't on D-Bus.
164 if (interfaceMap.find(endpoint) == interfaceMap.end())
165 {
166 addPendingAssociation(endpoint, reverse, path, forward, owner,
167 assocMaps);
168 continue;
169 }
170
Andrew Geissler4511b332019-02-21 15:40:40 -0600171 if (forward.size())
172 {
173 objects[path + "/" + forward].emplace(endpoint);
174 }
175 if (reverse.size())
176 {
Andrew Geissler4511b332019-02-21 15:40:40 -0600177 objects[endpoint + "/" + reverse].emplace(path);
178 }
179 }
180 for (const auto& object : objects)
181 {
182 // the mapper exposes the new association interface but intakes
183 // the old
184
Matt Spinlere2359fb2019-04-05 14:11:33 -0500185 auto& iface = assocMaps.ifaces[object.first];
Andrew Geissler4511b332019-02-21 15:40:40 -0600186 auto& i = std::get<ifacePos>(iface);
187 auto& endpoints = std::get<endpointsPos>(iface);
188
189 // Only add new endpoints
190 for (auto& e : object.second)
191 {
192 if (std::find(endpoints.begin(), endpoints.end(), e) ==
193 endpoints.end())
194 {
195 endpoints.push_back(e);
196 }
197 }
198
199 // If the interface already exists, only need to update
200 // the property value, otherwise create it
201 if (i)
202 {
203 i->set_property("endpoints", endpoints);
204 }
205 else
206 {
207 i = objectServer.add_interface(object.first,
208 XYZ_ASSOCIATION_INTERFACE);
209 i->register_property("endpoints", endpoints);
210 i->initialize();
211 }
212 }
213
214 // Check for endpoints being removed instead of added
215 checkAssociationEndpointRemoves(path, owner, objects, objectServer,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500216 assocMaps);
Andrew Geissler4511b332019-02-21 15:40:40 -0600217
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500218 if (!objects.empty())
Andrew Geissler4511b332019-02-21 15:40:40 -0600219 {
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500220 // Update associationOwners with the latest info
221 auto a = assocMaps.owners.find(path);
222 if (a != assocMaps.owners.end())
Andrew Geissler4511b332019-02-21 15:40:40 -0600223 {
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500224 auto o = a->second.find(owner);
225 if (o != a->second.end())
226 {
227 o->second = std::move(objects);
228 }
229 else
230 {
231 a->second.emplace(owner, std::move(objects));
232 }
Andrew Geissler4511b332019-02-21 15:40:40 -0600233 }
234 else
235 {
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500236 boost::container::flat_map<std::string, AssociationPaths> owners;
237 owners.emplace(owner, std::move(objects));
238 assocMaps.owners.emplace(path, owners);
Andrew Geissler4511b332019-02-21 15:40:40 -0600239 }
240 }
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500241}
242
243void addPendingAssociation(const std::string& objectPath,
244 const std::string& type,
245 const std::string& endpointPath,
246 const std::string& endpointType,
247 const std::string& owner, AssociationMaps& assocMaps)
248{
249 Association assoc{type, endpointType, endpointPath};
250
251 auto p = assocMaps.pending.find(objectPath);
252 if (p == assocMaps.pending.end())
253 {
254 ExistingEndpoints ee;
255 ee.emplace_back(owner, std::move(assoc));
256 assocMaps.pending.emplace(objectPath, std::move(ee));
257 }
Andrew Geissler4511b332019-02-21 15:40:40 -0600258 else
259 {
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500260 // Already waiting on this path for another association,
261 // so just add this endpoint and owner.
262 auto& endpoints = p->second;
263 auto e =
264 std::find_if(endpoints.begin(), endpoints.end(),
265 [&assoc, &owner](const auto& endpoint) {
266 return (std::get<ownerPos>(endpoint) == owner) &&
267 (std::get<assocPos>(endpoint) == assoc);
268 });
269 if (e == endpoints.end())
270 {
271 endpoints.emplace_back(owner, std::move(assoc));
272 }
Andrew Geissler4511b332019-02-21 15:40:40 -0600273 }
274}