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