blob: 93957d97f0676efbbf4308a5de4e2753bbf5ae16 [file] [log] [blame]
Brad Bishop49aefb32016-10-19 11:54:14 -04001#pragma once
2
Brad Bishop67b788d2016-11-29 13:09:01 -05003#include "events.hpp"
Brad Bishopc1f47982017-02-09 01:27:38 -05004#include "functor.hpp"
Deepak Kodihalli6620e982017-08-05 13:09:54 -05005#include "serialize.hpp"
Patrick Venturea680d1e2018-10-14 13:34:26 -07006#include "types.hpp"
7
Brad Bishop25d54b52018-11-21 12:57:51 -05008#include <any>
Patrick Venturea680d1e2018-10-14 13:34:26 -07009#include <map>
10#include <memory>
11#include <sdbusplus/server.hpp>
12#include <string>
13#include <vector>
14#include <xyz/openbmc_project/Inventory/Manager/server.hpp>
Brad Bishop49aefb32016-10-19 11:54:14 -040015
16namespace phosphor
17{
18namespace inventory
19{
20namespace manager
21{
Brad Bishop451f8d92016-11-21 14:15:19 -050022
Patrick Venturea680d1e2018-10-14 13:34:26 -070023template <typename T>
24using ServerObject = T;
Brad Bishop451f8d92016-11-21 14:15:19 -050025
26using ManagerIface =
Brad Bishop9aa5e2f2017-01-15 19:45:40 -050027 sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
Brad Bishop451f8d92016-11-21 14:15:19 -050028
Brad Bishop79ccaf72017-01-22 16:00:50 -050029/** @struct PropertiesVariant
30 * @brief Wrapper for sdbusplus PropertiesVariant.
31 *
32 * A wrapper is useful since MakeInterface is instantiated with 'int'
33 * to deduce the return type of its methods, which does not depend
34 * on T.
35 *
36 * @tparam T - The sdbusplus server binding type.
37 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070038template <typename T, typename Enable = void>
39struct PropertiesVariant
Brad Bishop615b2a82018-03-29 10:32:41 -040040{
41};
Brad Bishop79ccaf72017-01-22 16:00:50 -050042
43template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040044struct PropertiesVariant<
45 T, typename std::enable_if<std::is_object<T>::value>::type>
Brad Bishop79ccaf72017-01-22 16:00:50 -050046{
47 using Type = typename T::PropertiesVariant;
48};
49
50template <typename T>
51using PropertiesVariantType = typename PropertiesVariant<T>::Type;
52
Patrick Venturea680d1e2018-10-14 13:34:26 -070053template <typename T, typename U = int>
54struct HasProperties : std::false_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050055{
56};
57
58template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040059struct HasProperties<
60 T, decltype((void)std::declval<typename T::PropertiesVariant>(), 0)>
61 : std::true_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050062{
63};
64
65template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop25d54b52018-11-21 12:57:51 -050066std::any propMake(sdbusplus::bus::bus& bus, const char* path,
67 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050068{
Brad Bishop615b2a82018-03-29 10:32:41 -040069 using InterfaceVariant = std::map<std::string, PropertiesVariantType<T>>;
Marri Devender Raofa23d702017-09-02 04:43:42 -050070
71 InterfaceVariant v;
72 for (const auto& p : props)
73 {
Brad Bishop615b2a82018-03-29 10:32:41 -040074 v.emplace(p.first, convertVariant<PropertiesVariantType<T>>(p.second));
Marri Devender Raofa23d702017-09-02 04:43:42 -050075 }
76
Brad Bishop25d54b52018-11-21 12:57:51 -050077 return std::any(std::make_shared<T>(bus, path, v));
Marri Devender Raofa23d702017-09-02 04:43:42 -050078}
79
80template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop25d54b52018-11-21 12:57:51 -050081std::any propMake(sdbusplus::bus::bus& bus, const char* path,
82 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050083{
Brad Bishop25d54b52018-11-21 12:57:51 -050084 return std::any(std::make_shared<T>(bus, path));
Marri Devender Raofa23d702017-09-02 04:43:42 -050085}
86
87template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop25d54b52018-11-21 12:57:51 -050088void propAssign(const Interface& props, std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -050089{
Brad Bishop25d54b52018-11-21 12:57:51 -050090 auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -050091 for (const auto& p : props)
92 {
93 iface.setPropertyByName(
94 p.first, convertVariant<PropertiesVariantType<T>>(p.second));
95 }
96}
97
98template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop25d54b52018-11-21 12:57:51 -050099void propAssign(const Interface& props, std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500100{
101}
102
103template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -0400104void propSerialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500105 const std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500106{
Brad Bishop25d54b52018-11-21 12:57:51 -0500107 const auto& object = *std::any_cast<const std::shared_ptr<T>&>(holder);
Brad Bishop7dfd08f2018-12-12 21:40:26 -0500108 SerialOps::serialize(path, iface, object);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500109}
110
111template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400112void propSerialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500113 const std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500114{
Brad Bishop7dfd08f2018-12-12 21:40:26 -0500115 SerialOps::serialize(path, iface);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500116}
117
118template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -0400119void propDeSerialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500120 std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500121{
Brad Bishop25d54b52018-11-21 12:57:51 -0500122 auto& object = *std::any_cast<std::shared_ptr<T>&>(holder);
Brad Bishop7dfd08f2018-12-12 21:40:26 -0500123 SerialOps::deserialize(path, iface, object);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500124}
125
126template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400127void propDeSerialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500128 std::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500129{
Brad Bishop7dfd08f2018-12-12 21:40:26 -0500130 SerialOps::deserialize(path, iface);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500131}
132
Brad Bishop65ffffa2016-11-29 12:31:31 -0500133/** @struct MakeInterface
134 * @brief Adapt an sdbusplus interface proxy.
135 *
136 * Template instances are builder functions that create
137 * adapted sdbusplus interface proxy interface objects.
138 *
139 * @tparam T - The type of the interface being adapted.
140 */
Brad Bishop79ccaf72017-01-22 16:00:50 -0500141
Patrick Venturea680d1e2018-10-14 13:34:26 -0700142template <typename T>
143struct MakeInterface
Brad Bishop65ffffa2016-11-29 12:31:31 -0500144{
Brad Bishop25d54b52018-11-21 12:57:51 -0500145 static std::any make(sdbusplus::bus::bus& bus, const char* path,
146 const Interface& props)
Brad Bishop65ffffa2016-11-29 12:31:31 -0500147 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500148 return propMake<T>(bus, path, props);
Brad Bishop65ffffa2016-11-29 12:31:31 -0500149 }
Brad Bishop79ccaf72017-01-22 16:00:50 -0500150
Brad Bishop25d54b52018-11-21 12:57:51 -0500151 static void assign(const Interface& props, std::any& holder)
Brad Bishop79ccaf72017-01-22 16:00:50 -0500152 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500153 propAssign<T>(props, holder);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500154 }
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500155
Brad Bishop615b2a82018-03-29 10:32:41 -0400156 static void serialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500157 const std::any& holder)
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500158 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500159 propSerialize<T>(path, iface, holder);
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500160 }
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500161
Brad Bishop615b2a82018-03-29 10:32:41 -0400162 static void deserialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500163 std::any& holder)
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500164 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500165 propDeSerialize<T>(path, iface, holder);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500166 }
Brad Bishop65ffffa2016-11-29 12:31:31 -0500167};
Brad Bishop49aefb32016-10-19 11:54:14 -0400168
169/** @class Manager
170 * @brief OpenBMC inventory manager implementation.
171 *
172 * A concrete implementation for the xyz.openbmc_project.Inventory.Manager
173 * DBus API.
174 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400175class Manager final : public ServerObject<ManagerIface>
Brad Bishop49aefb32016-10-19 11:54:14 -0400176{
Brad Bishop615b2a82018-03-29 10:32:41 -0400177 public:
178 Manager() = delete;
179 Manager(const Manager&) = delete;
180 Manager& operator=(const Manager&) = delete;
181 Manager(Manager&&) = default;
182 Manager& operator=(Manager&&) = default;
183 ~Manager() = default;
Brad Bishop49aefb32016-10-19 11:54:14 -0400184
Brad Bishop615b2a82018-03-29 10:32:41 -0400185 /** @brief Construct an inventory manager.
186 *
187 * @param[in] bus - An sdbusplus bus connection.
188 * @param[in] busname - The DBus busname to own.
189 * @param[in] root - The DBus path on which to implement
190 * an inventory manager.
191 * @param[in] iface - The DBus inventory interface to implement.
192 */
193 Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*);
Brad Bishop49aefb32016-10-19 11:54:14 -0400194
Brad Bishop615b2a82018-03-29 10:32:41 -0400195 using EventInfo =
196 std::tuple<std::vector<EventBasePtr>, std::vector<Action>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400197
Brad Bishop615b2a82018-03-29 10:32:41 -0400198 /** @brief Start processing DBus messages. */
199 void run() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400200
Brad Bishop615b2a82018-03-29 10:32:41 -0400201 /** @brief Provided for testing only. */
202 void shutdown() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400203
Brad Bishop615b2a82018-03-29 10:32:41 -0400204 /** @brief sd_bus Notify method implementation callback. */
205 void
206 notify(std::map<sdbusplus::message::object_path, Object> objs) override;
Brad Bishop49aefb32016-10-19 11:54:14 -0400207
Brad Bishop615b2a82018-03-29 10:32:41 -0400208 /** @brief Event processing entry point. */
209 void handleEvent(sdbusplus::message::message&, const Event& event,
210 const EventInfo& info);
Brad Bishop49aefb32016-10-19 11:54:14 -0400211
Brad Bishop615b2a82018-03-29 10:32:41 -0400212 /** @brief Drop one or more objects from DBus. */
213 void destroyObjects(const std::vector<const char*>& paths);
Brad Bishop656a7d02016-10-19 22:20:02 -0400214
Brad Bishop615b2a82018-03-29 10:32:41 -0400215 /** @brief Add objects to DBus. */
216 void createObjects(
217 const std::map<sdbusplus::message::object_path, Object>& objs);
Brad Bishopeb68a682017-01-22 00:58:54 -0500218
Brad Bishop615b2a82018-03-29 10:32:41 -0400219 /** @brief Add or update objects on DBus. */
220 void updateObjects(
221 const std::map<sdbusplus::message::object_path, Object>& objs,
222 bool restoreFromCache = false);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500223
Brad Bishop615b2a82018-03-29 10:32:41 -0400224 /** @brief Restore persistent inventory items */
225 void restore();
Brad Bishop79ccaf72017-01-22 16:00:50 -0500226
Brad Bishop615b2a82018-03-29 10:32:41 -0400227 /** @brief Invoke an sdbusplus server binding method.
228 *
229 * Invoke the requested method with a reference to the requested
230 * sdbusplus server binding interface as a parameter.
231 *
232 * @tparam T - The sdbusplus server binding interface type.
233 * @tparam U - The type of the sdbusplus server binding member.
234 * @tparam Args - Argument types of the binding member.
235 *
236 * @param[in] path - The DBus path on which the method should
237 * be invoked.
238 * @param[in] interface - The DBus interface hosting the method.
239 * @param[in] member - Pointer to sdbusplus server binding member.
240 * @param[in] args - Arguments to forward to the binding member.
241 *
242 * @returns - The return/value type of the binding method being
243 * called.
244 */
245 template <typename T, typename U, typename... Args>
246 decltype(auto) invokeMethod(const char* path, const char* interface,
247 U&& member, Args&&... args)
248 {
249 auto& iface = getInterface<T>(path, interface);
250 return (iface.*member)(std::forward<Args>(args)...);
251 }
Brad Bishopda649b12016-11-30 14:35:02 -0500252
Brad Bishop615b2a82018-03-29 10:32:41 -0400253 using SigArgs = std::vector<std::unique_ptr<
254 std::tuple<Manager*, const DbusSignal*, const EventInfo*>>>;
255 using SigArg = SigArgs::value_type::element_type;
Brad Bishop49aefb32016-10-19 11:54:14 -0400256
Brad Bishop615b2a82018-03-29 10:32:41 -0400257 private:
Brad Bishop25d54b52018-11-21 12:57:51 -0500258 using InterfaceComposite = std::map<std::string, std::any>;
Brad Bishop615b2a82018-03-29 10:32:41 -0400259 using ObjectReferences = std::map<std::string, InterfaceComposite>;
260 using Events = std::vector<EventInfo>;
Brad Bishop90c30bc2017-01-22 16:40:47 -0500261
Brad Bishop615b2a82018-03-29 10:32:41 -0400262 // The int instantiations are safe since the signature of these
263 // functions don't change from one instantiation to the next.
264 using MakerType = std::add_pointer_t<decltype(MakeInterface<int>::make)>;
265 using AssignerType =
266 std::add_pointer_t<decltype(MakeInterface<int>::assign)>;
267 using SerializerType =
268 std::add_pointer_t<decltype(MakeInterface<int>::serialize)>;
269 using DeserializerType =
270 std::add_pointer_t<decltype(MakeInterface<int>::deserialize)>;
271 using Makers =
272 std::map<std::string, std::tuple<MakerType, AssignerType,
273 SerializerType, DeserializerType>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400274
Brad Bishop615b2a82018-03-29 10:32:41 -0400275 /** @brief Provides weak references to interface holders.
276 *
277 * Common code for all types for the templated getInterface
278 * methods.
279 *
280 * @param[in] path - The DBus path for which the interface
281 * holder instance should be provided.
282 * @param[in] interface - The DBus interface for which the
283 * holder instance should be provided.
284 *
285 * @returns A weak reference to the holder instance.
286 */
Brad Bishop25d54b52018-11-21 12:57:51 -0500287 const std::any& getInterfaceHolder(const char*, const char*) const;
288 std::any& getInterfaceHolder(const char*, const char*);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500289
Brad Bishop615b2a82018-03-29 10:32:41 -0400290 /** @brief Provides weak references to interface holders.
291 *
292 * @tparam T - The sdbusplus server binding interface type.
293 *
294 * @param[in] path - The DBus path for which the interface
295 * should be provided.
296 * @param[in] interface - The DBus interface to obtain.
297 *
298 * @returns A weak reference to the interface holder.
299 */
300 template <typename T>
301 auto& getInterface(const char* path, const char* interface)
302 {
303 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop25d54b52018-11-21 12:57:51 -0500304 return *std::any_cast<std::shared_ptr<T>&>(holder);
Brad Bishop615b2a82018-03-29 10:32:41 -0400305 }
306 template <typename T>
307 auto& getInterface(const char* path, const char* interface) const
308 {
309 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop25d54b52018-11-21 12:57:51 -0500310 return *std::any_cast<T>(holder);
Brad Bishop615b2a82018-03-29 10:32:41 -0400311 }
Brad Bishopb83a21e2016-11-30 13:43:37 -0500312
Brad Bishop615b2a82018-03-29 10:32:41 -0400313 /** @brief Add or update interfaces on DBus. */
314 void updateInterfaces(const sdbusplus::message::object_path& path,
315 const Object& interfaces,
316 ObjectReferences::iterator pos,
317 bool emitSignals = true,
318 bool restoreFromCache = false);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500319
Brad Bishop615b2a82018-03-29 10:32:41 -0400320 /** @brief Provided for testing only. */
321 volatile bool _shutdown;
Brad Bishop49aefb32016-10-19 11:54:14 -0400322
Brad Bishop615b2a82018-03-29 10:32:41 -0400323 /** @brief Path prefix applied to any relative paths. */
324 const char* _root;
Brad Bishop49aefb32016-10-19 11:54:14 -0400325
Brad Bishop615b2a82018-03-29 10:32:41 -0400326 /** @brief A container of sdbusplus server interface references. */
327 ObjectReferences _refs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400328
Brad Bishop615b2a82018-03-29 10:32:41 -0400329 /** @brief A container contexts for signal callbacks. */
330 SigArgs _sigargs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400331
Brad Bishop615b2a82018-03-29 10:32:41 -0400332 /** @brief A container of sdbusplus signal matches. */
333 std::vector<sdbusplus::bus::match_t> _matches;
Brad Bishop49aefb32016-10-19 11:54:14 -0400334
Brad Bishop615b2a82018-03-29 10:32:41 -0400335 /** @brief Persistent sdbusplus DBus bus connection. */
336 sdbusplus::bus::bus _bus;
Brad Bishop49aefb32016-10-19 11:54:14 -0400337
Brad Bishop615b2a82018-03-29 10:32:41 -0400338 /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
339 sdbusplus::server::manager::manager _manager;
Brad Bishop49aefb32016-10-19 11:54:14 -0400340
Brad Bishop615b2a82018-03-29 10:32:41 -0400341 /** @brief A container of pimgen generated events and responses. */
342 static const Events _events;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500343
Brad Bishop615b2a82018-03-29 10:32:41 -0400344 /** @brief A container of pimgen generated factory methods. */
345 static const Makers _makers;
Brad Bishop49aefb32016-10-19 11:54:14 -0400346};
347
348} // namespace manager
349} // namespace inventory
350} // namespace phosphor
351
352// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4