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