blob: 77e95c8d223b0f8fef2519926ab5f7f9c8dda738 [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 */
52template <typename T>
53auto make_handler(T&& handler)
54{
55 return Handler(std::forward<T>(handler));
56}
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 Barth38a93a82017-05-11 14:12:27 -050072 * @struct Property Changed
73 * @brief A match filter functor for Dbus property value changed signals
74 *
75 * @tparam T - The type of the property value
76 * @tparam U - The type of the handler
77 */
78template <typename T, typename U>
79struct PropertyChanged
80{
81 PropertyChanged() = delete;
82 ~PropertyChanged() = default;
83 PropertyChanged(const PropertyChanged&) = default;
84 PropertyChanged& operator=(const PropertyChanged&) = default;
85 PropertyChanged(PropertyChanged&&) = default;
86 PropertyChanged& operator=(PropertyChanged&&) = default;
Matthew Barth336f18a2017-09-26 09:15:56 -050087 PropertyChanged(const char* path,
88 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -050089 const char* property,
90 U&& handler) :
Matthew Barth336f18a2017-09-26 09:15:56 -050091 _path(path),
Matthew Barth38a93a82017-05-11 14:12:27 -050092 _iface(iface),
93 _property(property),
94 _handler(std::forward<U>(handler)) { }
95
96 /** @brief Run signal handler function
97 *
98 * Extract the property from the PropertiesChanged
Matthew Barth336f18a2017-09-26 09:15:56 -050099 * message (or read the property when the message is null)
100 * and run the handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -0500101 */
Matthew Barth336f18a2017-09-26 09:15:56 -0500102 void operator()(sdbusplus::bus::bus& bus,
Matthew Barth38a93a82017-05-11 14:12:27 -0500103 sdbusplus::message::message& msg,
104 Zone& zone) const
105 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500106 if (msg)
Matthew Barth38a93a82017-05-11 14:12:27 -0500107 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500108 std::map<std::string, sdbusplus::message::variant<T>> properties;
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600109 std::string iface;
Matthew Barth38a93a82017-05-11 14:12:27 -0500110
Matthew Barth336f18a2017-09-26 09:15:56 -0500111 msg.read(iface);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600112 if (iface != _iface)
Matthew Barth336f18a2017-09-26 09:15:56 -0500113 {
114 return;
115 }
116
117 msg.read(properties);
118 auto it = properties.find(_property);
119 if (it == properties.cend())
120 {
121 log<level::ERR>("Unable to find property on interface",
122 entry("PROPERTY=%s", _property),
Matthew Barthe65f6172017-12-11 13:36:02 -0600123 entry("INTERFACE=%s", _iface),
124 entry("PATH=%s", _path));
Matthew Barth336f18a2017-09-26 09:15:56 -0500125 return;
126 }
127
William A. Kennington III4978e062018-11-27 11:47:12 -0800128 _handler(zone, std::forward<T>(
129 sdbusplus::message::variant_ns::get<T>(it->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500130 }
131 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500132 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500133 try
134 {
Matthew Barth766f8542019-01-29 12:44:13 -0600135 auto val = zone.getPropertyByName<T>(_path, _iface, _property);
Matthew Barth336f18a2017-09-26 09:15:56 -0500136 _handler(zone, std::forward<T>(val));
137 }
Matthew Barth86be4762018-07-17 10:51:36 -0500138 catch (const sdbusplus::exception::SdBusError&)
139 {
140 // Property will not be used unless a property changed
141 // signal message is received for this property.
142 }
143 catch (const util::DBusError&)
Matthew Barth336f18a2017-09-26 09:15:56 -0500144 {
145 // Property will not be used unless a property changed
146 // signal message is received for this property.
Matthew Barth336f18a2017-09-26 09:15:56 -0500147 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500148 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500149 }
150
151private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500152 const char* _path;
Matthew Barth38a93a82017-05-11 14:12:27 -0500153 const char* _iface;
154 const char* _property;
155 U _handler;
156};
157
158/**
159 * @brief Used to process a Dbus property changed signal event
160 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500161 * @param[in] path - Object path
162 * @param[in] iface - Object interface
163 * @param[in] property - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500164 * @param[in] handler - Handler function to perform
165 *
166 * @tparam T - The type of the property
167 * @tparam U - The type of the handler
168 */
169template <typename T, typename U>
Matthew Barth336f18a2017-09-26 09:15:56 -0500170auto propertySignal(const char* path,
171 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500172 const char* property,
173 U&& handler)
174{
Matthew Barth336f18a2017-09-26 09:15:56 -0500175 return PropertyChanged<T, U>(path,
176 iface,
177 property,
178 std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500179}
180
Matthew Bartheb639c52017-08-04 09:43:11 -0500181/**
182 * @struct Interface Added
183 * @brief A match filter functor for Dbus interface added signals
184 *
185 * @tparam T - The type of the property value
186 * @tparam U - The type of the handler
187 */
188template <typename T, typename U>
189struct InterfaceAdded
190{
191 InterfaceAdded() = delete;
192 ~InterfaceAdded() = default;
193 InterfaceAdded(const InterfaceAdded&) = default;
194 InterfaceAdded& operator=(const InterfaceAdded&) = default;
195 InterfaceAdded(InterfaceAdded&&) = default;
196 InterfaceAdded& operator=(InterfaceAdded&&) = default;
197 InterfaceAdded(const char* path,
198 const char* iface,
199 const char* property,
200 U&& handler) :
201 _path(path),
202 _iface(iface),
203 _property(property),
204 _handler(std::forward<U>(handler)) { }
205
206 /** @brief Run signal handler function
207 *
208 * Extract the property from the InterfacesAdded
209 * message and run the handler function.
210 */
211 void operator()(sdbusplus::bus::bus&,
212 sdbusplus::message::message& msg,
213 Zone& zone) const
214 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500215 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500216 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500217 std::map<std::string,
218 std::map<std::string,
219 sdbusplus::message::variant<T>>> intfProp;
220 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500221
Matthew Barth336f18a2017-09-26 09:15:56 -0500222 msg.read(op);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600223 if (static_cast<const std::string&>(op) != _path)
Matthew Barth336f18a2017-09-26 09:15:56 -0500224 {
225 // Object path does not match this handler's path
226 return;
227 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500228
Matthew Barth336f18a2017-09-26 09:15:56 -0500229 msg.read(intfProp);
230 auto itIntf = intfProp.find(_iface);
231 if (itIntf == intfProp.cend())
232 {
233 // Interface not found on this handler's path
234 return;
235 }
236 auto itProp = itIntf->second.find(_property);
237 if (itProp == itIntf->second.cend())
238 {
239 // Property not found on this handler's path
240 return;
241 }
242
William A. Kennington III4978e062018-11-27 11:47:12 -0800243 _handler(zone, std::forward<T>(
244 sdbusplus::message::variant_ns::get<T>(itProp->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500245 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500246 }
247
248private:
249 const char* _path;
250 const char* _iface;
251 const char* _property;
252 U _handler;
253};
254
255/**
256 * @brief Used to process a Dbus interface added signal event
257 *
258 * @param[in] path - Object path
259 * @param[in] iface - Object interface
260 * @param[in] property - Object property
261 * @param[in] handler - Handler function to perform
262 *
263 * @tparam T - The type of the property
264 * @tparam U - The type of the handler
265 */
266template <typename T, typename U>
267auto objectSignal(const char* path,
268 const char* iface,
269 const char* property,
270 U&& handler)
271{
272 return InterfaceAdded<T, U>(path,
273 iface,
274 property,
275 std::forward<U>(handler));
276}
277
Matthew Barth8fa02da2017-09-28 12:18:20 -0500278/**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500279 * @struct Interface Removed
280 * @brief A match filter functor for Dbus interface removed signals
281 *
282 * @tparam U - The type of the handler
283 */
284template <typename U>
285struct InterfaceRemoved
286{
287 InterfaceRemoved() = delete;
288 ~InterfaceRemoved() = default;
289 InterfaceRemoved(const InterfaceRemoved&) = default;
290 InterfaceRemoved& operator=(const InterfaceRemoved&) = default;
291 InterfaceRemoved(InterfaceRemoved&&) = default;
292 InterfaceRemoved& operator=(InterfaceRemoved&&) = default;
293 InterfaceRemoved(const char* path,
294 const char* iface,
295 U&& handler) :
296 _path(path),
297 _iface(iface),
298 _handler(std::forward<U>(handler)) { }
299
300 /** @brief Run signal handler function
301 *
302 * Extract the property from the InterfacesRemoved
303 * message and run the handler function.
304 */
305 void operator()(sdbusplus::bus::bus&,
306 sdbusplus::message::message& msg,
307 Zone& zone) const
308 {
309 if (msg)
310 {
311 std::vector<std::string> intfs;
312 sdbusplus::message::object_path op;
313
314 msg.read(op);
315 if (static_cast<const std::string&>(op) != _path)
316 {
317 // Object path does not match this handler's path
318 return;
319 }
320
321 msg.read(intfs);
322 auto itIntf = std::find(intfs.begin(), intfs.end(), _iface);
323 if (itIntf == intfs.cend())
324 {
325 // Interface not found on this handler's path
326 return;
327 }
328
329 _handler(zone);
330 }
331 }
332
333private:
334 const char* _path;
335 const char* _iface;
336 U _handler;
337};
338
339/**
340 * @brief Used to process a Dbus interface removed signal event
341 *
342 * @param[in] path - Object path
343 * @param[in] iface - Object interface
344 * @param[in] handler - Handler function to perform
345 *
346 * @tparam U - The type of the handler
347 */
348template <typename U>
349auto objectSignal(const char* path,
350 const char* iface,
351 U&& handler)
352{
353 return InterfaceRemoved<U>(path,
354 iface,
355 std::forward<U>(handler));
356}
357
358/**
Matthew Barth8fa02da2017-09-28 12:18:20 -0500359 * @struct Name Owner Changed
360 * @brief A match filter functor for Dbus name owner changed signals
361 *
362 * @tparam U - The type of the handler
363 */
364template <typename U>
365struct NameOwnerChanged
366{
367 NameOwnerChanged() = delete;
368 ~NameOwnerChanged() = default;
369 NameOwnerChanged(const NameOwnerChanged&) = default;
370 NameOwnerChanged& operator=(const NameOwnerChanged&) = default;
371 NameOwnerChanged(NameOwnerChanged&&) = default;
372 NameOwnerChanged& operator=(NameOwnerChanged&&) = default;
373 NameOwnerChanged(const char* path,
374 const char* iface,
375 U&& handler) :
376 _path(path),
377 _iface(iface),
378 _handler(std::forward<U>(handler)) { }
379
380 /** @brief Run signal handler function
381 *
382 * Extract the name owner from the NameOwnerChanged
383 * message (or read the name owner when the message is null)
384 * and run the handler function.
385 */
386 void operator()(sdbusplus::bus::bus& bus,
387 sdbusplus::message::message& msg,
388 Zone& zone) const
389 {
Matthew Barth5a302572017-10-03 11:27:06 -0500390 std::string name;
391 bool hasOwner = false;
Matthew Barth8fa02da2017-09-28 12:18:20 -0500392 if (msg)
393 {
Matthew Barth5a302572017-10-03 11:27:06 -0500394 // Handle NameOwnerChanged signals
395 msg.read(name);
396
397 std::string oldOwn;
398 msg.read(oldOwn);
399
400 std::string newOwn;
401 msg.read(newOwn);
402 if (!newOwn.empty())
403 {
404 hasOwner = true;
405 }
Matthew Barth8fa02da2017-09-28 12:18:20 -0500406 }
407 else
408 {
Matthew Barth5a302572017-10-03 11:27:06 -0500409 try
410 {
411 // Initialize NameOwnerChanged data store with service name
Matthew Barthc72b8912018-01-19 17:28:18 -0600412 name = zone.getService(_path, _iface);
Matthew Barth5a302572017-10-03 11:27:06 -0500413 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
414 bus,
415 "org.freedesktop.DBus",
416 "/org/freedesktop/DBus",
417 "org.freedesktop.DBus",
418 "NameHasOwner",
419 name);
420 }
Matt Spinlerba7b5fe2018-04-25 15:26:10 -0500421 catch (const util::DBusMethodError& e)
Matthew Barth5a302572017-10-03 11:27:06 -0500422 {
423 // Failed to get service name owner state
424 hasOwner = false;
425 }
Matthew Barth8fa02da2017-09-28 12:18:20 -0500426 }
Matthew Barth5a302572017-10-03 11:27:06 -0500427
428 _handler(zone, name, hasOwner);
Matthew Barth8fa02da2017-09-28 12:18:20 -0500429 }
430
431private:
432 const char* _path;
433 const char* _iface;
434 U _handler;
435};
436
437/**
438 * @brief Used to process a Dbus name owner changed signal event
439 *
440 * @param[in] path - Object path
441 * @param[in] iface - Object interface
442 * @param[in] handler - Handler function to perform
443 *
444 * @tparam U - The type of the handler
445 *
446 * @return - The NameOwnerChanged signal struct
447 */
448template <typename U>
449auto ownerSignal(const char* path,
450 const char* iface,
451 U&& handler)
452{
453 return NameOwnerChanged<U>(path,
454 iface,
455 std::forward<U>(handler));
456}
457
Matthew Barth38a93a82017-05-11 14:12:27 -0500458} // namespace control
459} // namespace fan
460} // namespace phosphor