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 <any>
13 #include <map>
14 #include <memory>
15 #include <sdbusplus/server.hpp>
16 #include <string>
17 #include <vector>
18 #include <xyz/openbmc_project/Inventory/Manager/server.hpp>
19 
20 namespace sdbusplus
21 {
22 namespace bus
23 {
24 class bus;
25 }
26 } // namespace sdbusplus
27 namespace phosphor
28 {
29 namespace inventory
30 {
31 namespace manager
32 {
33 
34 template <typename T>
35 using ServerObject = T;
36 
37 using ManagerIface =
38     sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
39 
40 /** @class Manager
41  *  @brief OpenBMC inventory manager implementation.
42  *
43  *  A concrete implementation for the xyz.openbmc_project.Inventory.Manager
44  *  DBus API.
45  */
46 class Manager final : public ServerObject<ManagerIface>
47 {
48   public:
49     Manager() = delete;
50     Manager(const Manager&) = delete;
51     Manager& operator=(const Manager&) = delete;
52     Manager(Manager&&) = default;
53     Manager& operator=(Manager&&) = default;
54     ~Manager() = default;
55 
56     /** @brief Construct an inventory manager.
57      *
58      *  @param[in] bus - An sdbusplus bus connection.
59      *  @param[in] busname - The DBus busname to own.
60      *  @param[in] root - The DBus path on which to implement
61      *      an inventory manager.
62      *  @param[in] iface - The DBus inventory interface to implement.
63      */
64     Manager(sdbusplus::bus::bus&&, const char*, 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,
182                           bool emitSignals = true,
183                           bool restoreFromCache = false);
184 
185     /** @brief Provided for testing only. */
186     volatile bool _shutdown;
187 
188     /** @brief Path prefix applied to any relative paths. */
189     const char* _root;
190 
191     /** @brief A container of sdbusplus server interface references. */
192     ObjectReferences _refs;
193 
194     /** @brief A container contexts for signal callbacks. */
195     SigArgs _sigargs;
196 
197     /** @brief A container of sdbusplus signal matches.  */
198     std::vector<sdbusplus::bus::match_t> _matches;
199 
200     /** @brief Persistent sdbusplus DBus bus connection. */
201     sdbusplus::bus::bus _bus;
202 
203     /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
204     sdbusplus::server::manager::manager _manager;
205 
206     /** @brief A container of pimgen generated events and responses.  */
207     static const Events _events;
208 
209     /** @brief A container of pimgen generated factory methods.  */
210     static const Makers _makers;
211 
212     /** @brief Handles creating mapper associations for inventory objects */
213 #ifdef CREATE_ASSOCIATIONS
214     associations::Manager _associations;
215 #endif
216 };
217 
218 } // namespace manager
219 } // namespace inventory
220 } // namespace phosphor
221 
222 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
223