blob: ab5005d95d11667fad0e908fdc6832ebff5cd5a7 [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 Barth38a93a82017-05-11 14:12:27 -050033 * @brief Create a handler function object
34 *
35 * @param[in] handler - The handler being created
36 *
37 * @return - The created handler function object
38 */
39template <typename T>
40auto make_handler(T&& handler)
41{
42 return Handler(std::forward<T>(handler));
43}
44
45/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050046 * @brief Create an action function object
47 *
48 * @param[in] action - The action being created
49 *
50 * @return - The created action function object
51 */
52template <typename T>
53auto make_action(T&& action)
54{
55 return Action(std::forward<T>(action));
56}
57
58/**
Matthew Barth38a93a82017-05-11 14:12:27 -050059 * @struct Property Changed
60 * @brief A match filter functor for Dbus property value changed signals
61 *
62 * @tparam T - The type of the property value
63 * @tparam U - The type of the handler
64 */
65template <typename T, typename U>
66struct PropertyChanged
67{
68 PropertyChanged() = delete;
69 ~PropertyChanged() = default;
70 PropertyChanged(const PropertyChanged&) = default;
71 PropertyChanged& operator=(const PropertyChanged&) = default;
72 PropertyChanged(PropertyChanged&&) = default;
73 PropertyChanged& operator=(PropertyChanged&&) = default;
Matthew Barth336f18a2017-09-26 09:15:56 -050074 PropertyChanged(const char* path,
75 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -050076 const char* property,
77 U&& handler) :
Matthew Barth336f18a2017-09-26 09:15:56 -050078 _path(path),
Matthew Barth38a93a82017-05-11 14:12:27 -050079 _iface(iface),
80 _property(property),
81 _handler(std::forward<U>(handler)) { }
82
83 /** @brief Run signal handler function
84 *
85 * Extract the property from the PropertiesChanged
Matthew Barth336f18a2017-09-26 09:15:56 -050086 * message (or read the property when the message is null)
87 * and run the handler function.
Matthew Barth38a93a82017-05-11 14:12:27 -050088 */
Matthew Barth336f18a2017-09-26 09:15:56 -050089 void operator()(sdbusplus::bus::bus& bus,
Matthew Barth38a93a82017-05-11 14:12:27 -050090 sdbusplus::message::message& msg,
91 Zone& zone) const
92 {
Matthew Barth336f18a2017-09-26 09:15:56 -050093 if (msg)
Matthew Barth38a93a82017-05-11 14:12:27 -050094 {
Matthew Barth336f18a2017-09-26 09:15:56 -050095 std::map<std::string, sdbusplus::message::variant<T>> properties;
Matthew Barthd5cfdbe2017-11-14 15:29:50 -060096 std::string iface;
Matthew Barth38a93a82017-05-11 14:12:27 -050097
Matthew Barth336f18a2017-09-26 09:15:56 -050098 msg.read(iface);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -060099 if (iface != _iface)
Matthew Barth336f18a2017-09-26 09:15:56 -0500100 {
101 return;
102 }
103
104 msg.read(properties);
105 auto it = properties.find(_property);
106 if (it == properties.cend())
107 {
108 log<level::ERR>("Unable to find property on interface",
109 entry("PROPERTY=%s", _property),
Matthew Barthe65f6172017-12-11 13:36:02 -0600110 entry("INTERFACE=%s", _iface),
111 entry("PATH=%s", _path));
Matthew Barth336f18a2017-09-26 09:15:56 -0500112 return;
113 }
114
William A. Kennington III4978e062018-11-27 11:47:12 -0800115 _handler(zone, std::forward<T>(
116 sdbusplus::message::variant_ns::get<T>(it->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500117 }
118 else
Matthew Barth38a93a82017-05-11 14:12:27 -0500119 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500120 try
121 {
Matthew Barth766f8542019-01-29 12:44:13 -0600122 auto val = zone.getPropertyByName<T>(_path, _iface, _property);
Matthew Barth336f18a2017-09-26 09:15:56 -0500123 _handler(zone, std::forward<T>(val));
124 }
Matthew Barth86be4762018-07-17 10:51:36 -0500125 catch (const sdbusplus::exception::SdBusError&)
126 {
127 // Property will not be used unless a property changed
128 // signal message is received for this property.
129 }
130 catch (const util::DBusError&)
Matthew Barth336f18a2017-09-26 09:15:56 -0500131 {
132 // Property will not be used unless a property changed
133 // signal message is received for this property.
Matthew Barth336f18a2017-09-26 09:15:56 -0500134 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500135 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500136 }
137
138private:
Matthew Barth336f18a2017-09-26 09:15:56 -0500139 const char* _path;
Matthew Barth38a93a82017-05-11 14:12:27 -0500140 const char* _iface;
141 const char* _property;
142 U _handler;
143};
144
145/**
146 * @brief Used to process a Dbus property changed signal event
147 *
Matthew Barth336f18a2017-09-26 09:15:56 -0500148 * @param[in] path - Object path
149 * @param[in] iface - Object interface
150 * @param[in] property - Object property
Matthew Barth38a93a82017-05-11 14:12:27 -0500151 * @param[in] handler - Handler function to perform
152 *
153 * @tparam T - The type of the property
154 * @tparam U - The type of the handler
155 */
156template <typename T, typename U>
Matthew Barth336f18a2017-09-26 09:15:56 -0500157auto propertySignal(const char* path,
158 const char* iface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500159 const char* property,
160 U&& handler)
161{
Matthew Barth336f18a2017-09-26 09:15:56 -0500162 return PropertyChanged<T, U>(path,
163 iface,
164 property,
165 std::forward<U>(handler));
Matthew Barth38a93a82017-05-11 14:12:27 -0500166}
167
Matthew Bartheb639c52017-08-04 09:43:11 -0500168/**
169 * @struct Interface Added
170 * @brief A match filter functor for Dbus interface added signals
171 *
172 * @tparam T - The type of the property value
173 * @tparam U - The type of the handler
174 */
175template <typename T, typename U>
176struct InterfaceAdded
177{
178 InterfaceAdded() = delete;
179 ~InterfaceAdded() = default;
180 InterfaceAdded(const InterfaceAdded&) = default;
181 InterfaceAdded& operator=(const InterfaceAdded&) = default;
182 InterfaceAdded(InterfaceAdded&&) = default;
183 InterfaceAdded& operator=(InterfaceAdded&&) = default;
184 InterfaceAdded(const char* path,
185 const char* iface,
186 const char* property,
187 U&& handler) :
188 _path(path),
189 _iface(iface),
190 _property(property),
191 _handler(std::forward<U>(handler)) { }
192
193 /** @brief Run signal handler function
194 *
195 * Extract the property from the InterfacesAdded
196 * message and run the handler function.
197 */
198 void operator()(sdbusplus::bus::bus&,
199 sdbusplus::message::message& msg,
200 Zone& zone) const
201 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500202 if (msg)
Matthew Bartheb639c52017-08-04 09:43:11 -0500203 {
Matthew Barth336f18a2017-09-26 09:15:56 -0500204 std::map<std::string,
205 std::map<std::string,
206 sdbusplus::message::variant<T>>> intfProp;
207 sdbusplus::message::object_path op;
Matthew Bartheb639c52017-08-04 09:43:11 -0500208
Matthew Barth336f18a2017-09-26 09:15:56 -0500209 msg.read(op);
Matthew Barthd5cfdbe2017-11-14 15:29:50 -0600210 if (static_cast<const std::string&>(op) != _path)
Matthew Barth336f18a2017-09-26 09:15:56 -0500211 {
212 // Object path does not match this handler's path
213 return;
214 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500215
Matthew Barth336f18a2017-09-26 09:15:56 -0500216 msg.read(intfProp);
217 auto itIntf = intfProp.find(_iface);
218 if (itIntf == intfProp.cend())
219 {
220 // Interface not found on this handler's path
221 return;
222 }
223 auto itProp = itIntf->second.find(_property);
224 if (itProp == itIntf->second.cend())
225 {
226 // Property not found on this handler's path
227 return;
228 }
229
William A. Kennington III4978e062018-11-27 11:47:12 -0800230 _handler(zone, std::forward<T>(
231 sdbusplus::message::variant_ns::get<T>(itProp->second)));
Matthew Barth336f18a2017-09-26 09:15:56 -0500232 }
Matthew Bartheb639c52017-08-04 09:43:11 -0500233 }
234
235private:
236 const char* _path;
237 const char* _iface;
238 const char* _property;
239 U _handler;
240};
241
242/**
243 * @brief Used to process a Dbus interface added signal event
244 *
245 * @param[in] path - Object path
246 * @param[in] iface - Object interface
247 * @param[in] property - Object property
248 * @param[in] handler - Handler function to perform
249 *
250 * @tparam T - The type of the property
251 * @tparam U - The type of the handler
252 */
253template <typename T, typename U>
254auto objectSignal(const char* path,
255 const char* iface,
256 const char* property,
257 U&& handler)
258{
259 return InterfaceAdded<T, U>(path,
260 iface,
261 property,
262 std::forward<U>(handler));
263}
264
Matthew Barth8fa02da2017-09-28 12:18:20 -0500265/**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500266 * @struct Interface Removed
267 * @brief A match filter functor for Dbus interface removed signals
268 *
269 * @tparam U - The type of the handler
270 */
271template <typename U>
272struct InterfaceRemoved
273{
274 InterfaceRemoved() = delete;
275 ~InterfaceRemoved() = default;
276 InterfaceRemoved(const InterfaceRemoved&) = default;
277 InterfaceRemoved& operator=(const InterfaceRemoved&) = default;
278 InterfaceRemoved(InterfaceRemoved&&) = default;
279 InterfaceRemoved& operator=(InterfaceRemoved&&) = default;
280 InterfaceRemoved(const char* path,
281 const char* iface,
282 U&& handler) :
283 _path(path),
284 _iface(iface),
285 _handler(std::forward<U>(handler)) { }
286
287 /** @brief Run signal handler function
288 *
289 * Extract the property from the InterfacesRemoved
290 * message and run the handler function.
291 */
292 void operator()(sdbusplus::bus::bus&,
293 sdbusplus::message::message& msg,
294 Zone& zone) const
295 {
296 if (msg)
297 {
298 std::vector<std::string> intfs;
299 sdbusplus::message::object_path op;
300
301 msg.read(op);
302 if (static_cast<const std::string&>(op) != _path)
303 {
304 // Object path does not match this handler's path
305 return;
306 }
307
308 msg.read(intfs);
309 auto itIntf = std::find(intfs.begin(), intfs.end(), _iface);
310 if (itIntf == intfs.cend())
311 {
312 // Interface not found on this handler's path
313 return;
314 }
315
316 _handler(zone);
317 }
318 }
319
320private:
321 const char* _path;
322 const char* _iface;
323 U _handler;
324};
325
326/**
327 * @brief Used to process a Dbus interface removed signal event
328 *
329 * @param[in] path - Object path
330 * @param[in] iface - Object interface
331 * @param[in] handler - Handler function to perform
332 *
333 * @tparam U - The type of the handler
334 */
335template <typename U>
336auto objectSignal(const char* path,
337 const char* iface,
338 U&& handler)
339{
340 return InterfaceRemoved<U>(path,
341 iface,
342 std::forward<U>(handler));
343}
344
345/**
Matthew Barth8fa02da2017-09-28 12:18:20 -0500346 * @struct Name Owner Changed
347 * @brief A match filter functor for Dbus name owner changed signals
348 *
349 * @tparam U - The type of the handler
350 */
351template <typename U>
352struct NameOwnerChanged
353{
354 NameOwnerChanged() = delete;
355 ~NameOwnerChanged() = default;
356 NameOwnerChanged(const NameOwnerChanged&) = default;
357 NameOwnerChanged& operator=(const NameOwnerChanged&) = default;
358 NameOwnerChanged(NameOwnerChanged&&) = default;
359 NameOwnerChanged& operator=(NameOwnerChanged&&) = default;
360 NameOwnerChanged(const char* path,
361 const char* iface,
362 U&& handler) :
363 _path(path),
364 _iface(iface),
365 _handler(std::forward<U>(handler)) { }
366
367 /** @brief Run signal handler function
368 *
369 * Extract the name owner from the NameOwnerChanged
370 * message (or read the name owner when the message is null)
371 * and run the handler function.
372 */
373 void operator()(sdbusplus::bus::bus& bus,
374 sdbusplus::message::message& msg,
375 Zone& zone) const
376 {
Matthew Barth5a302572017-10-03 11:27:06 -0500377 std::string name;
378 bool hasOwner = false;
Matthew Barth8fa02da2017-09-28 12:18:20 -0500379 if (msg)
380 {
Matthew Barth5a302572017-10-03 11:27:06 -0500381 // Handle NameOwnerChanged signals
382 msg.read(name);
383
384 std::string oldOwn;
385 msg.read(oldOwn);
386
387 std::string newOwn;
388 msg.read(newOwn);
389 if (!newOwn.empty())
390 {
391 hasOwner = true;
392 }
Matthew Barth8fa02da2017-09-28 12:18:20 -0500393 }
394 else
395 {
Matthew Barth5a302572017-10-03 11:27:06 -0500396 try
397 {
398 // Initialize NameOwnerChanged data store with service name
Matthew Barthc72b8912018-01-19 17:28:18 -0600399 name = zone.getService(_path, _iface);
Matthew Barth5a302572017-10-03 11:27:06 -0500400 hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
401 bus,
402 "org.freedesktop.DBus",
403 "/org/freedesktop/DBus",
404 "org.freedesktop.DBus",
405 "NameHasOwner",
406 name);
407 }
Matt Spinlerba7b5fe2018-04-25 15:26:10 -0500408 catch (const util::DBusMethodError& e)
Matthew Barth5a302572017-10-03 11:27:06 -0500409 {
410 // Failed to get service name owner state
411 hasOwner = false;
412 }
Matthew Barth8fa02da2017-09-28 12:18:20 -0500413 }
Matthew Barth5a302572017-10-03 11:27:06 -0500414
415 _handler(zone, name, hasOwner);
Matthew Barth8fa02da2017-09-28 12:18:20 -0500416 }
417
418private:
419 const char* _path;
420 const char* _iface;
421 U _handler;
422};
423
424/**
425 * @brief Used to process a Dbus name owner changed signal event
426 *
427 * @param[in] path - Object path
428 * @param[in] iface - Object interface
429 * @param[in] handler - Handler function to perform
430 *
431 * @tparam U - The type of the handler
432 *
433 * @return - The NameOwnerChanged signal struct
434 */
435template <typename U>
436auto ownerSignal(const char* path,
437 const char* iface,
438 U&& handler)
439{
440 return NameOwnerChanged<U>(path,
441 iface,
442 std::forward<U>(handler));
443}
444
Matthew Barth38a93a82017-05-11 14:12:27 -0500445} // namespace control
446} // namespace fan
447} // namespace phosphor