blob: 8704020670bbcb7ecf7422db9674b59071da3ae0 [file] [log] [blame]
Matthew Barth38a93a82017-05-11 14:12:27 -05001#pragma once
2
3#include "types.hpp"
Matthew Barth336f18a2017-09-26 09:15:56 -05004#include "sdbusplus.hpp"
Matthew Barth38a93a82017-05-11 14:12:27 -05005#include <phosphor-logging/log.hpp>
6
7namespace phosphor
8{
9namespace fan
10{
11namespace control
12{
13class Zone;
14
Matthew Barth336f18a2017-09-26 09:15:56 -050015using namespace phosphor::fan;
Matthew Barth5a302572017-10-03 11:27:06 -050016using namespace sdbusplus::bus::match;
Matthew Barth38a93a82017-05-11 14:12:27 -050017using namespace phosphor::logging;
18
19/**
Matthew Barth1b3e9602019-02-13 11:37:03 -060020 * @brief Create a zone handler function object
21 *
22 * @param[in] handler - The handler being created
23 *
24 * @return - The created zone handler function object
25 */
26template <typename T>
27auto make_zoneHandler(T&& handler)
28{
29 return ZoneHandler(std::forward<T>(handler));
30}
31
32/**
Matthew Barth1b4de262018-03-06 13:03:16 -060033 * @brief Create a trigger function object
34 *
35 * @param[in] trigger - The trigger being created
36 *
37 * @return - The created trigger function object
38 */
39template <typename T>
40auto make_trigger(T&& trigger)
41{
42 return Trigger(std::forward<T>(trigger));
43}
44
45/**
Matthew Barth38a93a82017-05-11 14:12:27 -050046 * @brief Create a handler function object
47 *
48 * @param[in] handler - The handler being created
49 *
50 * @return - The created handler function object
51 */
Matthew Barth926df662018-10-09 09:51:12 -050052template <typename T, typename U>
53auto make_handler(U&& handler)
Matthew Barth38a93a82017-05-11 14:12:27 -050054{
Matthew Barth926df662018-10-09 09:51:12 -050055 return T(std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -050056}
57
58/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050059 * @brief Create an action function object
60 *
61 * @param[in] action - The action being created
62 *
63 * @return - The created action function object
64 */
65template <typename T>
66auto make_action(T&& action)
67{
68 return Action(std::forward<T>(action));
69}
70
71/**
Matthew Barth926df662018-10-09 09:51:12 -050072 * @struct Properties
73 * @brief A set of match filter functors for Dbus property values. Each
74 * functor provides an associated process for retrieving the value
75 * for a given property and providing it to the given handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -050076 *
77 * @tparam T - The type of the property value
78 * @tparam U - The type of the handler
79 */
80template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -050081struct Properties
Matthew Barth38a93a82017-05-11 14:12:27 -050082{
Matthew Barth926df662018-10-09 09:51:12 -050083 Properties() = delete;
84 ~Properties() = default;
85 Properties(const Properties&) = default;
86 Properties& operator=(const Properties&) = default;
87 Properties(Properties&&) = default;
88 Properties& operator=(Properties&&) = default;
89 explicit Properties(U&& handler) :
90 _path(""),
91 _iface(""),
92 _property(""),
93 _handler(std::forward<U>(handler)) { }
94 Properties(const char* path,
95 const char* iface,
96 const char* property,
97 U&& handler) :
Matthew Barth336f18a2017-09-26 09:15:56 -050098 _path(path),
Matthew Barth38a93a82017-05-11 14:12:27 -050099 _iface(iface),
100 _property(property),
101 _handler(std::forward<U>(handler)) { }
102
103 /** @brief Run signal handler function
104 *
105 * Extract the property from the PropertiesChanged
Matthew Barth926df662018-10-09 09:51:12 -0500106 * message and run the handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -0500107 */
Matthew Barth336f18a2017-09-26 09:15:56 -0500108 void operator()(sdbusplus::bus::bus& bus,
Matthew Barth38a93a82017-05-11 14:12:27 -0500109 sdbusplus::message::message& msg,
110 Zone& zone) const
111 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500112 if (msg)
Matthew Barth38a93a82017-05-11 14:12:27 -0500113 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500114 std::map<std::string, sdbusplus::message::variant<T>> properties;
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600115 std::string iface;
Matthew Barth38a93a82017-05-11 14:12:27 -0500116
Matthew Barth336f18a2017-09-26 09:15:56 -0500117 msg.read(iface);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600118 if (iface != _iface)
Matthew Barth336f18a2017-09-26 09:15:56 -0500119 {
120 return;
121 }
122
123 msg.read(properties);
124 auto it = properties.find(_property);
125 if (it == properties.cend())
126 {
127 log<level::ERR>("Unable to find property on interface",
128 entry("PROPERTY=%s", _property),
Matthew Barthe65f6172017-12-11 13:36:02 -0600129 entry("INTERFACE=%s", _iface),
130 entry("PATH=%s", _path));
Matthew Barth336f18a2017-09-26 09:15:56 -0500131 return;
132 }
133
William A. Kennington III4978e062018-11-27 11:47:12 -0800134 _handler(zone, std::forward<T>(
135 sdbusplus::message::variant_ns::get<T>(it->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500136 }
137 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500138 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500139 try
140 {
Matthew Barth766f8542019-01-29 12:44:13 -0600141 auto val = zone.getPropertyByName<T>(_path, _iface, _property);
Matthew Barth336f18a2017-09-26 09:15:56 -0500142 _handler(zone, std::forward<T>(val));
143 }
Matthew Barth86be4762018-07-17 10:51:36 -0500144 catch (const sdbusplus::exception::SdBusError&)
145 {
146 // Property will not be used unless a property changed
147 // signal message is received for this property.
148 }
149 catch (const util::DBusError&)
Matthew Barth336f18a2017-09-26 09:15:56 -0500150 {
151 // Property will not be used unless a property changed
152 // signal message is received for this property.
Matthew Barth336f18a2017-09-26 09:15:56 -0500153 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500154 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500155 }
156
Matthew Barth926df662018-10-09 09:51:12 -0500157 /** @brief Run init handler function
158 *
159 * Get the property from each member object of the group
160 * and run the handler function.
161 */
162 void operator()(Zone& zone, const Group& group) const
163 {
164 std::for_each(
165 group.begin(),
166 group.end(),
167 [&zone, &group, handler = std::move(_handler)](auto const& member)
168 {
169 auto path = std::get<pathPos>(member);
170 auto intf = std::get<intfPos>(member);
171 auto prop = std::get<propPos>(member);
172 try
173 {
174 auto val = zone.getPropertyByName<T>(path, intf, prop);
175 handler(zone, std::forward<T>(val));
176 }
177 catch (const sdbusplus::exception::SdBusError&)
178 {
179 // Property value not sent to handler
180 }
181 catch (const util::DBusError&)
182 {
183 // Property value not sent to handler
184 }
185 }
186 );
187 }
188
Matthew Barth38a93a82017-05-11 14:12:27 -0500189private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500190 const char* _path;
Matthew Barth38a93a82017-05-11 14:12:27 -0500191 const char* _iface;
192 const char* _property;
193 U _handler;
194};
195
196/**
197 * @brief Used to process a Dbus property changed signal event
198 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500199 * @param[in] path - Object path
200 * @param[in] iface - Object interface
201 * @param[in] property - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500202 * @param[in] handler - Handler function to perform
203 *
204 * @tparam T - The type of the property
205 * @tparam U - The type of the handler
206 */
207template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500208auto propertiesChanged(const char* path,
209 const char* iface,
210 const char* property,
211 U&& handler)
Matthew Barth38a93a82017-05-11 14:12:27 -0500212{
Matthew Barth926df662018-10-09 09:51:12 -0500213 return Properties<T, U>(path,
214 iface,
215 property,
216 std::forward<U>(handler));
217}
218
219/**
220 * @brief Used to get the property value of an object
221 *
222 * @param[in] handler - Handler function to perform
223 *
224 * @tparam T - The type of the property
225 * @tparam U - The type of the handler
226 */
227template <typename T, typename U>
228auto getProperty(U&& handler)
229{
230 return Properties<T, U>(std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500231}
232
Matthew Bartheb639c52017-08-04 09:43:11 -0500233/**
234 * @struct Interface Added
235 * @brief A match filter functor for Dbus interface added signals
236 *
237 * @tparam T - The type of the property value
238 * @tparam U - The type of the handler
239 */
240template <typename T, typename U>
241struct InterfaceAdded
242{
243 InterfaceAdded() = delete;
244 ~InterfaceAdded() = default;
245 InterfaceAdded(const InterfaceAdded&) = default;
246 InterfaceAdded& operator=(const InterfaceAdded&) = default;
247 InterfaceAdded(InterfaceAdded&&) = default;
248 InterfaceAdded& operator=(InterfaceAdded&&) = default;
249 InterfaceAdded(const char* path,
250 const char* iface,
251 const char* property,
252 U&& handler) :
253 _path(path),
254 _iface(iface),
255 _property(property),
256 _handler(std::forward<U>(handler)) { }
257
258 /** @brief Run signal handler function
259 *
260 * Extract the property from the InterfacesAdded
261 * message and run the handler function.
262 */
263 void operator()(sdbusplus::bus::bus&,
264 sdbusplus::message::message& msg,
265 Zone& zone) const
266 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500267 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500268 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500269 std::map<std::string,
270 std::map<std::string,
271 sdbusplus::message::variant<T>>> intfProp;
272 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500273
Matthew Barth336f18a2017-09-26 09:15:56 -0500274 msg.read(op);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600275 if (static_cast<const std::string&>(op) != _path)
Matthew Barth336f18a2017-09-26 09:15:56 -0500276 {
277 // Object path does not match this handler's path
278 return;
279 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500280
Matthew Barth336f18a2017-09-26 09:15:56 -0500281 msg.read(intfProp);
282 auto itIntf = intfProp.find(_iface);
283 if (itIntf == intfProp.cend())
284 {
285 // Interface not found on this handler's path
286 return;
287 }
288 auto itProp = itIntf->second.find(_property);
289 if (itProp == itIntf->second.cend())
290 {
291 // Property not found on this handler's path
292 return;
293 }
294
William A. Kennington III4978e062018-11-27 11:47:12 -0800295 _handler(zone, std::forward<T>(
296 sdbusplus::message::variant_ns::get<T>(itProp->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500297 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500298 }
299
300private:
301 const char* _path;
302 const char* _iface;
303 const char* _property;
304 U _handler;
305};
306
307/**
Matthew Barth926df662018-10-09 09:51:12 -0500308 * @brief Used to process a Dbus interfaces added signal event
Matthew Bartheb639c52017-08-04 09:43:11 -0500309 *
310 * @param[in] path - Object path
311 * @param[in] iface - Object interface
312 * @param[in] property - Object property
313 * @param[in] handler - Handler function to perform
314 *
315 * @tparam T - The type of the property
316 * @tparam U - The type of the handler
317 */
318template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500319auto interfacesAdded(const char* path,
320 const char* iface,
321 const char* property,
322 U&& handler)
Matthew Bartheb639c52017-08-04 09:43:11 -0500323{
324 return InterfaceAdded<T, U>(path,
325 iface,
326 property,
327 std::forward<U>(handler));
328}
329
Matthew Barth8fa02da2017-09-28 12:18:20 -0500330/**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500331 * @struct Interface Removed
332 * @brief A match filter functor for Dbus interface removed signals
333 *
334 * @tparam U - The type of the handler
335 */
336template <typename U>
337struct InterfaceRemoved
338{
339 InterfaceRemoved() = delete;
340 ~InterfaceRemoved() = default;
341 InterfaceRemoved(const InterfaceRemoved&) = default;
342 InterfaceRemoved& operator=(const InterfaceRemoved&) = default;
343 InterfaceRemoved(InterfaceRemoved&&) = default;
344 InterfaceRemoved& operator=(InterfaceRemoved&&) = default;
345 InterfaceRemoved(const char* path,
346 const char* iface,
347 U&& handler) :
348 _path(path),
349 _iface(iface),
350 _handler(std::forward<U>(handler)) { }
351
352 /** @brief Run signal handler function
353 *
354 * Extract the property from the InterfacesRemoved
355 * message and run the handler function.
356 */
357 void operator()(sdbusplus::bus::bus&,
358 sdbusplus::message::message& msg,
359 Zone& zone) const
360 {
361 if (msg)
362 {
363 std::vector<std::string> intfs;
364 sdbusplus::message::object_path op;
365
366 msg.read(op);
367 if (static_cast<const std::string&>(op) != _path)
368 {
369 // Object path does not match this handler's path
370 return;
371 }
372
373 msg.read(intfs);
374 auto itIntf = std::find(intfs.begin(), intfs.end(), _iface);
375 if (itIntf == intfs.cend())
376 {
377 // Interface not found on this handler's path
378 return;
379 }
380
381 _handler(zone);
382 }
383 }
384
385private:
386 const char* _path;
387 const char* _iface;
388 U _handler;
389};
390
391/**
Matthew Barth926df662018-10-09 09:51:12 -0500392 * @brief Used to process a Dbus interfaces removed signal event
Matthew Barth1499a5c2018-03-20 15:52:33 -0500393 *
394 * @param[in] path - Object path
395 * @param[in] iface - Object interface
396 * @param[in] handler - Handler function to perform
397 *
398 * @tparam U - The type of the handler
399 */
400template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500401auto interfacesRemoved(const char* path,
402 const char* iface,
403 U&& handler)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500404{
405 return InterfaceRemoved<U>(path,
406 iface,
407 std::forward<U>(handler));
408}
409
410/**
Matthew Barth926df662018-10-09 09:51:12 -0500411 * @struct Name Owner
412 * @brief A functor for Dbus name owner signals and methods
Matthew Barth8fa02da2017-09-28 12:18:20 -0500413 *
414 * @tparam U - The type of the handler
415 */
416template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500417struct NameOwner
Matthew Barth8fa02da2017-09-28 12:18:20 -0500418{
Matthew Barth926df662018-10-09 09:51:12 -0500419 NameOwner() = delete;
420 ~NameOwner() = default;
421 NameOwner(const NameOwner&) = default;
422 NameOwner& operator=(const NameOwner&) = default;
423 NameOwner(NameOwner&&) = default;
424 NameOwner& operator=(NameOwner&&) = default;
425 explicit NameOwner(U&& handler) :
Matthew Barth8fa02da2017-09-28 12:18:20 -0500426 _handler(std::forward<U>(handler)) { }
427
428 /** @brief Run signal handler function
429 *
430 * Extract the name owner from the NameOwnerChanged
Matthew Barth926df662018-10-09 09:51:12 -0500431 * message and run the handler function.
Matthew Barth8fa02da2017-09-28 12:18:20 -0500432 */
433 void operator()(sdbusplus::bus::bus& bus,
434 sdbusplus::message::message& msg,
435 Zone& zone) const
436 {
Matthew Barth5a302572017-10-03 11:27:06 -0500437 std::string name;
438 bool hasOwner = false;
Matthew Barth8fa02da2017-09-28 12:18:20 -0500439 if (msg)
440 {
Matthew Barth5a302572017-10-03 11:27:06 -0500441 // Handle NameOwnerChanged signals
442 msg.read(name);
443
444 std::string oldOwn;
445 msg.read(oldOwn);
446
447 std::string newOwn;
448 msg.read(newOwn);
449 if (!newOwn.empty())
450 {
451 hasOwner = true;
452 }
Matthew Barth926df662018-10-09 09:51:12 -0500453 _handler(zone, name, hasOwner);
Matthew Barth8fa02da2017-09-28 12:18:20 -0500454 }
Matthew Barth926df662018-10-09 09:51:12 -0500455 }
Matthew Barth5a302572017-10-03 11:27:06 -0500456
Matthew Barth926df662018-10-09 09:51:12 -0500457 void operator()(Zone& zone,
458 const Group& group) const
459 {
460 std::string name = "";
461 bool hasOwner = false;
462 std::for_each(
463 group.begin(),
464 group.end(),
465 [&zone, &group, &name, &hasOwner, handler = std::move(_handler)](
466 auto const& member)
467 {
468 auto path = std::get<pathPos>(member);
469 auto intf = std::get<intfPos>(member);
470 try
471 {
472 auto servName = zone.getService(path, intf);
473 if (name != servName)
474 {
475 name = servName;
476 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
477 zone.getBus(),
478 "org.freedesktop.DBus",
479 "/org/freedesktop/DBus",
480 "org.freedesktop.DBus",
481 "NameHasOwner",
482 name);
483 // Update service name owner state list of a group
484 handler(zone, name, hasOwner);
485 }
486 }
487 catch (const util::DBusMethodError& e)
488 {
489 // Failed to get service name owner state
490 name = "";
491 hasOwner = false;
492 }
493
494 }
495 );
Matthew Barth8fa02da2017-09-28 12:18:20 -0500496 }
497
498private:
Matthew Barth8fa02da2017-09-28 12:18:20 -0500499 U _handler;
500};
501
502/**
503 * @brief Used to process a Dbus name owner changed signal event
504 *
Matthew Barth8fa02da2017-09-28 12:18:20 -0500505 * @param[in] handler - Handler function to perform
506 *
507 * @tparam U - The type of the handler
508 *
509 * @return - The NameOwnerChanged signal struct
510 */
511template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500512auto nameOwnerChanged(U&& handler)
Matthew Barth8fa02da2017-09-28 12:18:20 -0500513{
Matthew Barth926df662018-10-09 09:51:12 -0500514 return NameOwner<U>(std::forward<U>(handler));
515}
516
517/**
518 * @brief Used to process the init of a name owner event
519 *
520 * @param[in] handler - Handler function to perform
521 *
522 * @tparam U - The type of the handler
523 *
524 * @return - The NameOwnerChanged signal struct
525 */
526template <typename U>
527auto nameHasOwner(U&& handler)
528{
529 return NameOwner<U>(std::forward<U>(handler));
Matthew Barth8fa02da2017-09-28 12:18:20 -0500530}
531
Matthew Barth38a93a82017-05-11 14:12:27 -0500532} // namespace control
533} // namespace fan
534} // namespace phosphor