blob: 46da0b3338c48f5dece29341f1644bbb5ef30369 [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;
112 std::map<std::string, sdbusplus::message::variant<T>> props;
Matthew Barth38a93a82017-05-11 14:12:27 -0500113
Matthew Barth469d1362018-10-11 14:10:47 -0500114 msg.read(intf);
115 if (intf != _intf)
Matthew Barth336f18a2017-09-26 09:15:56 -0500116 {
Matthew Barth469d1362018-10-11 14:10:47 -0500117 // Interface name does not match on object
Matthew Barth336f18a2017-09-26 09:15:56 -0500118 return;
119 }
120
Matthew Barth469d1362018-10-11 14:10:47 -0500121 msg.read(props);
122 auto it = props.find(_prop);
123 if (it == props.cend())
Matthew Barth336f18a2017-09-26 09:15:56 -0500124 {
Matthew Barth469d1362018-10-11 14:10:47 -0500125 // Property not included in dictionary of properties changed
Matthew Barth336f18a2017-09-26 09:15:56 -0500126 return;
127 }
128
Matthew Barth469d1362018-10-11 14:10:47 -0500129 _handler(zone, _path, _intf, _prop, std::forward<T>(
130 sdbusplus::message::variant_ns::get<T>(it->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500131 }
132 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500133 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500134 try
135 {
Matthew Barth469d1362018-10-11 14:10:47 -0500136 auto val = zone.getPropertyByName<T>(_path, _intf, _prop);
137 _handler(zone, _path, _intf, _prop, std::forward<T>(val));
Matthew Barth336f18a2017-09-26 09:15:56 -0500138 }
Matthew Barth86be4762018-07-17 10:51:36 -0500139 catch (const sdbusplus::exception::SdBusError&)
140 {
141 // Property will not be used unless a property changed
142 // signal message is received for this property.
143 }
144 catch (const util::DBusError&)
Matthew Barth336f18a2017-09-26 09:15:56 -0500145 {
146 // Property will not be used unless a property changed
147 // signal message is received for this property.
Matthew Barth336f18a2017-09-26 09:15:56 -0500148 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500149 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500150 }
151
Matthew Barth926df662018-10-09 09:51:12 -0500152 /** @brief Run init handler function
153 *
154 * Get the property from each member object of the group
155 * and run the handler function.
156 */
157 void operator()(Zone& zone, const Group& group) const
158 {
159 std::for_each(
160 group.begin(),
161 group.end(),
Matthew Barth469d1362018-10-11 14:10:47 -0500162 [&zone, handler = std::move(_handler)](auto const& member)
Matthew Barth926df662018-10-09 09:51:12 -0500163 {
164 auto path = std::get<pathPos>(member);
165 auto intf = std::get<intfPos>(member);
166 auto prop = std::get<propPos>(member);
167 try
168 {
169 auto val = zone.getPropertyByName<T>(path, intf, prop);
Matthew Barth469d1362018-10-11 14:10:47 -0500170 handler(zone, path, intf, prop, std::forward<T>(val));
Matthew Barth926df662018-10-09 09:51:12 -0500171 }
172 catch (const sdbusplus::exception::SdBusError&)
173 {
174 // Property value not sent to handler
175 }
176 catch (const util::DBusError&)
177 {
178 // Property value not sent to handler
179 }
180 }
181 );
182 }
183
Matthew Barth38a93a82017-05-11 14:12:27 -0500184private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500185 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500186 const char* _intf;
187 const char* _prop;
Matthew Barth38a93a82017-05-11 14:12:27 -0500188 U _handler;
189};
190
191/**
Matthew Barth469d1362018-10-11 14:10:47 -0500192 * @brief Used to process a Dbus properties changed signal event
Matthew Barth38a93a82017-05-11 14:12:27 -0500193 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500194 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500195 * @param[in] intf - Object interface
196 * @param[in] prop - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500197 * @param[in] handler - Handler function to perform
198 *
199 * @tparam T - The type of the property
200 * @tparam U - The type of the handler
201 */
202template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500203auto propertiesChanged(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500204 const char* intf,
205 const char* prop,
Matthew Barth926df662018-10-09 09:51:12 -0500206 U&& handler)
Matthew Barth38a93a82017-05-11 14:12:27 -0500207{
Matthew Barth926df662018-10-09 09:51:12 -0500208 return Properties<T, U>(path,
Matthew Barth469d1362018-10-11 14:10:47 -0500209 intf,
210 prop,
Matthew Barth926df662018-10-09 09:51:12 -0500211 std::forward<U>(handler));
212}
213
214/**
Matthew Barth469d1362018-10-11 14:10:47 -0500215 * @brief Used to get the properties of an event's group
Matthew Barth926df662018-10-09 09:51:12 -0500216 *
217 * @param[in] handler - Handler function to perform
218 *
Matthew Barth469d1362018-10-11 14:10:47 -0500219 * @tparam T - The type of all the properties
Matthew Barth926df662018-10-09 09:51:12 -0500220 * @tparam U - The type of the handler
221 */
222template <typename T, typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500223auto getProperties(U&& handler)
Matthew Barth926df662018-10-09 09:51:12 -0500224{
225 return Properties<T, U>(std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500226}
227
Matthew Bartheb639c52017-08-04 09:43:11 -0500228/**
Matthew Barth469d1362018-10-11 14:10:47 -0500229 * @struct Interfaces Added
230 * @brief A match filter functor for Dbus interfaces added signals
Matthew Bartheb639c52017-08-04 09:43:11 -0500231 *
232 * @tparam T - The type of the property value
233 * @tparam U - The type of the handler
234 */
235template <typename T, typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500236struct InterfacesAdded
Matthew Bartheb639c52017-08-04 09:43:11 -0500237{
Matthew Barth469d1362018-10-11 14:10:47 -0500238 InterfacesAdded() = delete;
239 ~InterfacesAdded() = default;
240 InterfacesAdded(const InterfacesAdded&) = default;
241 InterfacesAdded& operator=(const InterfacesAdded&) = default;
242 InterfacesAdded(InterfacesAdded&&) = default;
243 InterfacesAdded& operator=(InterfacesAdded&&) = default;
244 InterfacesAdded(const char* path,
245 const char* intf,
246 const char* prop,
247 U&& handler) :
Matthew Bartheb639c52017-08-04 09:43:11 -0500248 _path(path),
Matthew Barth469d1362018-10-11 14:10:47 -0500249 _intf(intf),
250 _prop(prop),
Matthew Bartheb639c52017-08-04 09:43:11 -0500251 _handler(std::forward<U>(handler)) { }
252
253 /** @brief Run signal handler function
254 *
255 * Extract the property from the InterfacesAdded
256 * message and run the handler function.
257 */
258 void operator()(sdbusplus::bus::bus&,
259 sdbusplus::message::message& msg,
260 Zone& zone) const
261 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500262 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500263 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500264 std::map<std::string,
265 std::map<std::string,
266 sdbusplus::message::variant<T>>> intfProp;
267 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500268
Matthew Barth336f18a2017-09-26 09:15:56 -0500269 msg.read(op);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600270 if (static_cast<const std::string&>(op) != _path)
Matthew Barth336f18a2017-09-26 09:15:56 -0500271 {
272 // Object path does not match this handler's path
273 return;
274 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500275
Matthew Barth336f18a2017-09-26 09:15:56 -0500276 msg.read(intfProp);
Matthew Barth469d1362018-10-11 14:10:47 -0500277 auto itIntf = intfProp.find(_intf);
Matthew Barth336f18a2017-09-26 09:15:56 -0500278 if (itIntf == intfProp.cend())
279 {
280 // Interface not found on this handler's path
281 return;
282 }
Matthew Barth469d1362018-10-11 14:10:47 -0500283 auto itProp = itIntf->second.find(_prop);
Matthew Barth336f18a2017-09-26 09:15:56 -0500284 if (itProp == itIntf->second.cend())
285 {
286 // Property not found on this handler's path
287 return;
288 }
289
Matthew Barth469d1362018-10-11 14:10:47 -0500290 _handler(zone, _path, _intf, _prop, std::forward<T>(
291 sdbusplus::message::variant_ns::get<T>(itProp->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500292 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500293 }
294
295private:
296 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500297 const char* _intf;
298 const char* _prop;
Matthew Bartheb639c52017-08-04 09:43:11 -0500299 U _handler;
300};
301
302/**
Matthew Barth926df662018-10-09 09:51:12 -0500303 * @brief Used to process a Dbus interfaces added signal event
Matthew Bartheb639c52017-08-04 09:43:11 -0500304 *
305 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500306 * @param[in] intf - Object interface
307 * @param[in] prop - Object property
Matthew Bartheb639c52017-08-04 09:43:11 -0500308 * @param[in] handler - Handler function to perform
309 *
310 * @tparam T - The type of the property
311 * @tparam U - The type of the handler
312 */
313template <typename T, typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500314auto interfacesAdded(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500315 const char* intf,
316 const char* prop,
Matthew Barth926df662018-10-09 09:51:12 -0500317 U&& handler)
Matthew Bartheb639c52017-08-04 09:43:11 -0500318{
Matthew Barth469d1362018-10-11 14:10:47 -0500319 return InterfacesAdded<T, U>(path,
320 intf,
321 prop,
322 std::forward<U>(handler));
Matthew Bartheb639c52017-08-04 09:43:11 -0500323}
324
Matthew Barth8fa02da2017-09-28 12:18:20 -0500325/**
Matthew Barth469d1362018-10-11 14:10:47 -0500326 * @struct Interfaces Removed
327 * @brief A match filter functor for Dbus interfaces removed signals
Matthew Barth1499a5c2018-03-20 15:52:33 -0500328 *
329 * @tparam U - The type of the handler
330 */
331template <typename U>
Matthew Barth469d1362018-10-11 14:10:47 -0500332struct InterfacesRemoved
Matthew Barth1499a5c2018-03-20 15:52:33 -0500333{
Matthew Barth469d1362018-10-11 14:10:47 -0500334 InterfacesRemoved() = delete;
335 ~InterfacesRemoved() = default;
336 InterfacesRemoved(const InterfacesRemoved&) = default;
337 InterfacesRemoved& operator=(const InterfacesRemoved&) = default;
338 InterfacesRemoved(InterfacesRemoved&&) = default;
339 InterfacesRemoved& operator=(InterfacesRemoved&&) = default;
340 InterfacesRemoved(const char* path,
341 const char* intf,
342 U&& handler) :
Matthew Barth1499a5c2018-03-20 15:52:33 -0500343 _path(path),
Matthew Barth469d1362018-10-11 14:10:47 -0500344 _intf(intf),
Matthew Barth1499a5c2018-03-20 15:52:33 -0500345 _handler(std::forward<U>(handler)) { }
346
347 /** @brief Run signal handler function
348 *
Matthew Barth469d1362018-10-11 14:10:47 -0500349 * Extract the interfaces from the InterfacesRemoved
Matthew Barth1499a5c2018-03-20 15:52:33 -0500350 * message and run the handler function.
351 */
352 void operator()(sdbusplus::bus::bus&,
353 sdbusplus::message::message& msg,
354 Zone& zone) const
355 {
356 if (msg)
357 {
358 std::vector<std::string> intfs;
359 sdbusplus::message::object_path op;
360
361 msg.read(op);
362 if (static_cast<const std::string&>(op) != _path)
363 {
364 // Object path does not match this handler's path
365 return;
366 }
367
368 msg.read(intfs);
Matthew Barth469d1362018-10-11 14:10:47 -0500369 auto itIntf = std::find(intfs.begin(), intfs.end(), _intf);
Matthew Barth1499a5c2018-03-20 15:52:33 -0500370 if (itIntf == intfs.cend())
371 {
372 // Interface not found on this handler's path
373 return;
374 }
375
376 _handler(zone);
377 }
378 }
379
380private:
381 const char* _path;
Matthew Barth469d1362018-10-11 14:10:47 -0500382 const char* _intf;
Matthew Barth1499a5c2018-03-20 15:52:33 -0500383 U _handler;
384};
385
386/**
Matthew Barth926df662018-10-09 09:51:12 -0500387 * @brief Used to process a Dbus interfaces removed signal event
Matthew Barth1499a5c2018-03-20 15:52:33 -0500388 *
389 * @param[in] path - Object path
Matthew Barth469d1362018-10-11 14:10:47 -0500390 * @param[in] intf - Object interface
Matthew Barth1499a5c2018-03-20 15:52:33 -0500391 * @param[in] handler - Handler function to perform
392 *
393 * @tparam U - The type of the handler
394 */
395template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500396auto interfacesRemoved(const char* path,
Matthew Barth469d1362018-10-11 14:10:47 -0500397 const char* intf,
Matthew Barth926df662018-10-09 09:51:12 -0500398 U&& handler)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500399{
Matthew Barth469d1362018-10-11 14:10:47 -0500400 return InterfacesRemoved<U>(path,
401 intf,
402 std::forward<U>(handler));
Matthew Barth1499a5c2018-03-20 15:52:33 -0500403}
404
405/**
Matthew Barth926df662018-10-09 09:51:12 -0500406 * @struct Name Owner
407 * @brief A functor for Dbus name owner signals and methods
Matthew Barth8fa02da2017-09-28 12:18:20 -0500408 *
409 * @tparam U - The type of the handler
410 */
411template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500412struct NameOwner
Matthew Barth8fa02da2017-09-28 12:18:20 -0500413{
Matthew Barth926df662018-10-09 09:51:12 -0500414 NameOwner() = delete;
415 ~NameOwner() = default;
416 NameOwner(const NameOwner&) = default;
417 NameOwner& operator=(const NameOwner&) = default;
418 NameOwner(NameOwner&&) = default;
419 NameOwner& operator=(NameOwner&&) = default;
420 explicit NameOwner(U&& handler) :
Matthew Barth8fa02da2017-09-28 12:18:20 -0500421 _handler(std::forward<U>(handler)) { }
422
423 /** @brief Run signal handler function
424 *
425 * Extract the name owner from the NameOwnerChanged
Matthew Barth926df662018-10-09 09:51:12 -0500426 * message and run the handler function.
Matthew Barth8fa02da2017-09-28 12:18:20 -0500427 */
428 void operator()(sdbusplus::bus::bus& bus,
429 sdbusplus::message::message& msg,
430 Zone& zone) const
431 {
Matthew Barth5a302572017-10-03 11:27:06 -0500432 std::string name;
433 bool hasOwner = false;
Matthew Barth8fa02da2017-09-28 12:18:20 -0500434 if (msg)
435 {
Matthew Barth5a302572017-10-03 11:27:06 -0500436 // Handle NameOwnerChanged signals
437 msg.read(name);
438
439 std::string oldOwn;
440 msg.read(oldOwn);
441
442 std::string newOwn;
443 msg.read(newOwn);
444 if (!newOwn.empty())
445 {
446 hasOwner = true;
447 }
Matthew Barth926df662018-10-09 09:51:12 -0500448 _handler(zone, name, hasOwner);
Matthew Barth8fa02da2017-09-28 12:18:20 -0500449 }
Matthew Barth926df662018-10-09 09:51:12 -0500450 }
Matthew Barth5a302572017-10-03 11:27:06 -0500451
Matthew Barth926df662018-10-09 09:51:12 -0500452 void operator()(Zone& zone,
453 const Group& group) const
454 {
455 std::string name = "";
456 bool hasOwner = false;
457 std::for_each(
458 group.begin(),
459 group.end(),
460 [&zone, &group, &name, &hasOwner, handler = std::move(_handler)](
461 auto const& member)
462 {
463 auto path = std::get<pathPos>(member);
464 auto intf = std::get<intfPos>(member);
465 try
466 {
467 auto servName = zone.getService(path, intf);
468 if (name != servName)
469 {
470 name = servName;
471 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
472 zone.getBus(),
473 "org.freedesktop.DBus",
474 "/org/freedesktop/DBus",
475 "org.freedesktop.DBus",
476 "NameHasOwner",
477 name);
478 // Update service name owner state list of a group
479 handler(zone, name, hasOwner);
480 }
481 }
482 catch (const util::DBusMethodError& e)
483 {
484 // Failed to get service name owner state
485 name = "";
486 hasOwner = false;
487 }
Matthew Barth926df662018-10-09 09:51:12 -0500488 }
489 );
Matthew Barth8fa02da2017-09-28 12:18:20 -0500490 }
491
492private:
Matthew Barth8fa02da2017-09-28 12:18:20 -0500493 U _handler;
494};
495
496/**
497 * @brief Used to process a Dbus name owner changed signal event
498 *
Matthew Barth8fa02da2017-09-28 12:18:20 -0500499 * @param[in] handler - Handler function to perform
500 *
501 * @tparam U - The type of the handler
502 *
503 * @return - The NameOwnerChanged signal struct
504 */
505template <typename U>
Matthew Barth926df662018-10-09 09:51:12 -0500506auto nameOwnerChanged(U&& handler)
Matthew Barth8fa02da2017-09-28 12:18:20 -0500507{
Matthew Barth926df662018-10-09 09:51:12 -0500508 return NameOwner<U>(std::forward<U>(handler));
509}
510
511/**
512 * @brief Used to process the init of a name owner event
513 *
514 * @param[in] handler - Handler function to perform
515 *
516 * @tparam U - The type of the handler
517 *
518 * @return - The NameOwnerChanged signal struct
519 */
520template <typename U>
521auto nameHasOwner(U&& handler)
522{
523 return NameOwner<U>(std::forward<U>(handler));
Matthew Barth8fa02da2017-09-28 12:18:20 -0500524}
525
Matthew Barth38a93a82017-05-11 14:12:27 -0500526} // namespace control
527} // namespace fan
528} // namespace phosphor