blob: b3ad9a09fbc3f4e443b42e7250c0c7b65f9ddd8b [file] [log] [blame]
Matthew Barthb86374d2017-04-12 10:57:19 -05001#pragma once
2
3#include "data_types.hpp"
4
5namespace phosphor
6{
7namespace dbus
8{
9namespace monitoring
10{
11
12class Monitor;
13
14template <typename T>
15auto make_condition(T&& condition)
16{
17 return Condition(std::forward<T>(condition));
18}
19
20template <typename T>
21auto make_action(T&& action)
22{
23 return Action(std::forward<T>(action));
24}
25
Matthew Barth240bf332017-04-12 13:48:29 -050026template <typename T, typename U>
27struct PropertyChangedCondition
28{
29 PropertyChangedCondition() = delete;
30 ~PropertyChangedCondition() = default;
31 PropertyChangedCondition(const PropertyChangedCondition&) = default;
32 PropertyChangedCondition& operator=(const PropertyChangedCondition&) =
33 default;
34 PropertyChangedCondition(PropertyChangedCondition&&) = default;
35 PropertyChangedCondition& operator=(PropertyChangedCondition&&) =
36 default;
37 PropertyChangedCondition(const char* iface, const char* property,
38 U&& condition) :
39 _iface(iface),
40 _property(property),
41 _condition(std::forward<U>(condition)) { }
42
43 /** @brief Test a property value.
44 *
45 * Extract the property from the PropertiesChanged
46 * message and run the condition test.
47 */
48 bool operator()(
49 sdbusplus::bus::bus&,
50 sdbusplus::message::message& msg,
51 Monitor&) const
52 {
53 std::map<std::string, sdbusplus::message::variant<T>> properties;
54 const char* iface = nullptr;
55
56 msg.read(iface);
57 if (!iface || strcmp(iface, _iface))
58 {
59 return false;
60 }
61
62 msg.read(properties);
63 auto it = properties.find(_property);
64 if (it == properties.cend())
65 {
66 return false;
67 }
68
69 return _condition(
70 std::forward<T>(it->second.template get<T>()));
71 }
72
73private:
74 const char* _iface;
75 const char* _property;
76 U _condition;
77};
78
Matthew Barthe6af2332017-04-12 13:37:29 -050079struct PropertyConditionBase
80{
81 PropertyConditionBase() = delete;
82 virtual ~PropertyConditionBase() = default;
83 PropertyConditionBase(const PropertyConditionBase&) = default;
84 PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
85 PropertyConditionBase(PropertyConditionBase&&) = default;
86 PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
87
88 /** @brief Constructor
89 *
90 * The service argument can be nullptr. If something
91 * else is provided the function will call the the
92 * service directly. If omitted, the function will
93 * look up the service in the ObjectMapper.
94 *
95 * @param path - The path of the object containing
96 * the property to be tested.
97 * @param iface - The interface hosting the property
98 * to be tested.
99 * @param property - The property to be tested.
100 * @param service - The DBus service hosting the object.
101 */
102 PropertyConditionBase(
103 const char* path,
104 const char* iface,
105 const char* property,
106 const char* service) :
107 _path(path ? path : std::string()),
108 _iface(iface),
109 _property(property),
110 _service(service) {}
111
112 /** @brief Forward comparison to type specific implementation. */
113 virtual bool eval(sdbusplus::message::message&) const = 0;
114
115 /** @brief Test a property value.
116 *
117 * Make a DBus call and test the value of any property.
118 */
119 bool operator()(
120 sdbusplus::bus::bus&,
121 sdbusplus::message::message&,
122 Monitor&) const;
123
124private:
125 std::string _path;
126 std::string _iface;
127 std::string _property;
128 const char* _service;
129};
130
131template <typename T, typename U>
132struct PropertyCondition final : public PropertyConditionBase
133{
134 PropertyCondition() = delete;
135 ~PropertyCondition() = default;
136 PropertyCondition(const PropertyCondition&) = default;
137 PropertyCondition& operator=(const PropertyCondition&) = default;
138 PropertyCondition(PropertyCondition&&) = default;
139 PropertyCondition& operator=(PropertyCondition&&) = default;
140
141 /** @brief Constructor
142 *
143 * The service argument can be nullptr. If something
144 * else is provided the function will call the the
145 * service directly. If omitted, the function will
146 * look up the service in the ObjectMapper.
147 *
148 * @param path - The path of the object containing
149 * the property to be tested.
150 * @param iface - The interface hosting the property
151 * to be tested.
152 * @param property - The property to be tested.
153 * @param condition - The test to run on the property.
154 * @param service - The DBus service hosting the object.
155 */
156 PropertyCondition(
157 const char* path,
158 const char* iface,
159 const char* property,
160 U&& condition,
161 const char* service) :
162 PropertyConditionBase(path, iface, property, service),
163 _condition(std::forward<decltype(condition)>(condition)) {}
164
165 /** @brief Test a property value.
166 *
167 * Make a DBus call and test the value of any property.
168 */
169 bool eval(sdbusplus::message::message& msg) const override
170 {
171 sdbusplus::message::variant<T> value;
172 msg.read(value);
173 return _condition(std::forward<T>(value.template get<T>()));
174 }
175
176private:
177 U _condition;
178};
179
180template <typename T, typename U>
Matthew Barth240bf332017-04-12 13:48:29 -0500181auto propertySignal(const char* iface,
182 const char* property,
183 U&& condition)
184{
185 return PropertyChangedCondition<T, U>(iface,
186 property,
187 std::move(condition));
188}
189
190template <typename T, typename U>
Matthew Barthe6af2332017-04-12 13:37:29 -0500191auto propertyStart(const char* path,
192 const char* iface,
193 const char* property,
194 U&& condition,
195 const char* service = nullptr)
196{
197 return PropertyCondition<T, U>(path,
198 iface,
199 property,
200 std::move(condition),
201 service);
202}
203
Matthew Barthb86374d2017-04-12 10:57:19 -0500204} // namespace monitoring
205} // namespace dbus
206} // namespace phosphor