blob: c309d871ffb6c12576c746609cec5b00bef995c6 [file] [log] [blame]
Andrew Geisslera80a3af2019-02-04 14:01:49 -06001#include "associations.hpp"
Andrew Geissler3b025e62019-02-01 10:33:54 -06002#include "processing.hpp"
Matt Spinler35396c12019-04-05 11:46:57 -05003#include "types.hpp"
Matt Spinlerdd945862018-09-07 12:41:05 -05004
Ed Tanous60520632018-06-11 17:46:52 -07005#include <tinyxml2.h>
6
Ed Tanous21c60592020-08-17 23:43:46 -07007#include <boost/asio/io_context.hpp>
8#include <boost/asio/signal_set.hpp>
Ed Tanous60520632018-06-11 17:46:52 -07009#include <boost/container/flat_map.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070010#include <sdbusplus/asio/connection.hpp>
11#include <sdbusplus/asio/object_server.hpp>
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +030012#include <xyz/openbmc_project/Common/error.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070013
Brad Bishop23520882022-05-26 21:39:53 -040014#include <atomic>
15#include <chrono>
Brad Bishopea119462022-05-31 20:32:04 -040016#include <exception>
Brad Bishop23520882022-05-26 21:39:53 -040017#include <iomanip>
18#include <iostream>
Brandon Kimf6ebfc72022-07-07 12:53:44 -070019#include <string>
20#include <string_view>
Brad Bishop1f623802022-05-31 18:22:10 -040021#include <utility>
Brad Bishop23520882022-05-26 21:39:53 -040022
Matt Spinlere2359fb2019-04-05 14:11:33 -050023AssociationMaps associationMaps;
Matt Spinler937a2322019-01-23 13:54:22 -060024
Brad Bishopa098a372022-05-05 15:19:04 -040025void updateOwners(sdbusplus::asio::connection* conn,
26 boost::container::flat_map<std::string, std::string>& owners,
27 const std::string& newObject)
Ed Tanous60520632018-06-11 17:46:52 -070028{
Brad Bishop86d28802022-07-11 15:49:31 -040029 if (newObject.starts_with(":"))
Ed Tanous60520632018-06-11 17:46:52 -070030 {
31 return;
32 }
33 conn->async_method_call(
Brad Bishopa098a372022-05-05 15:19:04 -040034 [&, newObject](const boost::system::error_code ec,
35 const std::string& nameOwner) {
Ed Tanous60520632018-06-11 17:46:52 -070036 if (ec)
37 {
Brad Bishopa098a372022-05-05 15:19:04 -040038 std::cerr << "Error getting owner of " << newObject << " : "
Ed Tanous60520632018-06-11 17:46:52 -070039 << ec << "\n";
40 return;
41 }
Brad Bishopa098a372022-05-05 15:19:04 -040042 owners[nameOwner] = newObject;
Ed Tanous60520632018-06-11 17:46:52 -070043 },
44 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
Brad Bishopa098a372022-05-05 15:19:04 -040045 newObject);
Ed Tanous60520632018-06-11 17:46:52 -070046}
47
Brad Bishopa098a372022-05-05 15:19:04 -040048void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
49 const std::string& processName)
Ed Tanous60520632018-06-11 17:46:52 -070050{
51 // TODO(ed) This signal doesn't get exposed properly in the
52 // introspect right now. Find out how to register signals in
53 // sdbusplus
Patrick Williamscc8070b2022-07-22 19:26:55 -050054 sdbusplus::message_t m = systemBus->new_signal(
Brad Bishopa02cd542021-10-12 19:12:42 -040055 "/xyz/openbmc_project/object_mapper",
56 "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
Brad Bishopa098a372022-05-05 15:19:04 -040057 m.append(processName);
Ed Tanous60520632018-06-11 17:46:52 -070058 m.signal_send();
59}
60
61struct InProgressIntrospect
62{
Brad Bishop1f623802022-05-31 18:22:10 -040063 InProgressIntrospect() = delete;
64 InProgressIntrospect(const InProgressIntrospect&) = delete;
65 InProgressIntrospect(InProgressIntrospect&&) = delete;
66 InProgressIntrospect& operator=(const InProgressIntrospect&) = delete;
67 InProgressIntrospect& operator=(InProgressIntrospect&&) = delete;
Ed Tanous60520632018-06-11 17:46:52 -070068 InProgressIntrospect(
Brad Bishopa098a372022-05-05 15:19:04 -040069 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
70 const std::string& processName, AssociationMaps& am
Brad Bishopd6aa5522022-05-31 19:23:48 -040071#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050072 ,
Ed Tanous60520632018-06-11 17:46:52 -070073 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -040074 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -050075#endif
76 ) :
Brad Bishopa098a372022-05-05 15:19:04 -040077 systemBus(systemBus),
78 io(io), processName(processName), assocMaps(am)
Brad Bishopd6aa5522022-05-31 19:23:48 -040079#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050080 ,
Brad Bishop1f623802022-05-31 18:22:10 -040081 globalStartTime(std::move(globalStartTime)),
Brad Bishopa098a372022-05-05 15:19:04 -040082 processStartTime(std::chrono::steady_clock::now())
Matt Spinleraecabe82018-09-19 13:25:42 -050083#endif
Brad Bishop23520882022-05-26 21:39:53 -040084 {}
Ed Tanous60520632018-06-11 17:46:52 -070085 ~InProgressIntrospect()
86 {
Brad Bishopea119462022-05-31 20:32:04 -040087 try
Ed Tanous60520632018-06-11 17:46:52 -070088 {
Brad Bishopea119462022-05-31 20:32:04 -040089 sendIntrospectionCompleteSignal(systemBus, processName);
Brad Bishopd6aa5522022-05-31 19:23:48 -040090#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopea119462022-05-31 20:32:04 -040091 std::chrono::duration<float> diff =
92 std::chrono::steady_clock::now() - processStartTime;
93 std::cout << std::setw(50) << processName << " scan took "
94 << diff.count() << " seconds\n";
95
96 // If we're the last outstanding caller globally, calculate the
97 // time it took
98 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
99 {
100 diff = std::chrono::steady_clock::now() - *globalStartTime;
101 std::cout << "Total scan took " << diff.count()
102 << " seconds to complete\n";
103 }
Matt Spinleraecabe82018-09-19 13:25:42 -0500104#endif
Brad Bishopea119462022-05-31 20:32:04 -0400105 }
106 catch (const std::exception& e)
107 {
108 std::cerr
109 << "Terminating, unhandled exception while introspecting: "
110 << e.what() << "\n";
111 std::terminate();
112 }
113 catch (...)
114 {
115 std::cerr
116 << "Terminating, unhandled exception while introspecting\n";
117 std::terminate();
118 }
Ed Tanous60520632018-06-11 17:46:52 -0700119 }
Brad Bishopa098a372022-05-05 15:19:04 -0400120 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700121 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400122 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500123 AssociationMaps& assocMaps;
Brad Bishopd6aa5522022-05-31 19:23:48 -0400124#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700125 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400126 globalStartTime;
127 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500128#endif
Ed Tanous60520632018-06-11 17:46:52 -0700129};
130
Brad Bishopa098a372022-05-05 15:19:04 -0400131void doAssociations(sdbusplus::asio::connection* systemBus,
132 InterfaceMapType& interfaceMap,
133 sdbusplus::asio::object_server& objectServer,
134 const std::string& processName, const std::string& path,
135 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700136{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100137 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400138 systemBus->async_method_call(
139 [&objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100140 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600141 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500142 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700143 if (ec)
144 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100145 if (ec.value() == boost::system::errc::timed_out &&
146 timeoutRetries < maxTimeoutRetries)
147 {
Brad Bishopa098a372022-05-05 15:19:04 -0400148 doAssociations(systemBus, interfaceMap, objectServer,
149 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100150 return;
151 }
Ed Tanous60520632018-06-11 17:46:52 -0700152 std::cerr << "Error getting associations from " << path << "\n";
153 }
154 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500155 std::get<std::vector<Association>>(variantAssociations);
Andrew Geissler4511b332019-02-21 15:40:40 -0600156 associationChanged(objectServer, associations, path, processName,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500157 interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700158 },
159 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800160 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700161}
162
Brad Bishopa098a372022-05-05 15:19:04 -0400163void doIntrospect(sdbusplus::asio::connection* systemBus,
Brad Bishop1f623802022-05-31 18:22:10 -0400164 const std::shared_ptr<InProgressIntrospect>& transaction,
Brad Bishopa098a372022-05-05 15:19:04 -0400165 InterfaceMapType& interfaceMap,
166 sdbusplus::asio::object_server& objectServer,
Brad Bishop1f623802022-05-31 18:22:10 -0400167 const std::string& path, int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700168{
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800169 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400170 systemBus->async_method_call(
171 [&interfaceMap, &objectServer, transaction, path, systemBus,
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800172 timeoutRetries](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400173 const std::string& introspectXml) {
Ed Tanous60520632018-06-11 17:46:52 -0700174 if (ec)
175 {
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800176 if (ec.value() == boost::system::errc::timed_out &&
177 timeoutRetries < maxTimeoutRetries)
178 {
Brad Bishopa098a372022-05-05 15:19:04 -0400179 doIntrospect(systemBus, transaction, interfaceMap,
180 objectServer, path, timeoutRetries + 1);
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800181 return;
182 }
Ed Tanous60520632018-06-11 17:46:52 -0700183 std::cerr << "Introspect call failed with error: " << ec << ", "
184 << ec.message()
Brad Bishopa098a372022-05-05 15:19:04 -0400185 << " on process: " << transaction->processName
Ed Tanous60520632018-06-11 17:46:52 -0700186 << " path: " << path << "\n";
187 return;
188 }
189
190 tinyxml2::XMLDocument doc;
191
Brad Bishopa098a372022-05-05 15:19:04 -0400192 tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
Ed Tanous60520632018-06-11 17:46:52 -0700193 if (e != tinyxml2::XMLError::XML_SUCCESS)
194 {
195 std::cerr << "XML parsing failed\n";
196 return;
197 }
198
199 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
200 if (pRoot == nullptr)
201 {
202 std::cerr << "XML document did not contain any data\n";
203 return;
204 }
Brad Bishopa098a372022-05-05 15:19:04 -0400205 auto& thisPathMap = interfaceMap[path];
Ed Tanous60520632018-06-11 17:46:52 -0700206 tinyxml2::XMLElement* pElement =
207 pRoot->FirstChildElement("interface");
208 while (pElement != nullptr)
209 {
Brad Bishopa098a372022-05-05 15:19:04 -0400210 const char* ifaceName = pElement->Attribute("name");
211 if (ifaceName == nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700212 {
213 continue;
214 }
215
Brad Bishopa098a372022-05-05 15:19:04 -0400216 thisPathMap[transaction->processName].emplace(ifaceName);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800217
Brad Bishopa098a372022-05-05 15:19:04 -0400218 if (std::strcmp(ifaceName, assocDefsInterface) == 0)
Ed Tanous60520632018-06-11 17:46:52 -0700219 {
Brad Bishopa098a372022-05-05 15:19:04 -0400220 doAssociations(systemBus, interfaceMap, objectServer,
221 transaction->processName, path);
Ed Tanous60520632018-06-11 17:46:52 -0700222 }
Ed Tanous60520632018-06-11 17:46:52 -0700223
224 pElement = pElement->NextSiblingElement("interface");
225 }
226
Matt Spinler11401e22019-04-08 13:13:25 -0500227 // Check if this new path has a pending association that can
228 // now be completed.
Brad Bishopa098a372022-05-05 15:19:04 -0400229 checkIfPendingAssociation(path, interfaceMap,
Matt Spinler11401e22019-04-08 13:13:25 -0500230 transaction->assocMaps, objectServer);
231
Ed Tanous50232cd2018-11-12 11:34:43 -0800232 pElement = pRoot->FirstChildElement("node");
233 while (pElement != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700234 {
Brad Bishopa098a372022-05-05 15:19:04 -0400235 const char* childPath = pElement->Attribute("name");
236 if (childPath != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700237 {
Brad Bishopa098a372022-05-05 15:19:04 -0400238 std::string parentPath(path);
239 if (parentPath == "/")
Ed Tanous60520632018-06-11 17:46:52 -0700240 {
Brad Bishopa098a372022-05-05 15:19:04 -0400241 parentPath.clear();
Ed Tanous60520632018-06-11 17:46:52 -0700242 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800243
Brad Bishopa098a372022-05-05 15:19:04 -0400244 doIntrospect(systemBus, transaction, interfaceMap,
245 objectServer, parentPath + "/" + childPath);
Ed Tanous60520632018-06-11 17:46:52 -0700246 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800247 pElement = pElement->NextSiblingElement("node");
Ed Tanous60520632018-06-11 17:46:52 -0700248 }
249 },
Brad Bishopa098a372022-05-05 15:19:04 -0400250 transaction->processName, path, "org.freedesktop.DBus.Introspectable",
Ed Tanous60520632018-06-11 17:46:52 -0700251 "Introspect");
252}
253
Brad Bishopa098a372022-05-05 15:19:04 -0400254void startNewIntrospect(
255 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
256 InterfaceMapType& interfaceMap, const std::string& processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500257 AssociationMaps& assocMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400258#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700259 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400260 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500261#endif
Ed Tanous60520632018-06-11 17:46:52 -0700262 sdbusplus::asio::object_server& objectServer)
263{
Brad Bishop1e94e602022-06-02 19:47:53 -0400264 if (needToIntrospect(processName))
Ed Tanous60520632018-06-11 17:46:52 -0700265 {
Ed Tanous60520632018-06-11 17:46:52 -0700266 std::shared_ptr<InProgressIntrospect> transaction =
Brad Bishopa098a372022-05-05 15:19:04 -0400267 std::make_shared<InProgressIntrospect>(systemBus, io, processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500268 assocMaps
Brad Bishopd6aa5522022-05-31 19:23:48 -0400269#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -0500270 ,
Brad Bishopa098a372022-05-05 15:19:04 -0400271 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -0500272#endif
273 );
Ed Tanous60520632018-06-11 17:46:52 -0700274
Brad Bishopa098a372022-05-05 15:19:04 -0400275 doIntrospect(systemBus, transaction, interfaceMap, objectServer, "/");
Ed Tanous60520632018-06-11 17:46:52 -0700276 }
277}
278
279// TODO(ed) replace with std::set_intersection once c++17 is available
280template <class InputIt1, class InputIt2>
281bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
282{
283 while (first1 != last1 && first2 != last2)
284 {
285 if (*first1 < *first2)
286 {
287 ++first1;
288 continue;
289 }
290 if (*first2 < *first1)
291 {
292 ++first2;
293 continue;
294 }
295 return true;
296 }
297 return false;
298}
299
300void doListNames(
Brad Bishopa098a372022-05-05 15:19:04 -0400301 boost::asio::io_context& io, InterfaceMapType& interfaceMap,
302 sdbusplus::asio::connection* systemBus,
303 boost::container::flat_map<std::string, std::string>& nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500304 AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
Ed Tanous60520632018-06-11 17:46:52 -0700305{
Brad Bishopa098a372022-05-05 15:19:04 -0400306 systemBus->async_method_call(
307 [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
Matt Spinler11401e22019-04-08 13:13:25 -0500308 &assocMaps](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400309 std::vector<std::string> processNames) {
Ed Tanous60520632018-06-11 17:46:52 -0700310 if (ec)
311 {
312 std::cerr << "Error getting names: " << ec << "\n";
313 std::exit(EXIT_FAILURE);
314 return;
315 }
Ed Tanous60520632018-06-11 17:46:52 -0700316 // Try to make startup consistent
Brad Bishopa098a372022-05-05 15:19:04 -0400317 std::sort(processNames.begin(), processNames.end());
Brad Bishopd6aa5522022-05-31 19:23:48 -0400318#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700319 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400320 globalStartTime = std::make_shared<
Ed Tanous60520632018-06-11 17:46:52 -0700321 std::chrono::time_point<std::chrono::steady_clock>>(
322 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500323#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400324 for (const std::string& processName : processNames)
Ed Tanous60520632018-06-11 17:46:52 -0700325 {
Brad Bishop1e94e602022-06-02 19:47:53 -0400326 if (needToIntrospect(processName))
Ed Tanous60520632018-06-11 17:46:52 -0700327 {
Brad Bishopa098a372022-05-05 15:19:04 -0400328 startNewIntrospect(systemBus, io, interfaceMap, processName,
329 assocMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400330#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400331 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500332#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400333 objectServer);
334 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700335 }
336 }
337 },
338 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
339 "ListNames");
340}
341
Ed Tanous964681c2022-07-08 12:47:24 -0700342void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
343 const std::string& objectPath,
344 const ConnectionNames::value_type& interfaceMap)
Matt Spinler9f0958e2018-09-11 08:26:10 -0500345{
346 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600347 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500348 // If an entry for the object path already exists, just add the
349 // service name and interfaces to that entry, otherwise create
350 // a new entry.
351 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600352 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500353 [&objectPath](const auto& i) { return objectPath == i.first; });
354
Matt Spinler47c09752018-11-29 14:54:13 -0600355 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500356 {
357 entry->second.emplace(interfaceMap);
358 }
359 else
360 {
Brad Bishopa098a372022-05-05 15:19:04 -0400361 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500362 object.first = objectPath;
363 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600364 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500365 }
366}
367
Matt Spinlera82779f2019-01-09 12:39:42 -0600368// Remove parents of the passed in path that:
369// 1) Only have the 3 default interfaces on them
370// - Means D-Bus created these, not application code,
371// with the Properties, Introspectable, and Peer ifaces
372// 2) Have no other child for this owner
373void removeUnneededParents(const std::string& objectPath,
374 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400375 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600376{
377 auto parent = objectPath;
378
379 while (true)
380 {
381 auto pos = parent.find_last_of('/');
382 if ((pos == std::string::npos) || (pos == 0))
383 {
384 break;
385 }
386 parent = parent.substr(0, pos);
387
Brad Bishopa098a372022-05-05 15:19:04 -0400388 auto parentIt = interfaceMap.find(parent);
389 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600390 {
391 break;
392 }
393
Brad Bishopa098a372022-05-05 15:19:04 -0400394 auto ifacesIt = parentIt->second.find(owner);
395 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600396 {
397 break;
398 }
399
Brad Bishopa098a372022-05-05 15:19:04 -0400400 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600401 {
402 break;
403 }
404
Brad Bishopa098a372022-05-05 15:19:04 -0400405 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600406
407 // Remove this parent if there isn't a remaining child on this owner
408 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400409 interfaceMap.begin(), interfaceMap.end(),
410 [&owner, &childPath](const auto& entry) {
Brad Bishop86d28802022-07-11 15:49:31 -0400411 return entry.first.starts_with(childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600412 (entry.second.find(owner) != entry.second.end());
413 });
414
Brad Bishopa098a372022-05-05 15:19:04 -0400415 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600416 {
Brad Bishopa098a372022-05-05 15:19:04 -0400417 parentIt->second.erase(ifacesIt);
418 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600419 {
Brad Bishopa098a372022-05-05 15:19:04 -0400420 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600421 }
422 }
423 else
424 {
425 break;
426 }
427 }
428}
429
Brad Bishopa098a372022-05-05 15:19:04 -0400430std::vector<InterfaceMapType::value_type>
431 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700432 std::vector<std::string>& interfaces)
433{
434 // Interfaces need to be sorted for intersect to function
435 std::sort(interfaces.begin(), interfaces.end());
436
Brad Bishop86d28802022-07-11 15:49:31 -0400437 if (reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700438 {
Brad Bishopa098a372022-05-05 15:19:04 -0400439 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700440 }
Brad Bishop1f623802022-05-31 18:22:10 -0400441 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700442 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300443 throw sdbusplus::xyz::openbmc_project::Common::Error::
444 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700445 }
446
Brad Bishopa098a372022-05-05 15:19:04 -0400447 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400448 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700449 {
Brad Bishop1f623802022-05-31 18:22:10 -0400450 const auto& thisPath = objectPath.first;
Brandon Kim82720f02022-07-08 09:57:22 -0700451
452 if (reqPath == thisPath)
453 {
454 continue;
455 }
456
Brad Bishop86d28802022-07-11 15:49:31 -0400457 if (reqPath.starts_with(thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700458 {
459 if (interfaces.empty())
460 {
Brad Bishopa098a372022-05-05 15:19:04 -0400461 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700462 }
463 else
464 {
Brad Bishop1f623802022-05-31 18:22:10 -0400465 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700466 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700467 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400468 interfaceMap.second.begin(),
469 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700470 {
Brad Bishopa098a372022-05-05 15:19:04 -0400471 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700472 }
473 }
474 }
475 }
476 }
477
478 return ret;
479}
480
Ed Tanous964681c2022-07-08 12:47:24 -0700481ConnectionNames getObject(const InterfaceMapType& interfaceMap,
482 const std::string& path,
483 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700484{
Ed Tanous964681c2022-07-08 12:47:24 -0700485 ConnectionNames results;
Ed Tanous0a13c762021-09-28 13:29:25 -0700486
487 // Interfaces need to be sorted for intersect to function
488 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400489 auto pathRef = interfaceMap.find(path);
490 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700491 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300492 throw sdbusplus::xyz::openbmc_project::Common::Error::
493 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700494 }
495 if (interfaces.empty())
496 {
Brad Bishopa098a372022-05-05 15:19:04 -0400497 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700498 }
Brad Bishop1f623802022-05-31 18:22:10 -0400499 for (const auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700500 {
501 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400502 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700503 {
Brad Bishopa098a372022-05-05 15:19:04 -0400504 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700505 }
506 }
507
508 if (results.empty())
509 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300510 throw sdbusplus::xyz::openbmc_project::Common::Error::
511 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700512 }
513
514 return results;
515}
516
Brad Bishopa098a372022-05-05 15:19:04 -0400517std::vector<InterfaceMapType::value_type>
518 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700519 int32_t depth, std::vector<std::string>& interfaces)
520{
521 if (depth <= 0)
522 {
523 depth = std::numeric_limits<int32_t>::max();
524 }
525 // Interfaces need to be sorted for intersect to function
526 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700527
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700528 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
529 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400530 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700531 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700532 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700533 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700534 std::string_view reqPathStripped =
535 std::string_view(reqPath).substr(0, reqPath.size() - 1);
536
537 if (!reqPathStripped.empty() &&
538 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700539 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300540 throw sdbusplus::xyz::openbmc_project::Common::Error::
541 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700542 }
543
Brandon Kim82720f02022-07-08 09:57:22 -0700544 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400545 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700546 {
Brad Bishop1f623802022-05-31 18:22:10 -0400547 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700548
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700549 // Skip exact match on stripped search term
550 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700551 {
552 continue;
553 }
554
Brad Bishop86d28802022-07-11 15:49:31 -0400555 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700556 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700557 // count the number of slashes past the stripped search term
558 int32_t thisDepth = std::count(
559 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400560 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700561 {
Brad Bishop1f623802022-05-31 18:22:10 -0400562 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700563 {
564 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400565 interfaceMap.second.begin(),
566 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700567 interfaces.empty())
568 {
Brad Bishopa098a372022-05-05 15:19:04 -0400569 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700570 }
571 }
572 }
573 }
574 }
575
576 return ret;
577}
578
Brad Bishopa098a372022-05-05 15:19:04 -0400579std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
580 std::string reqPath, int32_t depth,
581 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700582{
583 if (depth <= 0)
584 {
585 depth = std::numeric_limits<int32_t>::max();
586 }
587 // Interfaces need to be sorted for intersect to function
588 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700589
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700590 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
591 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400592 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700593 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700594 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700595 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700596 std::string_view reqPathStripped =
597 std::string_view(reqPath).substr(0, reqPath.size() - 1);
598
599 if (!reqPathStripped.empty() &&
600 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700601 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300602 throw sdbusplus::xyz::openbmc_project::Common::Error::
603 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700604 }
605
Brandon Kim82720f02022-07-08 09:57:22 -0700606 std::vector<std::string> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400607 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700608 {
Brad Bishop1f623802022-05-31 18:22:10 -0400609 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700610
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700611 // Skip exact match on stripped search term
612 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700613 {
614 continue;
615 }
616
Brad Bishop86d28802022-07-11 15:49:31 -0400617 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700618 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700619 // count the number of slashes past the stripped search term
620 int thisDepth = std::count(
621 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400622 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700623 {
624 bool add = interfaces.empty();
Brad Bishop1f623802022-05-31 18:22:10 -0400625 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700626 {
627 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400628 interfaceMap.second.begin(),
629 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700630 {
631 add = true;
632 break;
633 }
634 }
635 if (add)
636 {
637 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400638 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700639 }
640 }
641 }
642 }
643
644 return ret;
645}
646
Brad Bishop1e94e602022-06-02 19:47:53 -0400647int main()
Ed Tanous60520632018-06-11 17:46:52 -0700648{
Ed Tanous21c60592020-08-17 23:43:46 -0700649 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400650 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700651 std::make_shared<sdbusplus::asio::connection>(io);
652
Brad Bishopa098a372022-05-05 15:19:04 -0400653 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700654
655 // Construct a signal set registered for process termination.
656 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400657 signals.async_wait(
658 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700659
Brad Bishopa098a372022-05-05 15:19:04 -0400660 InterfaceMapType interfaceMap;
661 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700662
Patrick Williamscc8070b2022-07-22 19:26:55 -0500663 std::function<void(sdbusplus::message_t & message)> nameChangeHandler =
664 [&interfaceMap, &io, &nameOwners, &server,
665 systemBus](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400666 std::string name; // well-known
667 std::string oldOwner; // unique-name
668 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700669
Brad Bishopa098a372022-05-05 15:19:04 -0400670 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700671
Patrick Williams48248202022-10-10 10:26:47 -0500672 if (name.starts_with(':'))
673 {
674 // We should do nothing with unique-name connections.
675 return;
676 }
677
Brad Bishopa098a372022-05-05 15:19:04 -0400678 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700679 {
Brad Bishopa098a372022-05-05 15:19:04 -0400680 processNameChangeDelete(nameOwners, name, oldOwner,
681 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700682 }
683
Brad Bishopa098a372022-05-05 15:19:04 -0400684 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700685 {
Brad Bishopd6aa5522022-05-31 19:23:48 -0400686#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700687 auto transaction = std::make_shared<
688 std::chrono::time_point<std::chrono::steady_clock>>(
689 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500690#endif
Ed Tanous60520632018-06-11 17:46:52 -0700691 // New daemon added
Brad Bishop1e94e602022-06-02 19:47:53 -0400692 if (needToIntrospect(name))
Ed Tanous60520632018-06-11 17:46:52 -0700693 {
Brad Bishopa098a372022-05-05 15:19:04 -0400694 nameOwners[newOwner] = name;
695 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
696 associationMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400697#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400698 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500699#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400700 server);
Ed Tanous60520632018-06-11 17:46:52 -0700701 }
702 }
703 };
704
Patrick Williamscc8070b2022-07-22 19:26:55 -0500705 sdbusplus::bus::match_t nameOwnerChanged(
706 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700707 sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler);
708
Patrick Williamscc8070b2022-07-22 19:26:55 -0500709 std::function<void(sdbusplus::message_t & message)> interfacesAddedHandler =
710 [&interfaceMap, &nameOwners, &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400711 sdbusplus::message::object_path objPath;
712 InterfacesAdded interfacesAdded;
713 message.read(objPath, interfacesAdded);
714 std::string wellKnown;
715 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700716 {
717 return; // only introspect well-known
718 }
Brad Bishop1e94e602022-06-02 19:47:53 -0400719 if (needToIntrospect(wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700720 {
Brad Bishopa098a372022-05-05 15:19:04 -0400721 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
722 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700723 }
724 };
725
Patrick Williamscc8070b2022-07-22 19:26:55 -0500726 sdbusplus::bus::match_t interfacesAdded(
727 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700728 sdbusplus::bus::match::rules::interfacesAdded(),
729 interfacesAddedHandler);
730
Patrick Williamscc8070b2022-07-22 19:26:55 -0500731 std::function<void(sdbusplus::message_t & message)>
732 interfacesRemovedHandler = [&interfaceMap, &nameOwners,
733 &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400734 sdbusplus::message::object_path objPath;
735 std::vector<std::string> interfacesRemoved;
736 message.read(objPath, interfacesRemoved);
737 auto connectionMap = interfaceMap.find(objPath.str);
738 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700739 {
740 return;
741 }
742
743 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400744 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700745 {
746 return;
747 }
Brad Bishopa098a372022-05-05 15:19:04 -0400748 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700749 {
Brad Bishopa098a372022-05-05 15:19:04 -0400750 auto interfaceSet = connectionMap->second.find(sender);
751 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700752 {
753 continue;
754 }
755
John Wangd0cf9422019-09-17 16:01:34 +0800756 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700757 {
Brad Bishopa098a372022-05-05 15:19:04 -0400758 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500759 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700760 }
761
Brad Bishopa098a372022-05-05 15:19:04 -0400762 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500763
Brad Bishopa098a372022-05-05 15:19:04 -0400764 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700765 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500766 // If this was the last interface on this connection,
767 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400768 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500769
770 // Instead of checking if every single path is the endpoint
771 // of an association that needs to be moved to pending,
772 // only check when the only remaining owner of this path is
773 // ourself, which would be because we still own the
774 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400775 if ((connectionMap->second.size() == 1) &&
776 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400777 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500778 {
779 // Remove the 2 association D-Bus paths and move the
780 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400781 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500782 server);
783 }
Ed Tanous60520632018-06-11 17:46:52 -0700784 }
785 }
786 // If this was the last connection on this object path,
787 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400788 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700789 {
Brad Bishopa098a372022-05-05 15:19:04 -0400790 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700791 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600792
Brad Bishopa098a372022-05-05 15:19:04 -0400793 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700794 };
795
Patrick Williamscc8070b2022-07-22 19:26:55 -0500796 sdbusplus::bus::match_t interfacesRemoved(
797 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700798 sdbusplus::bus::match::rules::interfacesRemoved(),
799 interfacesRemovedHandler);
800
Patrick Williamscc8070b2022-07-22 19:26:55 -0500801 std::function<void(sdbusplus::message_t & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400802 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Patrick Williamscc8070b2022-07-22 19:26:55 -0500803 sdbusplus::message_t& message) {
Matt Spinler8f876a52019-04-15 13:22:50 -0500804 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500805 boost::container::flat_map<std::string,
806 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500807 values;
808 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800809 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500810 if (prop != values.end())
811 {
812 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500813 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500814
Brad Bishopa098a372022-05-05 15:19:04 -0400815 std::string wellKnown;
816 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500817 {
818 return;
Ed Tanous60520632018-06-11 17:46:52 -0700819 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500820 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400821 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500822 }
823 };
Patrick Williamscc8070b2022-07-22 19:26:55 -0500824 sdbusplus::bus::match_t assocChangedMatch(
825 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700826 sdbusplus::bus::match::rules::interface(
827 "org.freedesktop.DBus.Properties") +
828 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500829 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
830 associationChangedHandler);
831
Ed Tanous60520632018-06-11 17:46:52 -0700832 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400833 server.add_interface("/xyz/openbmc_project/object_mapper",
834 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700835
836 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400837 "GetAncestors", [&interfaceMap](std::string& reqPath,
838 std::vector<std::string>& interfaces) {
839 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700840 });
841
842 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400843 "GetObject", [&interfaceMap](const std::string& path,
844 std::vector<std::string>& interfaces) {
845 return getObject(interfaceMap, path, interfaces);
846 });
847
848 iface->register_method(
849 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700850 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400851 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700852 });
853
854 iface->register_method(
855 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400856 [&interfaceMap](std::string& reqPath, int32_t depth,
857 std::vector<std::string>& interfaces) {
858 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700859 });
860
861 iface->initialize();
862
863 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400864 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500865 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700866 });
867
Brad Bishopa098a372022-05-05 15:19:04 -0400868 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500869
Ed Tanous60520632018-06-11 17:46:52 -0700870 io.run();
871}