1 #include "entity_manager_interface.hpp"
2
3 #include <phosphor-logging/lg2.hpp>
4 #include <sdbusplus/async.hpp>
5 #include <sdbusplus/message/native_types.hpp>
6 #include <xyz/openbmc_project/Inventory/Item/client.hpp>
7
8 #include <algorithm>
9 #include <flat_map>
10 #include <utility>
11
12 namespace entity_manager
13 {
14
15 PHOSPHOR_LOG2_USING;
16
17 namespace rules_intf = sdbusplus::bus::match::rules;
18
19 using BasicVariantType =
20 std::variant<std::vector<std::string>, std::vector<uint8_t>, std::string,
21 int64_t, uint64_t, double, int32_t, uint32_t, int16_t,
22 uint16_t, uint8_t, bool>;
23 using BaseConfigMap = std::flat_map<std::string, BasicVariantType>;
24 using ConfigData = std::flat_map<std::string, BaseConfigMap>;
25 using ManagedObjectType =
26 std::flat_map<sdbusplus::message::object_path, ConfigData>;
27
EntityManagerInterface(sdbusplus::async::context & ctx,const interface_list_t & interfaceNames,Callback_t addedCallback,Callback_t removedCallback)28 EntityManagerInterface::EntityManagerInterface(
29 sdbusplus::async::context& ctx, const interface_list_t& interfaceNames,
30 Callback_t addedCallback, Callback_t removedCallback) :
31 ctx(ctx), interfaceNames(interfaceNames),
32 addedCallback(std::move(addedCallback)),
33 removedCallback(std::move(removedCallback))
34 {
35 ctx.spawn(handleInventoryAdded());
36 ctx.spawn(handleInventoryRemoved());
37 }
38
handleInventoryGet()39 auto EntityManagerInterface::handleInventoryGet() -> sdbusplus::async::task<>
40 {
41 if (!addedCallback)
42 {
43 error("addedCallback is not set");
44 co_return;
45 }
46
47 using InventoryIntf =
48 sdbusplus::client::xyz::openbmc_project::inventory::Item<>;
49
50 constexpr auto entityManager =
51 sdbusplus::async::proxy()
52 .service(serviceName)
53 .path(InventoryIntf::namespace_path)
54 .interface("org.freedesktop.DBus.ObjectManager");
55
56 for (const auto& [objectPath, interfaceConfig] :
57 co_await entityManager.call<ManagedObjectType>(ctx,
58 "GetManagedObjects"))
59 {
60 for (const auto& interfaceName : interfaceNames)
61 {
62 if (interfaceConfig.contains(interfaceName))
63 {
64 co_await addedCallback(objectPath, interfaceName);
65 }
66 }
67 }
68
69 co_return;
70 }
71
handleInventoryAdded()72 auto EntityManagerInterface::handleInventoryAdded() -> sdbusplus::async::task<>
73 {
74 if (!addedCallback)
75 {
76 error("addedCallback is not set");
77 co_return;
78 }
79
80 auto addedMatch = sdbusplus::async::match(
81 ctx, rules_intf::interfacesAdded() + rules_intf::sender(serviceName));
82
83 while (!ctx.stop_requested())
84 {
85 auto result = co_await addedMatch
86 .next<sdbusplus::message::object_path, ConfigData>();
87 auto& [objectPath, inventoryData] = result;
88
89 for (const auto& interfaceName : interfaceNames)
90 {
91 if (inventoryData.contains(interfaceName))
92 {
93 co_await addedCallback(objectPath, interfaceName);
94 }
95 }
96 }
97
98 co_return;
99 }
100
handleInventoryRemoved()101 auto EntityManagerInterface::handleInventoryRemoved()
102 -> sdbusplus::async::task<>
103 {
104 if (!removedCallback)
105 {
106 error("removedCallback is not set");
107 co_return;
108 }
109
110 auto removedMatch = sdbusplus::async::match(
111 ctx, rules_intf::interfacesRemoved() + rules_intf::sender(serviceName));
112
113 while (!ctx.stop_requested())
114 {
115 auto result =
116 co_await removedMatch
117 .next<sdbusplus::message::object_path, interface_list_t>();
118 auto& [objectPath, interfaces] = result;
119
120 for (const auto& interfaceName : interfaceNames)
121 {
122 if (std::ranges::find(interfaces, interfaceName) !=
123 interfaces.end())
124 {
125 co_await removedCallback(objectPath, interfaceName);
126 }
127 }
128 }
129
130 co_return;
131 }
132
133 } // namespace entity_manager
134