#pragma once #include #include #include #include #include #include #include "events.hpp" #include "functor.hpp" #include "types.hpp" namespace phosphor { namespace inventory { namespace manager { template using ServerObject = T; using ManagerIface = sdbusplus::xyz::openbmc_project::Inventory::server::Manager; /** @struct PropertiesVariant * @brief Wrapper for sdbusplus PropertiesVariant. * * A wrapper is useful since MakeInterface is instantiated with 'int' * to deduce the return type of its methods, which does not depend * on T. * * @tparam T - The sdbusplus server binding type. */ template struct PropertiesVariant {}; template struct PropertiesVariant::value>::type> { using Type = typename T::PropertiesVariant; }; template using PropertiesVariantType = typename PropertiesVariant::Type; /** @struct MakeInterface * @brief Adapt an sdbusplus interface proxy. * * Template instances are builder functions that create * adapted sdbusplus interface proxy interface objects. * * @tparam T - The type of the interface being adapted. */ template struct MakeInterface { static any_ns::any make( sdbusplus::bus::bus& bus, const char* path, const Interface& props) { using InterfaceVariant = std::map>; InterfaceVariant v; for (const auto& p : props) { v.emplace( p.first, convertVariant>(p.second)); } return any_ns::any(std::make_shared(bus, path, v)); } static void assign(const Interface& props, any_ns::any& holder) { auto& iface = *any_ns::any_cast &>(holder); for (const auto& p : props) { iface.setPropertyByName( p.first, convertVariant>(p.second)); } } }; /** @class Manager * @brief OpenBMC inventory manager implementation. * * A concrete implementation for the xyz.openbmc_project.Inventory.Manager * DBus API. */ class Manager final : public ServerObject { public: Manager() = delete; Manager(const Manager&) = delete; Manager& operator=(const Manager&) = delete; Manager(Manager&&) = default; Manager& operator=(Manager&&) = default; ~Manager() = default; /** @brief Construct an inventory manager. * * @param[in] bus - An sdbusplus bus connection. * @param[in] busname - The DBus busname to own. * @param[in] root - The DBus path on which to implement * an inventory manager. * @param[in] iface - The DBus inventory interface to implement. */ Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*); using EventInfo = std::tuple < std::vector, std::vector>; /** @brief Start processing DBus messages. */ void run() noexcept; /** @brief Provided for testing only. */ void shutdown() noexcept; /** @brief sd_bus Notify method implementation callback. */ void notify( std::map objs) override; /** @brief Event processing entry point. */ void handleEvent(sdbusplus::message::message&, const Event& event, const EventInfo& info); /** @brief Drop one or more objects from DBus. */ void destroyObjects( const std::vector& paths); /** @brief Add objects to DBus. */ void createObjects( const std::map& objs); /** @brief Add or update objects on DBus. */ void updateObjects( const std::map& objs); /** @brief Invoke an sdbusplus server binding method. * * Invoke the requested method with a reference to the requested * sdbusplus server binding interface as a parameter. * * @tparam T - The sdbusplus server binding interface type. * @tparam U - The type of the sdbusplus server binding member. * @tparam Args - Argument types of the binding member. * * @param[in] path - The DBus path on which the method should * be invoked. * @param[in] interface - The DBus interface hosting the method. * @param[in] member - Pointer to sdbusplus server binding member. * @param[in] args - Arguments to forward to the binding member. * * @returns - The return/value type of the binding method being * called. */ template decltype(auto) invokeMethod(const char* path, const char* interface, U&& member, Args&& ...args) { auto& iface = getInterface(path, interface); return (iface.*member)(std::forward(args)...); } using SigArgs = std::vector < std::unique_ptr < std::tuple < Manager*, const DbusSignal*, const EventInfo* >>>; using SigArg = SigArgs::value_type::element_type; private: using InterfaceComposite = std::map; using ObjectReferences = std::map; using Events = std::vector; // The int instantiations are safe since the signature of these // functions don't change from one instantiation to the next. using MakerType = std::add_pointer_t < decltype(MakeInterface::make) >; using AssignerType = std::add_pointer_t < decltype(MakeInterface::assign) >; using Makers = std::map>; /** @brief Provides weak references to interface holders. * * Common code for all types for the templated getInterface * methods. * * @param[in] path - The DBus path for which the interface * holder instance should be provided. * @param[in] interface - The DBus interface for which the * holder instance should be provided. * * @returns A weak reference to the holder instance. */ const any_ns::any& getInterfaceHolder( const char*, const char*) const; any_ns::any& getInterfaceHolder( const char*, const char*); /** @brief Provides weak references to interface holders. * * @tparam T - The sdbusplus server binding interface type. * * @param[in] path - The DBus path for which the interface * should be provided. * @param[in] interface - The DBus interface to obtain. * * @returns A weak reference to the interface holder. */ template auto& getInterface(const char* path, const char* interface) { auto& holder = getInterfaceHolder(path, interface); return *any_ns::any_cast &>(holder); } template auto& getInterface(const char* path, const char* interface) const { auto& holder = getInterfaceHolder(path, interface); return *any_ns::any_cast(holder); } /** @brief Add or update interfaces on DBus. */ void updateInterfaces( const sdbusplus::message::object_path& path, const Object& interfaces, ObjectReferences::iterator pos, bool emitSignals = true); /** @brief Provided for testing only. */ volatile bool _shutdown; /** @brief Path prefix applied to any relative paths. */ const char* _root; /** @brief A container of sdbusplus server interface references. */ ObjectReferences _refs; /** @brief A container contexts for signal callbacks. */ SigArgs _sigargs; /** @brief A container of sdbusplus signal matches. */ std::vector _matches; /** @brief Persistent sdbusplus DBus bus connection. */ sdbusplus::bus::bus _bus; /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */ sdbusplus::server::manager::manager _manager; /** @brief A container of pimgen generated events and responses. */ static const Events _events; /** @brief A container of pimgen generated factory methods. */ static const Makers _makers; }; } // namespace manager } // namespace inventory } // namespace phosphor // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4