1 #include "entity_manager_interface.hpp" 2 3 #include <boost/container/flat_map.hpp> 4 #include <phosphor-logging/lg2.hpp> 5 #include <sdbusplus/async.hpp> 6 #include <sdbusplus/message/native_types.hpp> 7 #include <xyz/openbmc_project/Inventory/Item/client.hpp> 8 9 #include <algorithm> 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 = boost::container::flat_map<std::string, BasicVariantType>; 24 using ConfigData = boost::container::flat_map<std::string, BaseConfigMap>; 25 using ManagedObjectType = 26 boost::container::flat_map<sdbusplus::message::object_path, ConfigData>; 27 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 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 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 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