1 #pragma once
2 
3 #include "events.hpp"
4 #include "functor.hpp"
5 #include "interface_ops.hpp"
6 #include "serialize.hpp"
7 #include "types.hpp"
8 #ifdef CREATE_ASSOCIATIONS
9 #include "association_manager.hpp"
10 #endif
11 
12 #include <sdbusplus/server.hpp>
13 #include <xyz/openbmc_project/Inventory/Manager/server.hpp>
14 
15 #include <any>
16 #include <map>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 namespace sdbusplus
22 {
23 namespace bus
24 {
25 class bus;
26 }
27 } // namespace sdbusplus
28 namespace phosphor
29 {
30 namespace inventory
31 {
32 namespace manager
33 {
34 
35 template <typename T>
36 using ServerObject = T;
37 
38 using ManagerIface =
39     sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
40 
41 /** @class Manager
42  *  @brief OpenBMC inventory manager implementation.
43  *
44  *  A concrete implementation for the xyz.openbmc_project.Inventory.Manager
45  *  DBus API.
46  */
47 class Manager final : public ServerObject<ManagerIface>
48 {
49   public:
50     Manager() = delete;
51     Manager(const Manager&) = delete;
52     Manager& operator=(const Manager&) = delete;
53     Manager(Manager&&) = default;
54     Manager& operator=(Manager&&) = default;
55     ~Manager() = default;
56 
57     /** @brief Construct an inventory manager.
58      *
59      *  @param[in] bus - An sdbusplus bus connection.
60      *  @param[in] busname - The DBus busname to own.
61      *  @param[in] root - The DBus path on which to implement
62      *      an inventory manager.
63      */
64     Manager(sdbusplus::bus::bus&&, const char*, const char*);
65 
66     using EventInfo =
67         std::tuple<std::vector<EventBasePtr>, std::vector<Action>>;
68 
69     /** @brief Start processing DBus messages. */
70     void run() noexcept;
71 
72     /** @brief Provided for testing only. */
73     void shutdown() noexcept;
74 
75     /** @brief sd_bus Notify method implementation callback. */
76     void
77         notify(std::map<sdbusplus::message::object_path, Object> objs) override;
78 
79     /** @brief Event processing entry point. */
80     void handleEvent(sdbusplus::message::message&, const Event& event,
81                      const EventInfo& info);
82 
83     /** @brief Drop one or more objects from DBus. */
84     void destroyObjects(const std::vector<const char*>& paths);
85 
86     /** @brief Add objects to DBus. */
87     void createObjects(
88         const std::map<sdbusplus::message::object_path, Object>& objs);
89 
90     /** @brief Add or update objects on DBus. */
91     void updateObjects(
92         const std::map<sdbusplus::message::object_path, Object>& objs,
93         bool restoreFromCache = false);
94 
95     /** @brief Restore persistent inventory items */
96     void restore();
97 
98     /** @brief Invoke an sdbusplus server binding method.
99      *
100      *  Invoke the requested method with a reference to the requested
101      *  sdbusplus server binding interface as a parameter.
102      *
103      *  @tparam T - The sdbusplus server binding interface type.
104      *  @tparam U - The type of the sdbusplus server binding member.
105      *  @tparam Args - Argument types of the binding member.
106      *
107      *  @param[in] path - The DBus path on which the method should
108      *      be invoked.
109      *  @param[in] interface - The DBus interface hosting the method.
110      *  @param[in] member - Pointer to sdbusplus server binding member.
111      *  @param[in] args - Arguments to forward to the binding member.
112      *
113      *  @returns - The return/value type of the binding method being
114      *      called.
115      */
116     template <typename T, typename U, typename... Args>
117     decltype(auto) invokeMethod(const char* path, const char* interface,
118                                 U&& member, Args&&... args)
119     {
120         auto& iface = getInterface<T>(path, interface);
121         return (iface.*member)(std::forward<Args>(args)...);
122     }
123 
124     using SigArgs = std::vector<std::unique_ptr<
125         std::tuple<Manager*, const DbusSignal*, const EventInfo*>>>;
126     using SigArg = SigArgs::value_type::element_type;
127 
128   private:
129     using InterfaceComposite = std::map<std::string, std::any>;
130     using ObjectReferences = std::map<std::string, InterfaceComposite>;
131     using Events = std::vector<EventInfo>;
132 
133     // The int instantiations are safe since the signature of these
134     // functions don't change from one instantiation to the next.
135     using Makers =
136         std::map<std::string, std::tuple<MakeInterfaceType, AssignInterfaceType,
137                                          SerializeInterfaceType<SerialOps>,
138                                          DeserializeInterfaceType<SerialOps>>>;
139 
140     /** @brief Provides weak references to interface holders.
141      *
142      *  Common code for all types for the templated getInterface
143      *  methods.
144      *
145      *  @param[in] path - The DBus path for which the interface
146      *      holder instance should be provided.
147      *  @param[in] interface - The DBus interface for which the
148      *      holder instance should be provided.
149      *
150      *  @returns A weak reference to the holder instance.
151      */
152     const std::any& getInterfaceHolder(const char*, const char*) const;
153     std::any& getInterfaceHolder(const char*, const char*);
154 
155     /** @brief Provides weak references to interface holders.
156      *
157      *  @tparam T - The sdbusplus server binding interface type.
158      *
159      *  @param[in] path - The DBus path for which the interface
160      *      should be provided.
161      *  @param[in] interface - The DBus interface to obtain.
162      *
163      *  @returns A weak reference to the interface holder.
164      */
165     template <typename T>
166     auto& getInterface(const char* path, const char* interface)
167     {
168         auto& holder = getInterfaceHolder(path, interface);
169         return *std::any_cast<std::shared_ptr<T>&>(holder);
170     }
171     template <typename T>
172     auto& getInterface(const char* path, const char* interface) const
173     {
174         auto& holder = getInterfaceHolder(path, interface);
175         return *std::any_cast<T>(holder);
176     }
177 
178     /** @brief Add or update interfaces on DBus. */
179     void updateInterfaces(const sdbusplus::message::object_path& path,
180                           const Object& interfaces,
181                           ObjectReferences::iterator pos, bool emitSignals,
182                           bool restoreFromCache);
183 
184     /** @brief Provided for testing only. */
185     volatile bool _shutdown;
186 
187     /** @brief Path prefix applied to any relative paths. */
188     const char* _root;
189 
190     /** @brief A container of sdbusplus server interface references. */
191     ObjectReferences _refs;
192 
193     /** @brief A container contexts for signal callbacks. */
194     SigArgs _sigargs;
195 
196     /** @brief A container of sdbusplus signal matches.  */
197     std::vector<sdbusplus::bus::match_t> _matches;
198 
199     /** @brief Persistent sdbusplus DBus bus connection. */
200     sdbusplus::bus::bus _bus;
201 
202     /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
203     sdbusplus::server::manager::manager _manager;
204 
205     /** @brief A container of pimgen generated events and responses.  */
206     static const Events _events;
207 
208     /** @brief A container of pimgen generated factory methods.  */
209     static const Makers _makers;
210 
211     /** @brief Handles creating mapper associations for inventory objects */
212 #ifdef CREATE_ASSOCIATIONS
213     associations::Manager _associations;
214 #endif
215 };
216 
217 } // namespace manager
218 } // namespace inventory
219 } // namespace phosphor
220 
221 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
222