blob: 6251ce8e10cf15e0722a4622cf763b30e2e24cc0 [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) :
Matthew Barth926df662018-10-09 09:51:12 -050090 _handler(std::forward<U>(handler)) { }
91 Properties(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -050092 const char* intf,
93 const char* prop,
Matthew Barth926df662018-10-09 09:51:12 -050094 U&& handler) :
Matthew Barth336f18a2017-09-26 09:15:56 -050095 _path(path),
Matthew Barth469d1362018-10-11 14:10:47 -050096 _intf(intf),
97 _prop(prop),
Matthew Barth38a93a82017-05-11 14:12:27 -050098 _handler(std::forward<U>(handler)) { }
99
100 /** @brief Run signal handler function
101 *
102 * Extract the property from the PropertiesChanged
Matthew Barth926df662018-10-09 09:51:12 -0500103 * message and run the handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -0500104 */
Matthew Barth336f18a2017-09-26 09:15:56 -0500105 void operator()(sdbusplus::bus::bus& bus,
Matthew Barth38a93a82017-05-11 14:12:27 -0500106 sdbusplus::message::message& msg,
107 Zone& zone) const
108 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500109 if (msg)
Matthew Barth38a93a82017-05-11 14:12:27 -0500110 {
Matthew Barth469d1362018-10-11 14:10:47 -0500111 std::string intf;
Matthew Barth469d1362018-10-11 14:10:47 -0500112 msg.read(intf);
113 if (intf != _intf)
Matthew Barth336f18a2017-09-26 09:15:56 -0500114 {
Matthew Barth469d1362018-10-11 14:10:47 -0500115 // Interface name does not match on object
Matthew Barth336f18a2017-09-26 09:15:56 -0500116 return;
117 }
118
Matthew Barth7f4c5482020-02-07 16:14:46 -0600119 std::map<std::string, PropertyVariantType> props;
Matthew Barth469d1362018-10-11 14:10:47 -0500120 msg.read(props);
121 auto it = props.find(_prop);
122 if (it == props.cend())
Matthew Barth336f18a2017-09-26 09:15:56 -0500123 {
Matthew Barth469d1362018-10-11 14:10:47 -0500124 // Property not included in dictionary of properties changed
Matthew Barth336f18a2017-09-26 09:15:56 -0500125 return;
126 }
127
Matthew Barth7f4c5482020-02-07 16:14:46 -0600128 // Retrieve the property's value applying any visitors necessary
129 auto value =
130 zone.getPropertyValueVisitor<T>(_intf, _prop, it->second);
131
132 _handler(zone, _path, _intf, _prop, std::forward<T>(value));
Matthew Barth336f18a2017-09-26 09:15:56 -0500133 }
134 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500135 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500136 try
137 {
Matthew Barth469d1362018-10-11 14:10:47 -0500138 auto val = zone.getPropertyByName<T>(_path, _intf, _prop);
139 _handler(zone, _path, _intf, _prop, std::forward<T>(val));
Matthew Barth336f18a2017-09-26 09:15:56 -0500140 }
Matthew Barth86be4762018-07-17 10:51:36 -0500141 catch (const sdbusplus::exception::SdBusError&)
142 {
143 // Property will not be used unless a property changed
144 // signal message is received for this property.
145 }
146 catch (const util::DBusError&)
Matthew Barth336f18a2017-09-26 09:15:56 -0500147 {
148 // Property will not be used unless a property changed
149 // signal message is received for this property.
Matthew Barth336f18a2017-09-26 09:15:56 -0500150 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500151 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500152 }
153
Matthew Barth926df662018-10-09 09:51:12 -0500154 /** @brief Run init handler function
155 *
156 * Get the property from each member object of the group
157 * and run the handler function.
158 */
159 void operator()(Zone& zone, const Group& group) const
160 {
161 std::for_each(
162 group.begin(),
163 group.end(),
Matthew Barth469d1362018-10-11 14:10:47 -0500164 [&zone, handler = std::move(_handler)](auto const& member)
Matthew Barth926df662018-10-09 09:51:12 -0500165 {
166 auto path = std::get<pathPos>(member);
167 auto intf = std::get<intfPos>(member);
168 auto prop = std::get<propPos>(member);
169 try
170 {
171 auto val = zone.getPropertyByName<T>(path, intf, prop);
Matthew Barth469d1362018-10-11 14:10:47 -0500172 handler(zone, path, intf, prop, std::forward<T>(val));
Matthew Barth926df662018-10-09 09:51:12 -0500173 }
174 catch (const sdbusplus::exception::SdBusError&)
175 {
176 // Property value not sent to handler
177 }
178 catch (const util::DBusError&)
179 {
180 // Property value not sent to handler
181 }
182 }
183 );
184 }
185
Matthew Barth38a93a82017-05-11 14:12:27 -0500186private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500187 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500188 const char* _intf;
189 const char* _prop;
Matthew Barth38a93a82017-05-11 14:12:27 -0500190 U _handler;
191};
192
193/**
Matthew Barth469d1362018-10-11 14:10:47 -0500194 * @brief Used to process a Dbus properties changed signal event
Matthew Barth38a93a82017-05-11 14:12:27 -0500195 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500196 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500197 * @param[in] intf - Object interface
198 * @param[in] prop - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500199 * @param[in] handler - Handler function to perform
200 *
201 * @tparam T - The type of the property
202 * @tparam U - The type of the handler
203 */
204template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500205auto propertiesChanged(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500206 const char* intf,
207 const char* prop,
Matthew Barth926df662018-10-09 09:51:12 -0500208 U&& handler)
Matthew Barth38a93a82017-05-11 14:12:27 -0500209{
Matthew Barth926df662018-10-09 09:51:12 -0500210 return Properties<T, U>(path,
Matthew Barth469d1362018-10-11 14:10:47 -0500211 intf,
212 prop,
Matthew Barth926df662018-10-09 09:51:12 -0500213 std::forward<U>(handler));
214}
215
216/**
Matthew Barth469d1362018-10-11 14:10:47 -0500217 * @brief Used to get the properties of an event's group
Matthew Barth926df662018-10-09 09:51:12 -0500218 *
219 * @param[in] handler - Handler function to perform
220 *
Matthew Barth469d1362018-10-11 14:10:47 -0500221 * @tparam T - The type of all the properties
Matthew Barth926df662018-10-09 09:51:12 -0500222 * @tparam U - The type of the handler
223 */
224template <typename T, typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500225auto getProperties(U&& handler)
Matthew Barth926df662018-10-09 09:51:12 -0500226{
227 return Properties<T, U>(std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500228}
229
Matthew Bartheb639c52017-08-04 09:43:11 -0500230/**
Matthew Barth469d1362018-10-11 14:10:47 -0500231 * @struct Interfaces Added
232 * @brief A match filter functor for Dbus interfaces added signals
Matthew Bartheb639c52017-08-04 09:43:11 -0500233 *
234 * @tparam T - The type of the property value
235 * @tparam U - The type of the handler
236 */
237template <typename T, typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500238struct InterfacesAdded
Matthew Bartheb639c52017-08-04 09:43:11 -0500239{
Matthew Barth469d1362018-10-11 14:10:47 -0500240 InterfacesAdded() = delete;
241 ~InterfacesAdded() = default;
242 InterfacesAdded(const InterfacesAdded&) = default;
243 InterfacesAdded& operator=(const InterfacesAdded&) = default;
244 InterfacesAdded(InterfacesAdded&&) = default;
245 InterfacesAdded& operator=(InterfacesAdded&&) = default;
246 InterfacesAdded(const char* path,
247 const char* intf,
248 const char* prop,
249 U&& handler) :
Matthew Bartheb639c52017-08-04 09:43:11 -0500250 _path(path),
Matthew Barth469d1362018-10-11 14:10:47 -0500251 _intf(intf),
252 _prop(prop),
Matthew Bartheb639c52017-08-04 09:43:11 -0500253 _handler(std::forward<U>(handler)) { }
254
255 /** @brief Run signal handler function
256 *
257 * Extract the property from the InterfacesAdded
258 * message and run the handler function.
259 */
260 void operator()(sdbusplus::bus::bus&,
261 sdbusplus::message::message& msg,
262 Zone& zone) const
263 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500264 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500265 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500266 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500267
Matthew Barth336f18a2017-09-26 09:15:56 -0500268 msg.read(op);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600269 if (static_cast<const std::string&>(op) != _path)
Matthew Barth336f18a2017-09-26 09:15:56 -0500270 {
271 // Object path does not match this handler's path
272 return;
273 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500274
Matthew Barth7f4c5482020-02-07 16:14:46 -0600275 std::map<std::string, std::map<std::string,
276 PropertyVariantType>> intfProp;
Matthew Barth336f18a2017-09-26 09:15:56 -0500277 msg.read(intfProp);
Matthew Barth469d1362018-10-11 14:10:47 -0500278 auto itIntf = intfProp.find(_intf);
Matthew Barth336f18a2017-09-26 09:15:56 -0500279 if (itIntf == intfProp.cend())
280 {
281 // Interface not found on this handler's path
282 return;
283 }
Matthew Barth469d1362018-10-11 14:10:47 -0500284 auto itProp = itIntf->second.find(_prop);
Matthew Barth336f18a2017-09-26 09:15:56 -0500285 if (itProp == itIntf->second.cend())
286 {
287 // Property not found on this handler's path
288 return;
289 }
290
Matthew Barth7f4c5482020-02-07 16:14:46 -0600291 // Retrieve the property's value applying any visitors necessary
292 auto value =
293 zone.getPropertyValueVisitor<T>(_intf, _prop, itProp->second);
294
295 _handler(zone, _path, _intf, _prop, std::forward<T>(value));
Matthew Barth336f18a2017-09-26 09:15:56 -0500296 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500297 }
298
299private:
300 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500301 const char* _intf;
302 const char* _prop;
Matthew Bartheb639c52017-08-04 09:43:11 -0500303 U _handler;
304};
305
306/**
Matthew Barth926df662018-10-09 09:51:12 -0500307 * @brief Used to process a Dbus interfaces added signal event
Matthew Bartheb639c52017-08-04 09:43:11 -0500308 *
309 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500310 * @param[in] intf - Object interface
311 * @param[in] prop - Object property
Matthew Bartheb639c52017-08-04 09:43:11 -0500312 * @param[in] handler - Handler function to perform
313 *
314 * @tparam T - The type of the property
315 * @tparam U - The type of the handler
316 */
317template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500318auto interfacesAdded(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500319 const char* intf,
320 const char* prop,
Matthew Barth926df662018-10-09 09:51:12 -0500321 U&& handler)
Matthew Bartheb639c52017-08-04 09:43:11 -0500322{
Matthew Barth469d1362018-10-11 14:10:47 -0500323 return InterfacesAdded<T, U>(path,
324 intf,
325 prop,
326 std::forward<U>(handler));
Matthew Bartheb639c52017-08-04 09:43:11 -0500327}
328
Matthew Barth8fa02da2017-09-28 12:18:20 -0500329/**
Matthew Barth469d1362018-10-11 14:10:47 -0500330 * @struct Interfaces Removed
331 * @brief A match filter functor for Dbus interfaces removed signals
Matthew Barth1499a5c2018-03-20 15:52:33 -0500332 *
333 * @tparam U - The type of the handler
334 */
335template <typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500336struct InterfacesRemoved
Matthew Barth1499a5c2018-03-20 15:52:33 -0500337{
Matthew Barth469d1362018-10-11 14:10:47 -0500338 InterfacesRemoved() = delete;
339 ~InterfacesRemoved() = default;
340 InterfacesRemoved(const InterfacesRemoved&) = default;
341 InterfacesRemoved& operator=(const InterfacesRemoved&) = default;
342 InterfacesRemoved(InterfacesRemoved&&) = default;
343 InterfacesRemoved& operator=(InterfacesRemoved&&) = default;
344 InterfacesRemoved(const char* path,
345 const char* intf,
346 U&& handler) :
Matthew Barth1499a5c2018-03-20 15:52:33 -0500347 _path(path),
Matthew Barth469d1362018-10-11 14:10:47 -0500348 _intf(intf),
Matthew Barth1499a5c2018-03-20 15:52:33 -0500349 _handler(std::forward<U>(handler)) { }
350
351 /** @brief Run signal handler function
352 *
Matthew Barth469d1362018-10-11 14:10:47 -0500353 * Extract the interfaces from the InterfacesRemoved
Matthew Barth1499a5c2018-03-20 15:52:33 -0500354 * message and run the handler function.
355 */
356 void operator()(sdbusplus::bus::bus&,
357 sdbusplus::message::message& msg,
358 Zone& zone) const
359 {
360 if (msg)
361 {
362 std::vector<std::string> intfs;
363 sdbusplus::message::object_path op;
364
365 msg.read(op);
366 if (static_cast<const std::string&>(op) != _path)
367 {
368 // Object path does not match this handler's path
369 return;
370 }
371
372 msg.read(intfs);
Matthew Barth469d1362018-10-11 14:10:47 -0500373 auto itIntf = std::find(intfs.begin(), intfs.end(), _intf);
Matthew Barth1499a5c2018-03-20 15:52:33 -0500374 if (itIntf == intfs.cend())
375 {
376 // Interface not found on this handler's path
377 return;
378 }
379
380 _handler(zone);
381 }
382 }
383
384private:
385 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500386 const char* _intf;
Matthew Barth1499a5c2018-03-20 15:52:33 -0500387 U _handler;
388};
389
390/**
Matthew Barth926df662018-10-09 09:51:12 -0500391 * @brief Used to process a Dbus interfaces removed signal event
Matthew Barth1499a5c2018-03-20 15:52:33 -0500392 *
393 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500394 * @param[in] intf - Object interface
Matthew Barth1499a5c2018-03-20 15:52:33 -0500395 * @param[in] handler - Handler function to perform
396 *
397 * @tparam U - The type of the handler
398 */
399template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500400auto interfacesRemoved(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500401 const char* intf,
Matthew Barth926df662018-10-09 09:51:12 -0500402 U&& handler)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500403{
Matthew Barth469d1362018-10-11 14:10:47 -0500404 return InterfacesRemoved<U>(path,
405 intf,
406 std::forward<U>(handler));
Matthew Barth1499a5c2018-03-20 15:52:33 -0500407}
408
409/**
Matthew Barth926df662018-10-09 09:51:12 -0500410 * @struct Name Owner
411 * @brief A functor for Dbus name owner signals and methods
Matthew Barth8fa02da2017-09-28 12:18:20 -0500412 *
413 * @tparam U - The type of the handler
414 */
415template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500416struct NameOwner
Matthew Barth8fa02da2017-09-28 12:18:20 -0500417{
Matthew Barth926df662018-10-09 09:51:12 -0500418 NameOwner() = delete;
419 ~NameOwner() = default;
420 NameOwner(const NameOwner&) = default;
421 NameOwner& operator=(const NameOwner&) = default;
422 NameOwner(NameOwner&&) = default;
423 NameOwner& operator=(NameOwner&&) = default;
424 explicit NameOwner(U&& handler) :
Matthew Barth8fa02da2017-09-28 12:18:20 -0500425 _handler(std::forward<U>(handler)) { }
426
427 /** @brief Run signal handler function
428 *
429 * Extract the name owner from the NameOwnerChanged
Matthew Barth926df662018-10-09 09:51:12 -0500430 * message and run the handler function.
Matthew Barth8fa02da2017-09-28 12:18:20 -0500431 */
432 void operator()(sdbusplus::bus::bus& bus,
433 sdbusplus::message::message& msg,
434 Zone& zone) const
435 {
Matthew Barth5a302572017-10-03 11:27:06 -0500436 std::string name;
437 bool hasOwner = false;
Matthew Barth8fa02da2017-09-28 12:18:20 -0500438 if (msg)
439 {
Matthew Barth5a302572017-10-03 11:27:06 -0500440 // Handle NameOwnerChanged signals
441 msg.read(name);
442
443 std::string oldOwn;
444 msg.read(oldOwn);
445
446 std::string newOwn;
447 msg.read(newOwn);
448 if (!newOwn.empty())
449 {
450 hasOwner = true;
451 }
Matthew Barth926df662018-10-09 09:51:12 -0500452 _handler(zone, name, hasOwner);
Matthew Barth8fa02da2017-09-28 12:18:20 -0500453 }
Matthew Barth926df662018-10-09 09:51:12 -0500454 }
Matthew Barth5a302572017-10-03 11:27:06 -0500455
Matthew Barth926df662018-10-09 09:51:12 -0500456 void operator()(Zone& zone,
457 const Group& group) const
458 {
459 std::string name = "";
460 bool hasOwner = false;
461 std::for_each(
462 group.begin(),
463 group.end(),
464 [&zone, &group, &name, &hasOwner, handler = std::move(_handler)](
465 auto const& member)
466 {
467 auto path = std::get<pathPos>(member);
468 auto intf = std::get<intfPos>(member);
469 try
470 {
471 auto servName = zone.getService(path, intf);
472 if (name != servName)
473 {
474 name = servName;
475 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
476 zone.getBus(),
477 "org.freedesktop.DBus",
478 "/org/freedesktop/DBus",
479 "org.freedesktop.DBus",
480 "NameHasOwner",
481 name);
482 // Update service name owner state list of a group
483 handler(zone, name, hasOwner);
484 }
485 }
486 catch (const util::DBusMethodError& e)
487 {
488 // Failed to get service name owner state
489 name = "";
490 hasOwner = false;
491 }
Matthew Barth926df662018-10-09 09:51:12 -0500492 }
493 );
Matthew Barth8fa02da2017-09-28 12:18:20 -0500494 }
495
496private:
Matthew Barth8fa02da2017-09-28 12:18:20 -0500497 U _handler;
498};
499
500/**
501 * @brief Used to process a Dbus name owner changed signal event
502 *
Matthew Barth8fa02da2017-09-28 12:18:20 -0500503 * @param[in] handler - Handler function to perform
504 *
505 * @tparam U - The type of the handler
506 *
507 * @return - The NameOwnerChanged signal struct
508 */
509template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500510auto nameOwnerChanged(U&& handler)
Matthew Barth8fa02da2017-09-28 12:18:20 -0500511{
Matthew Barth926df662018-10-09 09:51:12 -0500512 return NameOwner<U>(std::forward<U>(handler));
513}
514
515/**
516 * @brief Used to process the init of a name owner event
517 *
518 * @param[in] handler - Handler function to perform
519 *
520 * @tparam U - The type of the handler
521 *
522 * @return - The NameOwnerChanged signal struct
523 */
524template <typename U>
525auto nameHasOwner(U&& handler)
526{
527 return NameOwner<U>(std::forward<U>(handler));
Matthew Barth8fa02da2017-09-28 12:18:20 -0500528}
529
Matthew Barth38a93a82017-05-11 14:12:27 -0500530} // namespace control
531} // namespace fan
532} // namespace phosphor