blob: c9f14a0e2ec52931dda942496c4c0ee9765e09c3 [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);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500108 cereal::serialize(path, iface, object);
109}
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{
115 cereal::serialize(path, iface);
116}
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);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500123 cereal::deserialize(path, iface, object);
124}
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{
130}
131
Brad Bishop65ffffa2016-11-29 12:31:31 -0500132/** @struct MakeInterface
133 * @brief Adapt an sdbusplus interface proxy.
134 *
135 * Template instances are builder functions that create
136 * adapted sdbusplus interface proxy interface objects.
137 *
138 * @tparam T - The type of the interface being adapted.
139 */
Brad Bishop79ccaf72017-01-22 16:00:50 -0500140
Patrick Venturea680d1e2018-10-14 13:34:26 -0700141template <typename T>
142struct MakeInterface
Brad Bishop65ffffa2016-11-29 12:31:31 -0500143{
Brad Bishop25d54b52018-11-21 12:57:51 -0500144 static std::any make(sdbusplus::bus::bus& bus, const char* path,
145 const Interface& props)
Brad Bishop65ffffa2016-11-29 12:31:31 -0500146 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500147 return propMake<T>(bus, path, props);
Brad Bishop65ffffa2016-11-29 12:31:31 -0500148 }
Brad Bishop79ccaf72017-01-22 16:00:50 -0500149
Brad Bishop25d54b52018-11-21 12:57:51 -0500150 static void assign(const Interface& props, std::any& holder)
Brad Bishop79ccaf72017-01-22 16:00:50 -0500151 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500152 propAssign<T>(props, holder);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500153 }
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500154
Brad Bishop615b2a82018-03-29 10:32:41 -0400155 static void serialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500156 const std::any& holder)
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500157 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500158 propSerialize<T>(path, iface, holder);
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500159 }
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500160
Brad Bishop615b2a82018-03-29 10:32:41 -0400161 static void deserialize(const std::string& path, const std::string& iface,
Brad Bishop25d54b52018-11-21 12:57:51 -0500162 std::any& holder)
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500163 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500164 propDeSerialize<T>(path, iface, holder);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500165 }
Brad Bishop65ffffa2016-11-29 12:31:31 -0500166};
Brad Bishop49aefb32016-10-19 11:54:14 -0400167
168/** @class Manager
169 * @brief OpenBMC inventory manager implementation.
170 *
171 * A concrete implementation for the xyz.openbmc_project.Inventory.Manager
172 * DBus API.
173 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400174class Manager final : public ServerObject<ManagerIface>
Brad Bishop49aefb32016-10-19 11:54:14 -0400175{
Brad Bishop615b2a82018-03-29 10:32:41 -0400176 public:
177 Manager() = delete;
178 Manager(const Manager&) = delete;
179 Manager& operator=(const Manager&) = delete;
180 Manager(Manager&&) = default;
181 Manager& operator=(Manager&&) = default;
182 ~Manager() = default;
Brad Bishop49aefb32016-10-19 11:54:14 -0400183
Brad Bishop615b2a82018-03-29 10:32:41 -0400184 /** @brief Construct an inventory manager.
185 *
186 * @param[in] bus - An sdbusplus bus connection.
187 * @param[in] busname - The DBus busname to own.
188 * @param[in] root - The DBus path on which to implement
189 * an inventory manager.
190 * @param[in] iface - The DBus inventory interface to implement.
191 */
192 Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*);
Brad Bishop49aefb32016-10-19 11:54:14 -0400193
Brad Bishop615b2a82018-03-29 10:32:41 -0400194 using EventInfo =
195 std::tuple<std::vector<EventBasePtr>, std::vector<Action>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400196
Brad Bishop615b2a82018-03-29 10:32:41 -0400197 /** @brief Start processing DBus messages. */
198 void run() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400199
Brad Bishop615b2a82018-03-29 10:32:41 -0400200 /** @brief Provided for testing only. */
201 void shutdown() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400202
Brad Bishop615b2a82018-03-29 10:32:41 -0400203 /** @brief sd_bus Notify method implementation callback. */
204 void
205 notify(std::map<sdbusplus::message::object_path, Object> objs) override;
Brad Bishop49aefb32016-10-19 11:54:14 -0400206
Brad Bishop615b2a82018-03-29 10:32:41 -0400207 /** @brief Event processing entry point. */
208 void handleEvent(sdbusplus::message::message&, const Event& event,
209 const EventInfo& info);
Brad Bishop49aefb32016-10-19 11:54:14 -0400210
Brad Bishop615b2a82018-03-29 10:32:41 -0400211 /** @brief Drop one or more objects from DBus. */
212 void destroyObjects(const std::vector<const char*>& paths);
Brad Bishop656a7d02016-10-19 22:20:02 -0400213
Brad Bishop615b2a82018-03-29 10:32:41 -0400214 /** @brief Add objects to DBus. */
215 void createObjects(
216 const std::map<sdbusplus::message::object_path, Object>& objs);
Brad Bishopeb68a682017-01-22 00:58:54 -0500217
Brad Bishop615b2a82018-03-29 10:32:41 -0400218 /** @brief Add or update objects on DBus. */
219 void updateObjects(
220 const std::map<sdbusplus::message::object_path, Object>& objs,
221 bool restoreFromCache = false);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500222
Brad Bishop615b2a82018-03-29 10:32:41 -0400223 /** @brief Restore persistent inventory items */
224 void restore();
Brad Bishop79ccaf72017-01-22 16:00:50 -0500225
Brad Bishop615b2a82018-03-29 10:32:41 -0400226 /** @brief Invoke an sdbusplus server binding method.
227 *
228 * Invoke the requested method with a reference to the requested
229 * sdbusplus server binding interface as a parameter.
230 *
231 * @tparam T - The sdbusplus server binding interface type.
232 * @tparam U - The type of the sdbusplus server binding member.
233 * @tparam Args - Argument types of the binding member.
234 *
235 * @param[in] path - The DBus path on which the method should
236 * be invoked.
237 * @param[in] interface - The DBus interface hosting the method.
238 * @param[in] member - Pointer to sdbusplus server binding member.
239 * @param[in] args - Arguments to forward to the binding member.
240 *
241 * @returns - The return/value type of the binding method being
242 * called.
243 */
244 template <typename T, typename U, typename... Args>
245 decltype(auto) invokeMethod(const char* path, const char* interface,
246 U&& member, Args&&... args)
247 {
248 auto& iface = getInterface<T>(path, interface);
249 return (iface.*member)(std::forward<Args>(args)...);
250 }
Brad Bishopda649b12016-11-30 14:35:02 -0500251
Brad Bishop615b2a82018-03-29 10:32:41 -0400252 using SigArgs = std::vector<std::unique_ptr<
253 std::tuple<Manager*, const DbusSignal*, const EventInfo*>>>;
254 using SigArg = SigArgs::value_type::element_type;
Brad Bishop49aefb32016-10-19 11:54:14 -0400255
Brad Bishop615b2a82018-03-29 10:32:41 -0400256 private:
Brad Bishop25d54b52018-11-21 12:57:51 -0500257 using InterfaceComposite = std::map<std::string, std::any>;
Brad Bishop615b2a82018-03-29 10:32:41 -0400258 using ObjectReferences = std::map<std::string, InterfaceComposite>;
259 using Events = std::vector<EventInfo>;
Brad Bishop90c30bc2017-01-22 16:40:47 -0500260
Brad Bishop615b2a82018-03-29 10:32:41 -0400261 // The int instantiations are safe since the signature of these
262 // functions don't change from one instantiation to the next.
263 using MakerType = std::add_pointer_t<decltype(MakeInterface<int>::make)>;
264 using AssignerType =
265 std::add_pointer_t<decltype(MakeInterface<int>::assign)>;
266 using SerializerType =
267 std::add_pointer_t<decltype(MakeInterface<int>::serialize)>;
268 using DeserializerType =
269 std::add_pointer_t<decltype(MakeInterface<int>::deserialize)>;
270 using Makers =
271 std::map<std::string, std::tuple<MakerType, AssignerType,
272 SerializerType, DeserializerType>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400273
Brad Bishop615b2a82018-03-29 10:32:41 -0400274 /** @brief Provides weak references to interface holders.
275 *
276 * Common code for all types for the templated getInterface
277 * methods.
278 *
279 * @param[in] path - The DBus path for which the interface
280 * holder instance should be provided.
281 * @param[in] interface - The DBus interface for which the
282 * holder instance should be provided.
283 *
284 * @returns A weak reference to the holder instance.
285 */
Brad Bishop25d54b52018-11-21 12:57:51 -0500286 const std::any& getInterfaceHolder(const char*, const char*) const;
287 std::any& getInterfaceHolder(const char*, const char*);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500288
Brad Bishop615b2a82018-03-29 10:32:41 -0400289 /** @brief Provides weak references to interface holders.
290 *
291 * @tparam T - The sdbusplus server binding interface type.
292 *
293 * @param[in] path - The DBus path for which the interface
294 * should be provided.
295 * @param[in] interface - The DBus interface to obtain.
296 *
297 * @returns A weak reference to the interface holder.
298 */
299 template <typename T>
300 auto& getInterface(const char* path, const char* interface)
301 {
302 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop25d54b52018-11-21 12:57:51 -0500303 return *std::any_cast<std::shared_ptr<T>&>(holder);
Brad Bishop615b2a82018-03-29 10:32:41 -0400304 }
305 template <typename T>
306 auto& getInterface(const char* path, const char* interface) const
307 {
308 auto& holder = getInterfaceHolder(path, interface);
Brad Bishop25d54b52018-11-21 12:57:51 -0500309 return *std::any_cast<T>(holder);
Brad Bishop615b2a82018-03-29 10:32:41 -0400310 }
Brad Bishopb83a21e2016-11-30 13:43:37 -0500311
Brad Bishop615b2a82018-03-29 10:32:41 -0400312 /** @brief Add or update interfaces on DBus. */
313 void updateInterfaces(const sdbusplus::message::object_path& path,
314 const Object& interfaces,
315 ObjectReferences::iterator pos,
316 bool emitSignals = true,
317 bool restoreFromCache = false);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500318
Brad Bishop615b2a82018-03-29 10:32:41 -0400319 /** @brief Provided for testing only. */
320 volatile bool _shutdown;
Brad Bishop49aefb32016-10-19 11:54:14 -0400321
Brad Bishop615b2a82018-03-29 10:32:41 -0400322 /** @brief Path prefix applied to any relative paths. */
323 const char* _root;
Brad Bishop49aefb32016-10-19 11:54:14 -0400324
Brad Bishop615b2a82018-03-29 10:32:41 -0400325 /** @brief A container of sdbusplus server interface references. */
326 ObjectReferences _refs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400327
Brad Bishop615b2a82018-03-29 10:32:41 -0400328 /** @brief A container contexts for signal callbacks. */
329 SigArgs _sigargs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400330
Brad Bishop615b2a82018-03-29 10:32:41 -0400331 /** @brief A container of sdbusplus signal matches. */
332 std::vector<sdbusplus::bus::match_t> _matches;
Brad Bishop49aefb32016-10-19 11:54:14 -0400333
Brad Bishop615b2a82018-03-29 10:32:41 -0400334 /** @brief Persistent sdbusplus DBus bus connection. */
335 sdbusplus::bus::bus _bus;
Brad Bishop49aefb32016-10-19 11:54:14 -0400336
Brad Bishop615b2a82018-03-29 10:32:41 -0400337 /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
338 sdbusplus::server::manager::manager _manager;
Brad Bishop49aefb32016-10-19 11:54:14 -0400339
Brad Bishop615b2a82018-03-29 10:32:41 -0400340 /** @brief A container of pimgen generated events and responses. */
341 static const Events _events;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500342
Brad Bishop615b2a82018-03-29 10:32:41 -0400343 /** @brief A container of pimgen generated factory methods. */
344 static const Makers _makers;
Brad Bishop49aefb32016-10-19 11:54:14 -0400345};
346
347} // namespace manager
348} // namespace inventory
349} // namespace phosphor
350
351// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4