blob: 624eb600e07717337d87b5809e4c710bb7460f48 [file] [log] [blame]
Brad Bishop49aefb32016-10-19 11:54:14 -04001#pragma once
2
3#include <map>
4#include <memory>
5#include <string>
6#include <vector>
7#include <sdbusplus/server.hpp>
Brad Bishop03f4cd92017-02-03 15:17:21 -05008#include <xyz/openbmc_project/Inventory/Manager/server.hpp>
Brad Bishop67b788d2016-11-29 13:09:01 -05009#include "events.hpp"
Brad Bishopc1f47982017-02-09 01:27:38 -050010#include "functor.hpp"
Brad Bishop1157af12017-01-22 01:03:02 -050011#include "types.hpp"
Deepak Kodihalli6620e982017-08-05 13:09:54 -050012#include "serialize.hpp"
Brad Bishop49aefb32016-10-19 11:54:14 -040013
14namespace phosphor
15{
16namespace inventory
17{
18namespace manager
19{
Brad Bishop451f8d92016-11-21 14:15:19 -050020
21template <typename T>
Brad Bishopa5cc34c2017-02-03 20:57:36 -050022using ServerObject = T;
Brad Bishop451f8d92016-11-21 14:15:19 -050023
24using ManagerIface =
Brad Bishop9aa5e2f2017-01-15 19:45:40 -050025 sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
Brad Bishop451f8d92016-11-21 14:15:19 -050026
Brad Bishop79ccaf72017-01-22 16:00:50 -050027/** @struct PropertiesVariant
28 * @brief Wrapper for sdbusplus PropertiesVariant.
29 *
30 * A wrapper is useful since MakeInterface is instantiated with 'int'
31 * to deduce the return type of its methods, which does not depend
32 * on T.
33 *
34 * @tparam T - The sdbusplus server binding type.
35 */
36template <typename T, typename Enable = void>
37struct PropertiesVariant {};
38
39template <typename T>
40struct PropertiesVariant<T, typename std::enable_if<std::is_object<T>::value>::type>
41{
42 using Type = typename T::PropertiesVariant;
43};
44
45template <typename T>
46using PropertiesVariantType = typename PropertiesVariant<T>::Type;
47
Marri Devender Raofa23d702017-09-02 04:43:42 -050048template <typename T, typename U = int>
49struct HasProperties : std::false_type
50{
51};
52
53template <typename T>
54struct HasProperties <T,
55 decltype((void) std::declval<typename T::PropertiesVariant>(), 0)> :
56 std::true_type
57{
58};
59
60template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
61any_ns::any propMake(
62 sdbusplus::bus::bus& bus, const char* path, const Interface& props)
63{
64 using InterfaceVariant =
65 std::map<std::string, PropertiesVariantType<T>>;
66
67 InterfaceVariant v;
68 for (const auto& p : props)
69 {
70 v.emplace(
71 p.first,
72 convertVariant<PropertiesVariantType<T>>(p.second));
73 }
74
75 return any_ns::any(std::make_shared<T>(bus, path, v));
76}
77
78template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
79any_ns::any propMake(
80 sdbusplus::bus::bus& bus, const char* path, const Interface& props)
81{
82 return any_ns::any(std::make_shared<T>(bus, path));
83}
84
85template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
86void propAssign(const Interface& props, any_ns::any& holder)
87{
88 auto& iface = *any_ns::any_cast<std::shared_ptr<T> &>(holder);
89 for (const auto& p : props)
90 {
91 iface.setPropertyByName(
92 p.first, convertVariant<PropertiesVariantType<T>>(p.second));
93 }
94}
95
96template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
97void propAssign(const Interface& props, any_ns::any& holder)
98{
99}
100
101template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
102void propSerialize(
103 const std::string& path, const std::string& iface,
104 const any_ns::any& holder)
105{
106 const auto& object =
107 *any_ns::any_cast<const std::shared_ptr<T> &>(holder);
108 cereal::serialize(path, iface, object);
109}
110
111template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
112void propSerialize(
113 const std::string& path, const std::string& iface,
114 const any_ns::any& holder)
115{
116 cereal::serialize(path, iface);
117}
118
119template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
120void propDeSerialize(
121 const std::string& path, const std::string& iface, any_ns::any& holder)
122{
123 auto& object = *any_ns::any_cast<std::shared_ptr<T> &>(holder);
124 cereal::deserialize(path, iface, object);
125}
126
127template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
128void propDeSerialize(
129 const std::string& path, const std::string& iface, any_ns::any& holder)
130{
131}
132
133
Brad Bishop65ffffa2016-11-29 12:31:31 -0500134/** @struct MakeInterface
135 * @brief Adapt an sdbusplus interface proxy.
136 *
137 * Template instances are builder functions that create
138 * adapted sdbusplus interface proxy interface objects.
139 *
140 * @tparam T - The type of the interface being adapted.
141 */
Brad Bishop79ccaf72017-01-22 16:00:50 -0500142
Brad Bishop65ffffa2016-11-29 12:31:31 -0500143template <typename T>
144struct MakeInterface
145{
Brad Bishop150147a2017-02-08 23:57:46 -0500146 static any_ns::any make(
Marri Devender Raofa23d702017-09-02 04:43:42 -0500147 sdbusplus::bus::bus& bus, const char* path, const Interface& props)
Brad Bishop65ffffa2016-11-29 12:31:31 -0500148 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500149 return propMake<T>(bus, path, props);
Brad Bishop65ffffa2016-11-29 12:31:31 -0500150 }
Brad Bishop79ccaf72017-01-22 16:00:50 -0500151
152 static void assign(const Interface& props, any_ns::any& holder)
153 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500154 propAssign<T>(props, holder);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500155 }
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500156
Marri Devender Raofa23d702017-09-02 04:43:42 -0500157 static void serialize(
158 const std::string& path, const std::string& iface,
159 const any_ns::any& holder)
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500160 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500161 propSerialize<T>(path, iface, holder);
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500162 }
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500163
Marri Devender Raofa23d702017-09-02 04:43:42 -0500164 static void deserialize(
165 const std::string& path, const std::string& iface, any_ns::any& holder)
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500166 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500167 propDeSerialize<T>(path, iface, holder);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500168 }
Marri Devender Raofa23d702017-09-02 04:43:42 -0500169
Brad Bishop65ffffa2016-11-29 12:31:31 -0500170};
Brad Bishop49aefb32016-10-19 11:54:14 -0400171
172/** @class Manager
173 * @brief OpenBMC inventory manager implementation.
174 *
175 * A concrete implementation for the xyz.openbmc_project.Inventory.Manager
176 * DBus API.
177 */
178class Manager final :
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500179 public ServerObject<ManagerIface>
Brad Bishop49aefb32016-10-19 11:54:14 -0400180{
181 public:
Brad Bishop7b337772017-01-12 16:11:24 -0500182 Manager() = delete;
183 Manager(const Manager&) = delete;
184 Manager& operator=(const Manager&) = delete;
185 Manager(Manager&&) = default;
186 Manager& operator=(Manager&&) = default;
187 ~Manager() = default;
Brad Bishop49aefb32016-10-19 11:54:14 -0400188
Brad Bishop7b337772017-01-12 16:11:24 -0500189 /** @brief Construct an inventory manager.
190 *
191 * @param[in] bus - An sdbusplus bus connection.
192 * @param[in] busname - The DBus busname to own.
193 * @param[in] root - The DBus path on which to implement
194 * an inventory manager.
195 * @param[in] iface - The DBus inventory interface to implement.
196 */
197 Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*);
Brad Bishop49aefb32016-10-19 11:54:14 -0400198
Brad Bishop7b337772017-01-12 16:11:24 -0500199 using EventInfo = std::tuple <
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500200 std::vector<EventBasePtr>,
201 std::vector<Action >>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400202
Brad Bishop7b337772017-01-12 16:11:24 -0500203 /** @brief Start processing DBus messages. */
204 void run() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400205
Brad Bishop7b337772017-01-12 16:11:24 -0500206 /** @brief Provided for testing only. */
207 void shutdown() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400208
Brad Bishop7b337772017-01-12 16:11:24 -0500209 /** @brief sd_bus Notify method implementation callback. */
Brad Bishop03f4cd92017-02-03 15:17:21 -0500210 void notify(
211 std::map<sdbusplus::message::object_path, Object> objs) override;
Brad Bishop49aefb32016-10-19 11:54:14 -0400212
Brad Bishop48547a82017-01-19 15:12:50 -0500213 /** @brief Event processing entry point. */
214 void handleEvent(sdbusplus::message::message&,
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500215 const Event& event,
Brad Bishop48547a82017-01-19 15:12:50 -0500216 const EventInfo& info);
Brad Bishop49aefb32016-10-19 11:54:14 -0400217
Brad Bishop7b7e7122017-01-21 21:21:46 -0500218 /** @brief Drop one or more objects from DBus. */
219 void destroyObjects(
220 const std::vector<const char*>& paths);
Brad Bishop656a7d02016-10-19 22:20:02 -0400221
Brad Bishopeb68a682017-01-22 00:58:54 -0500222 /** @brief Add objects to DBus. */
223 void createObjects(
224 const std::map<sdbusplus::message::object_path, Object>& objs);
225
Brad Bishop79ccaf72017-01-22 16:00:50 -0500226 /** @brief Add or update objects on DBus. */
227 void updateObjects(
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500228 const std::map<sdbusplus::message::object_path, Object>& objs,
229 bool restoreFromCache = false);
230
231 /** @brief Restore persistent inventory items */
232 void restore();
Brad Bishop79ccaf72017-01-22 16:00:50 -0500233
Brad Bishop7b337772017-01-12 16:11:24 -0500234 /** @brief Invoke an sdbusplus server binding method.
235 *
236 * Invoke the requested method with a reference to the requested
237 * sdbusplus server binding interface as a parameter.
238 *
239 * @tparam T - The sdbusplus server binding interface type.
240 * @tparam U - The type of the sdbusplus server binding member.
241 * @tparam Args - Argument types of the binding member.
242 *
243 * @param[in] path - The DBus path on which the method should
244 * be invoked.
245 * @param[in] interface - The DBus interface hosting the method.
246 * @param[in] member - Pointer to sdbusplus server binding member.
247 * @param[in] args - Arguments to forward to the binding member.
248 *
249 * @returns - The return/value type of the binding method being
250 * called.
251 */
252 template<typename T, typename U, typename ...Args>
253 decltype(auto) invokeMethod(const char* path, const char* interface,
254 U&& member, Args&& ...args)
255 {
Brad Bishop150147a2017-02-08 23:57:46 -0500256 auto& iface = getInterface<T>(path, interface);
Brad Bishop7b337772017-01-12 16:11:24 -0500257 return (iface.*member)(std::forward<Args>(args)...);
258 }
Brad Bishopda649b12016-11-30 14:35:02 -0500259
Brad Bishop7b337772017-01-12 16:11:24 -0500260 using SigArgs = std::vector <
261 std::unique_ptr <
262 std::tuple <
263 Manager*,
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500264 const DbusSignal*,
Brad Bishop7b337772017-01-12 16:11:24 -0500265 const EventInfo* >>>;
266 using SigArg = SigArgs::value_type::element_type;
Brad Bishop49aefb32016-10-19 11:54:14 -0400267
268 private:
Brad Bishop150147a2017-02-08 23:57:46 -0500269 using InterfaceComposite = std::map<std::string, any_ns::any>;
Brad Bishop7b337772017-01-12 16:11:24 -0500270 using ObjectReferences = std::map<std::string, InterfaceComposite>;
271 using Events = std::vector<EventInfo>;
Brad Bishop90c30bc2017-01-22 16:40:47 -0500272
Brad Bishop79ccaf72017-01-22 16:00:50 -0500273 // The int instantiations are safe since the signature of these
Brad Bishop90c30bc2017-01-22 16:40:47 -0500274 // functions don't change from one instantiation to the next.
275 using MakerType = std::add_pointer_t <
Brad Bishop12f8a3c2017-02-09 00:02:00 -0500276 decltype(MakeInterface<int>::make) >;
Brad Bishop79ccaf72017-01-22 16:00:50 -0500277 using AssignerType = std::add_pointer_t <
278 decltype(MakeInterface<int>::assign) >;
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500279 using SerializerType = std::add_pointer_t <
280 decltype(MakeInterface<int>::serialize) >;
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500281 using DeserializerType = std::add_pointer_t <
282 decltype(MakeInterface<int>::deserialize) >;
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500283 using Makers = std::map<std::string,
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500284 std::tuple<MakerType, AssignerType,
285 SerializerType, DeserializerType>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400286
Brad Bishop7b337772017-01-12 16:11:24 -0500287 /** @brief Provides weak references to interface holders.
288 *
289 * Common code for all types for the templated getInterface
290 * methods.
291 *
292 * @param[in] path - The DBus path for which the interface
293 * holder instance should be provided.
294 * @param[in] interface - The DBus interface for which the
295 * holder instance should be provided.
296 *
297 * @returns A weak reference to the holder instance.
298 */
Brad Bishop150147a2017-02-08 23:57:46 -0500299 const any_ns::any& getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500300 const char*, const char*) const;
Brad Bishop150147a2017-02-08 23:57:46 -0500301 any_ns::any& getInterfaceHolder(
Brad Bishop7b337772017-01-12 16:11:24 -0500302 const char*, const char*);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500303
Brad Bishop7b337772017-01-12 16:11:24 -0500304 /** @brief Provides weak references to interface holders.
305 *
306 * @tparam T - The sdbusplus server binding interface type.
307 *
308 * @param[in] path - The DBus path for which the interface
309 * should be provided.
310 * @param[in] interface - The DBus interface to obtain.
311 *
312 * @returns A weak reference to the interface holder.
313 */
314 template<typename T>
315 auto& getInterface(const char* path, const char* interface)
316 {
317 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop150147a2017-02-08 23:57:46 -0500318 return *any_ns::any_cast<std::shared_ptr<T> &>(holder);
Brad Bishop7b337772017-01-12 16:11:24 -0500319 }
320 template<typename T>
321 auto& getInterface(const char* path, const char* interface) const
322 {
323 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop150147a2017-02-08 23:57:46 -0500324 return *any_ns::any_cast<T>(holder);
Brad Bishop7b337772017-01-12 16:11:24 -0500325 }
Brad Bishopb83a21e2016-11-30 13:43:37 -0500326
Brad Bishop79ccaf72017-01-22 16:00:50 -0500327 /** @brief Add or update interfaces on DBus. */
328 void updateInterfaces(
329 const sdbusplus::message::object_path& path,
330 const Object& interfaces,
331 ObjectReferences::iterator pos,
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500332 bool emitSignals = true,
333 bool restoreFromCache = false);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500334
Brad Bishop7b337772017-01-12 16:11:24 -0500335 /** @brief Provided for testing only. */
Brad Bishopb9b929b2017-01-13 16:33:06 -0500336 volatile bool _shutdown;
Brad Bishop49aefb32016-10-19 11:54:14 -0400337
Brad Bishop7b337772017-01-12 16:11:24 -0500338 /** @brief Path prefix applied to any relative paths. */
339 const char* _root;
Brad Bishop49aefb32016-10-19 11:54:14 -0400340
Brad Bishop7b337772017-01-12 16:11:24 -0500341 /** @brief A container of sdbusplus server interface references. */
342 ObjectReferences _refs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400343
Brad Bishop7b337772017-01-12 16:11:24 -0500344 /** @brief A container contexts for signal callbacks. */
345 SigArgs _sigargs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400346
Brad Bishop7b337772017-01-12 16:11:24 -0500347 /** @brief A container of sdbusplus signal matches. */
Patrick Williams133ca132017-05-01 22:12:34 -0500348 std::vector<sdbusplus::bus::match_t> _matches;
Brad Bishop49aefb32016-10-19 11:54:14 -0400349
Brad Bishop7b337772017-01-12 16:11:24 -0500350 /** @brief Persistent sdbusplus DBus bus connection. */
351 sdbusplus::bus::bus _bus;
Brad Bishop49aefb32016-10-19 11:54:14 -0400352
Brad Bishop7b337772017-01-12 16:11:24 -0500353 /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
354 sdbusplus::server::manager::manager _manager;
Brad Bishop49aefb32016-10-19 11:54:14 -0400355
Brad Bishop7b337772017-01-12 16:11:24 -0500356 /** @brief A container of pimgen generated events and responses. */
357 static const Events _events;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500358
Brad Bishop7b337772017-01-12 16:11:24 -0500359 /** @brief A container of pimgen generated factory methods. */
360 static const Makers _makers;
Brad Bishop49aefb32016-10-19 11:54:14 -0400361};
362
363} // namespace manager
364} // namespace inventory
365} // namespace phosphor
366
367// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4