1 #pragma once
2 
3 #include <map>
4 #include <memory>
5 #include <string>
6 #include <vector>
7 #include <sdbusplus/server.hpp>
8 #include "xyz/openbmc_project/Inventory/Manager/server.hpp"
9 #include "events.hpp"
10 #include "actions.hpp"
11 
12 namespace phosphor
13 {
14 namespace inventory
15 {
16 namespace manager
17 {
18 namespace details
19 {
20 
21 template <typename T>
22 using ServerObject = typename sdbusplus::server::object::object<T>;
23 
24 using ManagerIface =
25     sdbusplus::server::xyz::openbmc_project::Inventory::Manager;
26 
27 /** @struct MakeInterface
28  *  @brief Adapt an sdbusplus interface proxy.
29  *
30  *  Template instances are builder functions that create
31  *  adapted sdbusplus interface proxy interface objects.
32  *
33  *  @tparam T - The type of the interface being adapted.
34  */
35 template <typename T>
36 struct MakeInterface
37 {
38     static decltype(auto) make(sdbusplus::bus::bus &bus, const char *path)
39     {
40         using HolderType = holder::Holder<std::unique_ptr<T>>;
41         return static_cast<std::unique_ptr<holder::Base>>(
42             HolderType::template make_unique<HolderType>(
43                 std::forward<std::unique_ptr<T>>(
44                     std::make_unique<T>(
45                         std::forward<decltype(bus)>(bus),
46                         std::forward<decltype(path)>(path)))));
47     }
48 };
49 } // namespace details
50 
51 /** @class Manager
52  *  @brief OpenBMC inventory manager implementation.
53  *
54  *  A concrete implementation for the xyz.openbmc_project.Inventory.Manager
55  *  DBus API.
56  */
57 class Manager final :
58     public details::ServerObject<details::ManagerIface>
59 {
60     public:
61     Manager() = delete;
62     Manager(const Manager&) = delete;
63     Manager& operator=(const Manager&) = delete;
64     Manager(Manager&&) = default;
65     Manager& operator=(Manager&&) = default;
66     ~Manager() = default;
67 
68     /** @brief Construct an inventory manager.
69      *
70      *  @param[in] bus - An sdbusplus bus connection.
71      *  @param[in] busname - The DBus busname to own.
72      *  @param[in] root - The DBus path on which to implement
73      *      an inventory manager.
74      *  @param[in] iface - The DBus inventory interface to implement.
75      */
76     Manager(sdbusplus::bus::bus &&, const char *, const char*, const char*);
77 
78     using Object = std::map<
79         std::string, std::map<
80             std::string, sdbusplus::message::variant<std::string>>>;
81     using EventInfo = std::tuple<
82         std::vector<details::EventBasePtr>,
83         std::vector<details::ActionBasePtr>>;
84 
85     /** @brief Start processing DBus messages. */
86     void run() noexcept;
87 
88     /** @brief Provided for testing only. */
89     void shutdown() noexcept;
90 
91     /** @brief sd_bus Notify method implementation callback. */
92     void notify(std::string path, Object) override;
93 
94     /** @brief sd_bus signal callback. */
95     void signal(sdbusplus::message::message&,
96             const details::DbusSignal &event,
97             const EventInfo &info);
98 
99     /** @brief Drop an object from DBus. */
100     void destroyObject(const char *);
101 
102     using SigArgs = std::vector<
103         std::unique_ptr<
104             std::tuple<
105                 Manager *,
106                 const details::DbusSignal *,
107                 const EventInfo *>>>;
108     using SigArg = SigArgs::value_type::element_type;
109 
110     private:
111     using HolderPtr = std::unique_ptr<details::holder::Base>;
112     using InterfaceComposite = std::map<std::string, HolderPtr>;
113     using ObjectReferences = std::map<std::string, InterfaceComposite>;
114     using Events = std::vector<EventInfo>;
115     using MakerType = HolderPtr(*)(
116             sdbusplus::bus::bus &, const char *);
117     using Makers = std::map<std::string, MakerType>;
118 
119     /** @brief Provides weak references to interface holders.
120      *
121      *  Common code for all types for the templated getInterface
122      *  methods.
123      *
124      *  @param[in] path - The DBus path for which the interface
125      *      holder instance should be provided.
126      *  @param[in] interface - The DBus interface for which the
127      *      holder instance should be provided.
128      *
129      *  @returns A weak reference to the holder instance.
130      */
131     details::holder::Base& getInterfaceHolder(
132             const char *, const char *) const;
133     details::holder::Base& getInterfaceHolder(
134             const char *, const char *);
135 
136     /** @brief Provides weak references to interface holders.
137      *
138      *  @tparam T - The sdbusplus server binding interface type.
139      *
140      *  @param[in] path - The DBus path for which the interface
141      *      should be provided.
142      *  @param[in] interface - The DBus interface to obtain.
143      *
144      *  @returns A weak reference to the interface holder.
145      */
146     template<typename T>
147     auto& getInterface(const char *path, const char *interface)
148     {
149         auto &holder = getInterfaceHolder(path, interface);
150         return static_cast<
151             details::holder::Holder<T> &>(holder);
152     }
153     template<typename T>
154     auto& getInterface(const char *path, const char *interface) const
155     {
156         auto &holder = getInterfaceHolder(path, interface);
157         return static_cast<
158             const details::holder::Holder<T> &>(holder);
159     }
160 
161     /** @brief Provided for testing only. */
162     bool _shutdown;
163 
164     /** @brief Path prefix applied to any relative paths. */
165     const char * _root;
166 
167     /** @brief A container of sdbusplus server interface references. */
168     ObjectReferences _refs;
169 
170     /** @brief A container contexts for signal callbacks. */
171     SigArgs _sigargs;
172 
173     /** @brief A container of sdbusplus signal matches.  */
174     std::vector<sdbusplus::server::match::match> _matches;
175 
176     /** @brief Persistent sdbusplus DBus bus connection. */
177     sdbusplus::bus::bus _bus;
178 
179     /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
180     sdbusplus::server::manager::manager _manager;
181 
182     /** @brief A container of pimgen generated events and responses.  */
183     static const Events _events;
184 
185     /** @brief A container of pimgen generated factory methods.  */
186     static const Makers _makers;
187 };
188 
189 } // namespace manager
190 } // namespace inventory
191 } // namespace phosphor
192 
193 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
194