blob: 121326799df98e3812079290e2f9f1c41f19bc26 [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
8#include <map>
9#include <memory>
10#include <sdbusplus/server.hpp>
11#include <string>
12#include <vector>
13#include <xyz/openbmc_project/Inventory/Manager/server.hpp>
Brad Bishop49aefb32016-10-19 11:54:14 -040014
15namespace phosphor
16{
17namespace inventory
18{
19namespace manager
20{
Brad Bishop451f8d92016-11-21 14:15:19 -050021
Patrick Venturea680d1e2018-10-14 13:34:26 -070022template <typename T>
23using ServerObject = T;
Brad Bishop451f8d92016-11-21 14:15:19 -050024
25using ManagerIface =
Brad Bishop9aa5e2f2017-01-15 19:45:40 -050026 sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
Brad Bishop451f8d92016-11-21 14:15:19 -050027
Brad Bishop79ccaf72017-01-22 16:00:50 -050028/** @struct PropertiesVariant
29 * @brief Wrapper for sdbusplus PropertiesVariant.
30 *
31 * A wrapper is useful since MakeInterface is instantiated with 'int'
32 * to deduce the return type of its methods, which does not depend
33 * on T.
34 *
35 * @tparam T - The sdbusplus server binding type.
36 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070037template <typename T, typename Enable = void>
38struct PropertiesVariant
Brad Bishop615b2a82018-03-29 10:32:41 -040039{
40};
Brad Bishop79ccaf72017-01-22 16:00:50 -050041
42template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040043struct PropertiesVariant<
44 T, typename std::enable_if<std::is_object<T>::value>::type>
Brad Bishop79ccaf72017-01-22 16:00:50 -050045{
46 using Type = typename T::PropertiesVariant;
47};
48
49template <typename T>
50using PropertiesVariantType = typename PropertiesVariant<T>::Type;
51
Patrick Venturea680d1e2018-10-14 13:34:26 -070052template <typename T, typename U = int>
53struct HasProperties : std::false_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050054{
55};
56
57template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040058struct HasProperties<
59 T, decltype((void)std::declval<typename T::PropertiesVariant>(), 0)>
60 : std::true_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050061{
62};
63
64template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -040065any_ns::any propMake(sdbusplus::bus::bus& bus, const char* path,
66 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050067{
Brad Bishop615b2a82018-03-29 10:32:41 -040068 using InterfaceVariant = std::map<std::string, PropertiesVariantType<T>>;
Marri Devender Raofa23d702017-09-02 04:43:42 -050069
70 InterfaceVariant v;
71 for (const auto& p : props)
72 {
Brad Bishop615b2a82018-03-29 10:32:41 -040073 v.emplace(p.first, convertVariant<PropertiesVariantType<T>>(p.second));
Marri Devender Raofa23d702017-09-02 04:43:42 -050074 }
75
76 return any_ns::any(std::make_shared<T>(bus, path, v));
77}
78
79template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -040080any_ns::any propMake(sdbusplus::bus::bus& bus, const char* path,
81 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050082{
83 return any_ns::any(std::make_shared<T>(bus, path));
84}
85
86template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
87void propAssign(const Interface& props, any_ns::any& holder)
88{
Brad Bishop615b2a82018-03-29 10:32:41 -040089 auto& iface = *any_ns::any_cast<std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -050090 for (const auto& p : props)
91 {
92 iface.setPropertyByName(
93 p.first, convertVariant<PropertiesVariantType<T>>(p.second));
94 }
95}
96
97template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
98void propAssign(const Interface& props, any_ns::any& holder)
99{
100}
101
102template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -0400103void propSerialize(const std::string& path, const std::string& iface,
104 const any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500105{
Brad Bishop615b2a82018-03-29 10:32:41 -0400106 const auto& object = *any_ns::any_cast<const std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500107 cereal::serialize(path, iface, object);
108}
109
110template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400111void propSerialize(const std::string& path, const std::string& iface,
112 const any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500113{
114 cereal::serialize(path, iface);
115}
116
117template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -0400118void propDeSerialize(const std::string& path, const std::string& iface,
119 any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500120{
Brad Bishop615b2a82018-03-29 10:32:41 -0400121 auto& object = *any_ns::any_cast<std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500122 cereal::deserialize(path, iface, object);
123}
124
125template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400126void propDeSerialize(const std::string& path, const std::string& iface,
127 any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500128{
129}
130
Brad Bishop65ffffa2016-11-29 12:31:31 -0500131/** @struct MakeInterface
132 * @brief Adapt an sdbusplus interface proxy.
133 *
134 * Template instances are builder functions that create
135 * adapted sdbusplus interface proxy interface objects.
136 *
137 * @tparam T - The type of the interface being adapted.
138 */
Brad Bishop79ccaf72017-01-22 16:00:50 -0500139
Patrick Venturea680d1e2018-10-14 13:34:26 -0700140template <typename T>
141struct MakeInterface
Brad Bishop65ffffa2016-11-29 12:31:31 -0500142{
Brad Bishop615b2a82018-03-29 10:32:41 -0400143 static any_ns::any make(sdbusplus::bus::bus& bus, const char* path,
144 const Interface& props)
Brad Bishop65ffffa2016-11-29 12:31:31 -0500145 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500146 return propMake<T>(bus, path, props);
Brad Bishop65ffffa2016-11-29 12:31:31 -0500147 }
Brad Bishop79ccaf72017-01-22 16:00:50 -0500148
149 static void assign(const Interface& props, any_ns::any& holder)
150 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500151 propAssign<T>(props, holder);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500152 }
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500153
Brad Bishop615b2a82018-03-29 10:32:41 -0400154 static void serialize(const std::string& path, const std::string& iface,
155 const any_ns::any& holder)
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500156 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500157 propSerialize<T>(path, iface, holder);
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500158 }
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500159
Brad Bishop615b2a82018-03-29 10:32:41 -0400160 static void deserialize(const std::string& path, const std::string& iface,
161 any_ns::any& holder)
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500162 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500163 propDeSerialize<T>(path, iface, holder);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500164 }
Brad Bishop65ffffa2016-11-29 12:31:31 -0500165};
Brad Bishop49aefb32016-10-19 11:54:14 -0400166
167/** @class Manager
168 * @brief OpenBMC inventory manager implementation.
169 *
170 * A concrete implementation for the xyz.openbmc_project.Inventory.Manager
171 * DBus API.
172 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400173class Manager final : public ServerObject<ManagerIface>
Brad Bishop49aefb32016-10-19 11:54:14 -0400174{
Brad Bishop615b2a82018-03-29 10:32:41 -0400175 public:
176 Manager() = delete;
177 Manager(const Manager&) = delete;
178 Manager& operator=(const Manager&) = delete;
179 Manager(Manager&&) = default;
180 Manager& operator=(Manager&&) = default;
181 ~Manager() = default;
Brad Bishop49aefb32016-10-19 11:54:14 -0400182
Brad Bishop615b2a82018-03-29 10:32:41 -0400183 /** @brief Construct an inventory manager.
184 *
185 * @param[in] bus - An sdbusplus bus connection.
186 * @param[in] busname - The DBus busname to own.
187 * @param[in] root - The DBus path on which to implement
188 * an inventory manager.
189 * @param[in] iface - The DBus inventory interface to implement.
190 */
191 Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*);
Brad Bishop49aefb32016-10-19 11:54:14 -0400192
Brad Bishop615b2a82018-03-29 10:32:41 -0400193 using EventInfo =
194 std::tuple<std::vector<EventBasePtr>, std::vector<Action>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400195
Brad Bishop615b2a82018-03-29 10:32:41 -0400196 /** @brief Start processing DBus messages. */
197 void run() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400198
Brad Bishop615b2a82018-03-29 10:32:41 -0400199 /** @brief Provided for testing only. */
200 void shutdown() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400201
Brad Bishop615b2a82018-03-29 10:32:41 -0400202 /** @brief sd_bus Notify method implementation callback. */
203 void
204 notify(std::map<sdbusplus::message::object_path, Object> objs) override;
Brad Bishop49aefb32016-10-19 11:54:14 -0400205
Brad Bishop615b2a82018-03-29 10:32:41 -0400206 /** @brief Event processing entry point. */
207 void handleEvent(sdbusplus::message::message&, const Event& event,
208 const EventInfo& info);
Brad Bishop49aefb32016-10-19 11:54:14 -0400209
Brad Bishop615b2a82018-03-29 10:32:41 -0400210 /** @brief Drop one or more objects from DBus. */
211 void destroyObjects(const std::vector<const char*>& paths);
Brad Bishop656a7d02016-10-19 22:20:02 -0400212
Brad Bishop615b2a82018-03-29 10:32:41 -0400213 /** @brief Add objects to DBus. */
214 void createObjects(
215 const std::map<sdbusplus::message::object_path, Object>& objs);
Brad Bishopeb68a682017-01-22 00:58:54 -0500216
Brad Bishop615b2a82018-03-29 10:32:41 -0400217 /** @brief Add or update objects on DBus. */
218 void updateObjects(
219 const std::map<sdbusplus::message::object_path, Object>& objs,
220 bool restoreFromCache = false);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500221
Brad Bishop615b2a82018-03-29 10:32:41 -0400222 /** @brief Restore persistent inventory items */
223 void restore();
Brad Bishop79ccaf72017-01-22 16:00:50 -0500224
Brad Bishop615b2a82018-03-29 10:32:41 -0400225 /** @brief Invoke an sdbusplus server binding method.
226 *
227 * Invoke the requested method with a reference to the requested
228 * sdbusplus server binding interface as a parameter.
229 *
230 * @tparam T - The sdbusplus server binding interface type.
231 * @tparam U - The type of the sdbusplus server binding member.
232 * @tparam Args - Argument types of the binding member.
233 *
234 * @param[in] path - The DBus path on which the method should
235 * be invoked.
236 * @param[in] interface - The DBus interface hosting the method.
237 * @param[in] member - Pointer to sdbusplus server binding member.
238 * @param[in] args - Arguments to forward to the binding member.
239 *
240 * @returns - The return/value type of the binding method being
241 * called.
242 */
243 template <typename T, typename U, typename... Args>
244 decltype(auto) invokeMethod(const char* path, const char* interface,
245 U&& member, Args&&... args)
246 {
247 auto& iface = getInterface<T>(path, interface);
248 return (iface.*member)(std::forward<Args>(args)...);
249 }
Brad Bishopda649b12016-11-30 14:35:02 -0500250
Brad Bishop615b2a82018-03-29 10:32:41 -0400251 using SigArgs = std::vector<std::unique_ptr<
252 std::tuple<Manager*, const DbusSignal*, const EventInfo*>>>;
253 using SigArg = SigArgs::value_type::element_type;
Brad Bishop49aefb32016-10-19 11:54:14 -0400254
Brad Bishop615b2a82018-03-29 10:32:41 -0400255 private:
256 using InterfaceComposite = std::map<std::string, any_ns::any>;
257 using ObjectReferences = std::map<std::string, InterfaceComposite>;
258 using Events = std::vector<EventInfo>;
Brad Bishop90c30bc2017-01-22 16:40:47 -0500259
Brad Bishop615b2a82018-03-29 10:32:41 -0400260 // The int instantiations are safe since the signature of these
261 // functions don't change from one instantiation to the next.
262 using MakerType = std::add_pointer_t<decltype(MakeInterface<int>::make)>;
263 using AssignerType =
264 std::add_pointer_t<decltype(MakeInterface<int>::assign)>;
265 using SerializerType =
266 std::add_pointer_t<decltype(MakeInterface<int>::serialize)>;
267 using DeserializerType =
268 std::add_pointer_t<decltype(MakeInterface<int>::deserialize)>;
269 using Makers =
270 std::map<std::string, std::tuple<MakerType, AssignerType,
271 SerializerType, DeserializerType>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400272
Brad Bishop615b2a82018-03-29 10:32:41 -0400273 /** @brief Provides weak references to interface holders.
274 *
275 * Common code for all types for the templated getInterface
276 * methods.
277 *
278 * @param[in] path - The DBus path for which the interface
279 * holder instance should be provided.
280 * @param[in] interface - The DBus interface for which the
281 * holder instance should be provided.
282 *
283 * @returns A weak reference to the holder instance.
284 */
285 const any_ns::any& getInterfaceHolder(const char*, const char*) const;
286 any_ns::any& getInterfaceHolder(const char*, const char*);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500287
Brad Bishop615b2a82018-03-29 10:32:41 -0400288 /** @brief Provides weak references to interface holders.
289 *
290 * @tparam T - The sdbusplus server binding interface type.
291 *
292 * @param[in] path - The DBus path for which the interface
293 * should be provided.
294 * @param[in] interface - The DBus interface to obtain.
295 *
296 * @returns A weak reference to the interface holder.
297 */
298 template <typename T>
299 auto& getInterface(const char* path, const char* interface)
300 {
301 auto& holder = getInterfaceHolder(path, interface);
302 return *any_ns::any_cast<std::shared_ptr<T>&>(holder);
303 }
304 template <typename T>
305 auto& getInterface(const char* path, const char* interface) const
306 {
307 auto& holder = getInterfaceHolder(path, interface);
308 return *any_ns::any_cast<T>(holder);
309 }
Brad Bishopb83a21e2016-11-30 13:43:37 -0500310
Brad Bishop615b2a82018-03-29 10:32:41 -0400311 /** @brief Add or update interfaces on DBus. */
312 void updateInterfaces(const sdbusplus::message::object_path& path,
313 const Object& interfaces,
314 ObjectReferences::iterator pos,
315 bool emitSignals = true,
316 bool restoreFromCache = false);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500317
Brad Bishop615b2a82018-03-29 10:32:41 -0400318 /** @brief Provided for testing only. */
319 volatile bool _shutdown;
Brad Bishop49aefb32016-10-19 11:54:14 -0400320
Brad Bishop615b2a82018-03-29 10:32:41 -0400321 /** @brief Path prefix applied to any relative paths. */
322 const char* _root;
Brad Bishop49aefb32016-10-19 11:54:14 -0400323
Brad Bishop615b2a82018-03-29 10:32:41 -0400324 /** @brief A container of sdbusplus server interface references. */
325 ObjectReferences _refs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400326
Brad Bishop615b2a82018-03-29 10:32:41 -0400327 /** @brief A container contexts for signal callbacks. */
328 SigArgs _sigargs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400329
Brad Bishop615b2a82018-03-29 10:32:41 -0400330 /** @brief A container of sdbusplus signal matches. */
331 std::vector<sdbusplus::bus::match_t> _matches;
Brad Bishop49aefb32016-10-19 11:54:14 -0400332
Brad Bishop615b2a82018-03-29 10:32:41 -0400333 /** @brief Persistent sdbusplus DBus bus connection. */
334 sdbusplus::bus::bus _bus;
Brad Bishop49aefb32016-10-19 11:54:14 -0400335
Brad Bishop615b2a82018-03-29 10:32:41 -0400336 /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
337 sdbusplus::server::manager::manager _manager;
Brad Bishop49aefb32016-10-19 11:54:14 -0400338
Brad Bishop615b2a82018-03-29 10:32:41 -0400339 /** @brief A container of pimgen generated events and responses. */
340 static const Events _events;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500341
Brad Bishop615b2a82018-03-29 10:32:41 -0400342 /** @brief A container of pimgen generated factory methods. */
343 static const Makers _makers;
Brad Bishop49aefb32016-10-19 11:54:14 -0400344};
345
346} // namespace manager
347} // namespace inventory
348} // namespace phosphor
349
350// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4