blob: 9bbd3c727835c61047573bb26b86a3b638b6cef2 [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
Brad Bishop615b2a82018-03-29 10:32:41 -040021template <typename T> using ServerObject = T;
Brad Bishop451f8d92016-11-21 14:15:19 -050022
23using ManagerIface =
Brad Bishop9aa5e2f2017-01-15 19:45:40 -050024 sdbusplus::xyz::openbmc_project::Inventory::server::Manager;
Brad Bishop451f8d92016-11-21 14:15:19 -050025
Brad Bishop79ccaf72017-01-22 16:00:50 -050026/** @struct PropertiesVariant
27 * @brief Wrapper for sdbusplus PropertiesVariant.
28 *
29 * A wrapper is useful since MakeInterface is instantiated with 'int'
30 * to deduce the return type of its methods, which does not depend
31 * on T.
32 *
33 * @tparam T - The sdbusplus server binding type.
34 */
Brad Bishop615b2a82018-03-29 10:32:41 -040035template <typename T, typename Enable = void> struct PropertiesVariant
36{
37};
Brad Bishop79ccaf72017-01-22 16:00:50 -050038
39template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040040struct PropertiesVariant<
41 T, typename std::enable_if<std::is_object<T>::value>::type>
Brad Bishop79ccaf72017-01-22 16:00:50 -050042{
43 using Type = typename T::PropertiesVariant;
44};
45
46template <typename T>
47using PropertiesVariantType = typename PropertiesVariant<T>::Type;
48
Brad Bishop615b2a82018-03-29 10:32:41 -040049template <typename T, typename U = int> struct HasProperties : std::false_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050050{
51};
52
53template <typename T>
Brad Bishop615b2a82018-03-29 10:32:41 -040054struct HasProperties<
55 T, decltype((void)std::declval<typename T::PropertiesVariant>(), 0)>
56 : std::true_type
Marri Devender Raofa23d702017-09-02 04:43:42 -050057{
58};
59
60template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -040061any_ns::any propMake(sdbusplus::bus::bus& bus, const char* path,
62 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050063{
Brad Bishop615b2a82018-03-29 10:32:41 -040064 using InterfaceVariant = std::map<std::string, PropertiesVariantType<T>>;
Marri Devender Raofa23d702017-09-02 04:43:42 -050065
66 InterfaceVariant v;
67 for (const auto& p : props)
68 {
Brad Bishop615b2a82018-03-29 10:32:41 -040069 v.emplace(p.first, convertVariant<PropertiesVariantType<T>>(p.second));
Marri Devender Raofa23d702017-09-02 04:43:42 -050070 }
71
72 return any_ns::any(std::make_shared<T>(bus, path, v));
73}
74
75template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -040076any_ns::any propMake(sdbusplus::bus::bus& bus, const char* path,
77 const Interface& props)
Marri Devender Raofa23d702017-09-02 04:43:42 -050078{
79 return any_ns::any(std::make_shared<T>(bus, path));
80}
81
82template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
83void propAssign(const Interface& props, any_ns::any& holder)
84{
Brad Bishop615b2a82018-03-29 10:32:41 -040085 auto& iface = *any_ns::any_cast<std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -050086 for (const auto& p : props)
87 {
88 iface.setPropertyByName(
89 p.first, convertVariant<PropertiesVariantType<T>>(p.second));
90 }
91}
92
93template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
94void propAssign(const Interface& props, any_ns::any& holder)
95{
96}
97
98template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -040099void propSerialize(const std::string& path, const std::string& iface,
100 const any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500101{
Brad Bishop615b2a82018-03-29 10:32:41 -0400102 const auto& object = *any_ns::any_cast<const std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500103 cereal::serialize(path, iface, object);
104}
105
106template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400107void propSerialize(const std::string& path, const std::string& iface,
108 const any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500109{
110 cereal::serialize(path, iface);
111}
112
113template <typename T, std::enable_if_t<HasProperties<T>::value, bool> = true>
Brad Bishop615b2a82018-03-29 10:32:41 -0400114void propDeSerialize(const std::string& path, const std::string& iface,
115 any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500116{
Brad Bishop615b2a82018-03-29 10:32:41 -0400117 auto& object = *any_ns::any_cast<std::shared_ptr<T>&>(holder);
Marri Devender Raofa23d702017-09-02 04:43:42 -0500118 cereal::deserialize(path, iface, object);
119}
120
121template <typename T, std::enable_if_t<!HasProperties<T>::value, bool> = false>
Brad Bishop615b2a82018-03-29 10:32:41 -0400122void propDeSerialize(const std::string& path, const std::string& iface,
123 any_ns::any& holder)
Marri Devender Raofa23d702017-09-02 04:43:42 -0500124{
125}
126
Brad Bishop65ffffa2016-11-29 12:31:31 -0500127/** @struct MakeInterface
128 * @brief Adapt an sdbusplus interface proxy.
129 *
130 * Template instances are builder functions that create
131 * adapted sdbusplus interface proxy interface objects.
132 *
133 * @tparam T - The type of the interface being adapted.
134 */
Brad Bishop79ccaf72017-01-22 16:00:50 -0500135
Brad Bishop615b2a82018-03-29 10:32:41 -0400136template <typename T> struct MakeInterface
Brad Bishop65ffffa2016-11-29 12:31:31 -0500137{
Brad Bishop615b2a82018-03-29 10:32:41 -0400138 static any_ns::any make(sdbusplus::bus::bus& bus, const char* path,
139 const Interface& props)
Brad Bishop65ffffa2016-11-29 12:31:31 -0500140 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500141 return propMake<T>(bus, path, props);
Brad Bishop65ffffa2016-11-29 12:31:31 -0500142 }
Brad Bishop79ccaf72017-01-22 16:00:50 -0500143
144 static void assign(const Interface& props, any_ns::any& holder)
145 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500146 propAssign<T>(props, holder);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500147 }
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500148
Brad Bishop615b2a82018-03-29 10:32:41 -0400149 static void serialize(const std::string& path, const std::string& iface,
150 const any_ns::any& holder)
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500151 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500152 propSerialize<T>(path, iface, holder);
Deepak Kodihalli6620e982017-08-05 13:09:54 -0500153 }
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500154
Brad Bishop615b2a82018-03-29 10:32:41 -0400155 static void deserialize(const std::string& path, const std::string& iface,
156 any_ns::any& holder)
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500157 {
Marri Devender Raofa23d702017-09-02 04:43:42 -0500158 propDeSerialize<T>(path, iface, holder);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500159 }
Brad Bishop65ffffa2016-11-29 12:31:31 -0500160};
Brad Bishop49aefb32016-10-19 11:54:14 -0400161
162/** @class Manager
163 * @brief OpenBMC inventory manager implementation.
164 *
165 * A concrete implementation for the xyz.openbmc_project.Inventory.Manager
166 * DBus API.
167 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400168class Manager final : public ServerObject<ManagerIface>
Brad Bishop49aefb32016-10-19 11:54:14 -0400169{
Brad Bishop615b2a82018-03-29 10:32:41 -0400170 public:
171 Manager() = delete;
172 Manager(const Manager&) = delete;
173 Manager& operator=(const Manager&) = delete;
174 Manager(Manager&&) = default;
175 Manager& operator=(Manager&&) = default;
176 ~Manager() = default;
Brad Bishop49aefb32016-10-19 11:54:14 -0400177
Brad Bishop615b2a82018-03-29 10:32:41 -0400178 /** @brief Construct an inventory manager.
179 *
180 * @param[in] bus - An sdbusplus bus connection.
181 * @param[in] busname - The DBus busname to own.
182 * @param[in] root - The DBus path on which to implement
183 * an inventory manager.
184 * @param[in] iface - The DBus inventory interface to implement.
185 */
186 Manager(sdbusplus::bus::bus&&, const char*, const char*, const char*);
Brad Bishop49aefb32016-10-19 11:54:14 -0400187
Brad Bishop615b2a82018-03-29 10:32:41 -0400188 using EventInfo =
189 std::tuple<std::vector<EventBasePtr>, std::vector<Action>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400190
Brad Bishop615b2a82018-03-29 10:32:41 -0400191 /** @brief Start processing DBus messages. */
192 void run() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400193
Brad Bishop615b2a82018-03-29 10:32:41 -0400194 /** @brief Provided for testing only. */
195 void shutdown() noexcept;
Brad Bishop49aefb32016-10-19 11:54:14 -0400196
Brad Bishop615b2a82018-03-29 10:32:41 -0400197 /** @brief sd_bus Notify method implementation callback. */
198 void
199 notify(std::map<sdbusplus::message::object_path, Object> objs) override;
Brad Bishop49aefb32016-10-19 11:54:14 -0400200
Brad Bishop615b2a82018-03-29 10:32:41 -0400201 /** @brief Event processing entry point. */
202 void handleEvent(sdbusplus::message::message&, const Event& event,
203 const EventInfo& info);
Brad Bishop49aefb32016-10-19 11:54:14 -0400204
Brad Bishop615b2a82018-03-29 10:32:41 -0400205 /** @brief Drop one or more objects from DBus. */
206 void destroyObjects(const std::vector<const char*>& paths);
Brad Bishop656a7d02016-10-19 22:20:02 -0400207
Brad Bishop615b2a82018-03-29 10:32:41 -0400208 /** @brief Add objects to DBus. */
209 void createObjects(
210 const std::map<sdbusplus::message::object_path, Object>& objs);
Brad Bishopeb68a682017-01-22 00:58:54 -0500211
Brad Bishop615b2a82018-03-29 10:32:41 -0400212 /** @brief Add or update objects on DBus. */
213 void updateObjects(
214 const std::map<sdbusplus::message::object_path, Object>& objs,
215 bool restoreFromCache = false);
Deepak Kodihallib28990f2017-08-08 07:19:34 -0500216
Brad Bishop615b2a82018-03-29 10:32:41 -0400217 /** @brief Restore persistent inventory items */
218 void restore();
Brad Bishop79ccaf72017-01-22 16:00:50 -0500219
Brad Bishop615b2a82018-03-29 10:32:41 -0400220 /** @brief Invoke an sdbusplus server binding method.
221 *
222 * Invoke the requested method with a reference to the requested
223 * sdbusplus server binding interface as a parameter.
224 *
225 * @tparam T - The sdbusplus server binding interface type.
226 * @tparam U - The type of the sdbusplus server binding member.
227 * @tparam Args - Argument types of the binding member.
228 *
229 * @param[in] path - The DBus path on which the method should
230 * be invoked.
231 * @param[in] interface - The DBus interface hosting the method.
232 * @param[in] member - Pointer to sdbusplus server binding member.
233 * @param[in] args - Arguments to forward to the binding member.
234 *
235 * @returns - The return/value type of the binding method being
236 * called.
237 */
238 template <typename T, typename U, typename... Args>
239 decltype(auto) invokeMethod(const char* path, const char* interface,
240 U&& member, Args&&... args)
241 {
242 auto& iface = getInterface<T>(path, interface);
243 return (iface.*member)(std::forward<Args>(args)...);
244 }
Brad Bishopda649b12016-11-30 14:35:02 -0500245
Brad Bishop615b2a82018-03-29 10:32:41 -0400246 using SigArgs = std::vector<std::unique_ptr<
247 std::tuple<Manager*, const DbusSignal*, const EventInfo*>>>;
248 using SigArg = SigArgs::value_type::element_type;
Brad Bishop49aefb32016-10-19 11:54:14 -0400249
Brad Bishop615b2a82018-03-29 10:32:41 -0400250 private:
251 using InterfaceComposite = std::map<std::string, any_ns::any>;
252 using ObjectReferences = std::map<std::string, InterfaceComposite>;
253 using Events = std::vector<EventInfo>;
Brad Bishop90c30bc2017-01-22 16:40:47 -0500254
Brad Bishop615b2a82018-03-29 10:32:41 -0400255 // The int instantiations are safe since the signature of these
256 // functions don't change from one instantiation to the next.
257 using MakerType = std::add_pointer_t<decltype(MakeInterface<int>::make)>;
258 using AssignerType =
259 std::add_pointer_t<decltype(MakeInterface<int>::assign)>;
260 using SerializerType =
261 std::add_pointer_t<decltype(MakeInterface<int>::serialize)>;
262 using DeserializerType =
263 std::add_pointer_t<decltype(MakeInterface<int>::deserialize)>;
264 using Makers =
265 std::map<std::string, std::tuple<MakerType, AssignerType,
266 SerializerType, DeserializerType>>;
Brad Bishop49aefb32016-10-19 11:54:14 -0400267
Brad Bishop615b2a82018-03-29 10:32:41 -0400268 /** @brief Provides weak references to interface holders.
269 *
270 * Common code for all types for the templated getInterface
271 * methods.
272 *
273 * @param[in] path - The DBus path for which the interface
274 * holder instance should be provided.
275 * @param[in] interface - The DBus interface for which the
276 * holder instance should be provided.
277 *
278 * @returns A weak reference to the holder instance.
279 */
280 const any_ns::any& getInterfaceHolder(const char*, const char*) const;
281 any_ns::any& getInterfaceHolder(const char*, const char*);
Brad Bishopb83a21e2016-11-30 13:43:37 -0500282
Brad Bishop615b2a82018-03-29 10:32:41 -0400283 /** @brief Provides weak references to interface holders.
284 *
285 * @tparam T - The sdbusplus server binding interface type.
286 *
287 * @param[in] path - The DBus path for which the interface
288 * should be provided.
289 * @param[in] interface - The DBus interface to obtain.
290 *
291 * @returns A weak reference to the interface holder.
292 */
293 template <typename T>
294 auto& getInterface(const char* path, const char* interface)
295 {
296 auto& holder = getInterfaceHolder(path, interface);
297 return *any_ns::any_cast<std::shared_ptr<T>&>(holder);
298 }
299 template <typename T>
300 auto& getInterface(const char* path, const char* interface) const
301 {
302 auto& holder = getInterfaceHolder(path, interface);
303 return *any_ns::any_cast<T>(holder);
304 }
Brad Bishopb83a21e2016-11-30 13:43:37 -0500305
Brad Bishop615b2a82018-03-29 10:32:41 -0400306 /** @brief Add or update interfaces on DBus. */
307 void updateInterfaces(const sdbusplus::message::object_path& path,
308 const Object& interfaces,
309 ObjectReferences::iterator pos,
310 bool emitSignals = true,
311 bool restoreFromCache = false);
Brad Bishop79ccaf72017-01-22 16:00:50 -0500312
Brad Bishop615b2a82018-03-29 10:32:41 -0400313 /** @brief Provided for testing only. */
314 volatile bool _shutdown;
Brad Bishop49aefb32016-10-19 11:54:14 -0400315
Brad Bishop615b2a82018-03-29 10:32:41 -0400316 /** @brief Path prefix applied to any relative paths. */
317 const char* _root;
Brad Bishop49aefb32016-10-19 11:54:14 -0400318
Brad Bishop615b2a82018-03-29 10:32:41 -0400319 /** @brief A container of sdbusplus server interface references. */
320 ObjectReferences _refs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400321
Brad Bishop615b2a82018-03-29 10:32:41 -0400322 /** @brief A container contexts for signal callbacks. */
323 SigArgs _sigargs;
Brad Bishop49aefb32016-10-19 11:54:14 -0400324
Brad Bishop615b2a82018-03-29 10:32:41 -0400325 /** @brief A container of sdbusplus signal matches. */
326 std::vector<sdbusplus::bus::match_t> _matches;
Brad Bishop49aefb32016-10-19 11:54:14 -0400327
Brad Bishop615b2a82018-03-29 10:32:41 -0400328 /** @brief Persistent sdbusplus DBus bus connection. */
329 sdbusplus::bus::bus _bus;
Brad Bishop49aefb32016-10-19 11:54:14 -0400330
Brad Bishop615b2a82018-03-29 10:32:41 -0400331 /** @brief sdbusplus org.freedesktop.DBus.ObjectManager reference. */
332 sdbusplus::server::manager::manager _manager;
Brad Bishop49aefb32016-10-19 11:54:14 -0400333
Brad Bishop615b2a82018-03-29 10:32:41 -0400334 /** @brief A container of pimgen generated events and responses. */
335 static const Events _events;
Brad Bishop5fbaa7f2016-10-31 10:42:41 -0500336
Brad Bishop615b2a82018-03-29 10:32:41 -0400337 /** @brief A container of pimgen generated factory methods. */
338 static const Makers _makers;
Brad Bishop49aefb32016-10-19 11:54:14 -0400339};
340
341} // namespace manager
342} // namespace inventory
343} // namespace phosphor
344
345// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4