blob: b1c8d0b88b26fa0b3c72664c0b16cdac915370e3 [file] [log] [blame]
Brad Bishopc1283ae2017-05-20 21:42:38 -04001#pragma once
2
3#include "data_types.hpp"
4
Patrick Venture3d6d3182018-08-31 09:33:09 -07005#include <chrono>
William A. Kennington III223c4092018-10-19 15:56:09 -07006#include <sdeventplus/clock.hpp>
7#include <sdeventplus/event.hpp>
8#include <sdeventplus/utility/timer.hpp>
Patrick Venture3d6d3182018-08-31 09:33:09 -07009
Brad Bishopc1283ae2017-05-20 21:42:38 -040010namespace phosphor
11{
12namespace dbus
13{
14namespace monitoring
15{
16
17/** @class Callback
18 * @brief Callback interface.
19 *
20 * Callbacks of any type can be run.
21 */
22class Callback
23{
Brad Bishopd1eac882018-03-29 10:34:05 -040024 public:
25 Callback() = default;
26 Callback(const Callback&) = delete;
27 Callback(Callback&&) = default;
28 Callback& operator=(const Callback&) = delete;
29 Callback& operator=(Callback&&) = default;
30 virtual ~Callback() = default;
Brad Bishopc1283ae2017-05-20 21:42:38 -040031
Brad Bishopd1eac882018-03-29 10:34:05 -040032 /** @brief Run the callback.
33 * @param[in] ctx - caller context
34 * Context could be Startup or Signal
35 * Startup: Callback is called as part of process startup.
36 * Signal: Callback is called as part of watch condition has been met.
37 *
38 */
39 virtual void operator()(Context ctx) = 0;
Marri Devender Rao70aafbb2018-04-12 01:11:48 -050040
41 /** @brief Run the callback.
42 * @param[in] ctx - caller context
43 * Context could be Startup or Signal
44 * Startup: Callback is called as part of process startup.
45 * Signal: Callback is called as part of watch condition has been met.
46 * @param[in] msg - The sdbusplus signal message
47 */
48 virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
Brad Bishopc1283ae2017-05-20 21:42:38 -040049};
50
Brad Bishop4041d722017-05-21 10:06:07 -040051/** @class Conditional
52 * @brief Condition interface.
53 *
54 * Conditions of any type can be tested for true or false.
55 */
56class Conditional
57{
Brad Bishopd1eac882018-03-29 10:34:05 -040058 public:
59 Conditional() = default;
60 Conditional(const Conditional&) = delete;
61 Conditional(Conditional&&) = default;
62 Conditional& operator=(const Conditional&) = delete;
63 Conditional& operator=(Conditional&&) = default;
64 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040065
Brad Bishopd1eac882018-03-29 10:34:05 -040066 /** @brief Test the condition. */
67 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040068};
69
70/** @class IndexedConditional
71 * @brief Condition with an index.
72 */
73class IndexedConditional : public Conditional
74{
Brad Bishopd1eac882018-03-29 10:34:05 -040075 public:
76 IndexedConditional() = delete;
77 IndexedConditional(const IndexedConditional&) = delete;
78 IndexedConditional(IndexedConditional&&) = default;
79 IndexedConditional& operator=(const IndexedConditional&) = delete;
80 IndexedConditional& operator=(IndexedConditional&&) = default;
81 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040082
Brad Bishopd1eac882018-03-29 10:34:05 -040083 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
84 Conditional(), index(conditionIndex)
85 {
86 }
Brad Bishop4041d722017-05-21 10:06:07 -040087
Brad Bishopd1eac882018-03-29 10:34:05 -040088 /** @brief Test the condition. */
89 virtual bool operator()() override = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040090
Brad Bishopd1eac882018-03-29 10:34:05 -040091 protected:
92 /** @brief Property names and their associated storage. */
93 const PropertyIndex& index;
Brad Bishop4041d722017-05-21 10:06:07 -040094};
95
Brad Bishopc1283ae2017-05-20 21:42:38 -040096/** @class IndexedCallback
97 * @brief Callback with an index.
98 */
99class IndexedCallback : public Callback
100{
Brad Bishopd1eac882018-03-29 10:34:05 -0400101 public:
102 IndexedCallback() = delete;
103 IndexedCallback(const IndexedCallback&) = delete;
104 IndexedCallback(IndexedCallback&&) = default;
105 IndexedCallback& operator=(const IndexedCallback&) = delete;
106 IndexedCallback& operator=(IndexedCallback&&) = default;
107 virtual ~IndexedCallback() = default;
108 explicit IndexedCallback(const PropertyIndex& callbackIndex) :
109 Callback(), index(callbackIndex)
110 {
111 }
Brad Bishopc1283ae2017-05-20 21:42:38 -0400112
Brad Bishopd1eac882018-03-29 10:34:05 -0400113 /** @brief Run the callback. */
114 virtual void operator()(Context ctx) override = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400115
Brad Bishopd1eac882018-03-29 10:34:05 -0400116 protected:
117 /** @brief Property names and their associated storage. */
118 const PropertyIndex& index;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400119};
120
Brad Bishop49e66172017-05-23 19:16:21 -0400121/** @class GroupOfCallbacks
122 * @brief Invoke multiple callbacks.
123 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500124 * A group of callbacks is implemented as a vector of array indices
Brad Bishop49e66172017-05-23 19:16:21 -0400125 * into an external array of callbacks. The group function call
Gunnar Mills78199b42017-10-25 16:30:18 -0500126 * operator traverses the vector of indices, invoking each
Brad Bishop49e66172017-05-23 19:16:21 -0400127 * callback.
128 *
129 * @tparam CallbackAccess - Access to the array of callbacks.
130 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700131template <typename CallbackAccess>
132class GroupOfCallbacks : public Callback
Brad Bishop49e66172017-05-23 19:16:21 -0400133{
Brad Bishopd1eac882018-03-29 10:34:05 -0400134 public:
135 GroupOfCallbacks() = delete;
136 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
137 GroupOfCallbacks(GroupOfCallbacks&&) = default;
138 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
139 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
140 ~GroupOfCallbacks() = default;
141 explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
142 graph(graphEntry)
143 {
144 }
Brad Bishop49e66172017-05-23 19:16:21 -0400145
Brad Bishopd1eac882018-03-29 10:34:05 -0400146 /** @brief Run the callbacks. */
147 void operator()(Context ctx) override
148 {
149 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400150 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400151 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400152 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400153 }
Brad Bishop49e66172017-05-23 19:16:21 -0400154
Brad Bishopd1eac882018-03-29 10:34:05 -0400155 private:
156 /** @brief The offsets of the callbacks in the group. */
157 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400158};
159
Brad Bishop4041d722017-05-21 10:06:07 -0400160/** @class ConditionalCallback
161 * @brief Callback adaptor that asssociates a condition with a callback.
162 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700163template <typename CallbackAccess>
164class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400165{
Brad Bishopd1eac882018-03-29 10:34:05 -0400166 public:
167 ConditionalCallback() = delete;
168 ConditionalCallback(const ConditionalCallback&) = delete;
169 ConditionalCallback(ConditionalCallback&&) = default;
170 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
171 ConditionalCallback& operator=(ConditionalCallback&&) = default;
172 virtual ~ConditionalCallback() = default;
173 ConditionalCallback(const std::vector<size_t>& graphEntry,
174 Conditional& cond) :
175 graph(graphEntry),
176 condition(cond)
177 {
178 }
Brad Bishop4041d722017-05-21 10:06:07 -0400179
Brad Bishopd1eac882018-03-29 10:34:05 -0400180 /** @brief Run the callback if the condition is satisfied. */
181 virtual void operator()(Context ctx) override
182 {
183 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400184 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400185 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400186 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400187 }
Brad Bishop4041d722017-05-21 10:06:07 -0400188
Brad Bishopd1eac882018-03-29 10:34:05 -0400189 protected:
190 /** @brief The index of the callback to conditionally invoke. */
191 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400192
Brad Bishopd1eac882018-03-29 10:34:05 -0400193 /** @brief The condition to test. */
194 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400195};
196
Brad Bishop3539db62017-05-30 14:21:12 -0400197/** @class DeferrableCallback
198 *
199 * Deferrable callbacks wait a configurable period before
200 * invoking their associated callback.
201 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500202 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400203 * condition is tested again before the timer expires and it is not
204 * met cancel the timer. If the timer expires invoke the associated
205 * callback.
206 *
207 * @tparam CallbackAccess - Provide access to callback group instances.
Brad Bishop3539db62017-05-30 14:21:12 -0400208 */
William A. Kennington III223c4092018-10-19 15:56:09 -0700209template <typename CallbackAccess>
Brad Bishop3539db62017-05-30 14:21:12 -0400210class DeferrableCallback : public ConditionalCallback<CallbackAccess>
211{
Brad Bishopd1eac882018-03-29 10:34:05 -0400212 public:
William A. Kennington III223c4092018-10-19 15:56:09 -0700213 using TimerType =
214 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
215
Brad Bishopd1eac882018-03-29 10:34:05 -0400216 DeferrableCallback() = delete;
217 DeferrableCallback(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700218 DeferrableCallback(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400219 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700220 DeferrableCallback& operator=(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400221 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400222
Brad Bishopd1eac882018-03-29 10:34:05 -0400223 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
224 const std::chrono::microseconds& delay) :
225 ConditionalCallback<CallbackAccess>(graphEntry, cond),
226 delayInterval(delay), timer(nullptr)
227 {
228 }
Brad Bishop3539db62017-05-30 14:21:12 -0400229
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300230 /** @brief Start internal timer if the condition is satisfied.
231 *
232 * When the timer expires, it calls operator() for the
233 * ConditionalCallback with the context saved in
234 * DeferrableCallback instance.
235 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400236 void operator()(Context ctx) override
237 {
238 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400239 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400240 timer = std::make_unique<TimerType>(
William A. Kennington III223c4092018-10-19 15:56:09 -0700241 sdeventplus::Event::get_default(),
Brad Bishopd1eac882018-03-29 10:34:05 -0400242 // **INDENT-OFF**
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300243 [this](auto& source) {
244 // The timer uses the context saved on timer enable
245 this->ConditionalCallback<CallbackAccess>::operator()(
246 this->ctx);
Brad Bishopd1eac882018-03-29 10:34:05 -0400247 });
248 // **INDENT-ON**
Brad Bishop3539db62017-05-30 14:21:12 -0400249 }
250
Brad Bishopd1eac882018-03-29 10:34:05 -0400251 if (this->condition())
252 {
William A. Kennington III223c4092018-10-19 15:56:09 -0700253 if (!timer->isEnabled())
Brad Bishopd1eac882018-03-29 10:34:05 -0400254 {
255 // This is the first time the condition evaluated.
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300256 // Save current context for timer use.
257 this->ctx = ctx;
Brad Bishopd1eac882018-03-29 10:34:05 -0400258 // Start the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700259 timer->restartOnce(delayInterval);
Brad Bishopd1eac882018-03-29 10:34:05 -0400260 }
261 }
262 else
263 {
264 // The condition did not evaluate. Stop the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700265 timer->setEnabled(false);
Brad Bishopd1eac882018-03-29 10:34:05 -0400266 }
267 }
Brad Bishop3539db62017-05-30 14:21:12 -0400268
Brad Bishopd1eac882018-03-29 10:34:05 -0400269 private:
270 /** @brief The length to wait for the condition to stop evaluating. */
271 std::chrono::microseconds delayInterval;
272
273 /** @brief Delegated timer functions. */
274 std::unique_ptr<TimerType> timer;
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300275
276 /** @brief Current context for timer. */
277 Context ctx;
Brad Bishop3539db62017-05-30 14:21:12 -0400278};
279
Brad Bishopc1283ae2017-05-20 21:42:38 -0400280} // namespace monitoring
281} // namespace dbus
282} // namespace phosphor