blob: 099cd7c7bd809bead2760061ac096be522367f21 [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>
Andrew Geisslerf3367682020-05-16 14:02:45 -05006#include <cstddef>
William A. Kennington III223c4092018-10-19 15:56:09 -07007#include <sdeventplus/clock.hpp>
8#include <sdeventplus/event.hpp>
9#include <sdeventplus/utility/timer.hpp>
Patrick Venture3d6d3182018-08-31 09:33:09 -070010
Brad Bishopc1283ae2017-05-20 21:42:38 -040011namespace phosphor
12{
13namespace dbus
14{
15namespace monitoring
16{
17
18/** @class Callback
19 * @brief Callback interface.
20 *
21 * Callbacks of any type can be run.
22 */
23class Callback
24{
Brad Bishopd1eac882018-03-29 10:34:05 -040025 public:
26 Callback() = default;
27 Callback(const Callback&) = delete;
28 Callback(Callback&&) = default;
29 Callback& operator=(const Callback&) = delete;
30 Callback& operator=(Callback&&) = default;
31 virtual ~Callback() = default;
Brad Bishopc1283ae2017-05-20 21:42:38 -040032
Brad Bishopd1eac882018-03-29 10:34:05 -040033 /** @brief Run the callback.
34 * @param[in] ctx - caller context
35 * Context could be Startup or Signal
36 * Startup: Callback is called as part of process startup.
37 * Signal: Callback is called as part of watch condition has been met.
38 *
39 */
40 virtual void operator()(Context ctx) = 0;
Marri Devender Rao70aafbb2018-04-12 01:11:48 -050041
42 /** @brief Run the callback.
43 * @param[in] ctx - caller context
44 * Context could be Startup or Signal
45 * Startup: Callback is called as part of process startup.
46 * Signal: Callback is called as part of watch condition has been met.
47 * @param[in] msg - The sdbusplus signal message
48 */
49 virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
Brad Bishopc1283ae2017-05-20 21:42:38 -040050};
51
Brad Bishop4041d722017-05-21 10:06:07 -040052/** @class Conditional
53 * @brief Condition interface.
54 *
55 * Conditions of any type can be tested for true or false.
56 */
57class Conditional
58{
Brad Bishopd1eac882018-03-29 10:34:05 -040059 public:
60 Conditional() = default;
61 Conditional(const Conditional&) = delete;
62 Conditional(Conditional&&) = default;
63 Conditional& operator=(const Conditional&) = delete;
64 Conditional& operator=(Conditional&&) = default;
65 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040066
Brad Bishopd1eac882018-03-29 10:34:05 -040067 /** @brief Test the condition. */
68 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040069};
70
71/** @class IndexedConditional
72 * @brief Condition with an index.
73 */
74class IndexedConditional : public Conditional
75{
Brad Bishopd1eac882018-03-29 10:34:05 -040076 public:
77 IndexedConditional() = delete;
78 IndexedConditional(const IndexedConditional&) = delete;
79 IndexedConditional(IndexedConditional&&) = default;
80 IndexedConditional& operator=(const IndexedConditional&) = delete;
81 IndexedConditional& operator=(IndexedConditional&&) = default;
82 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040083
Brad Bishopd1eac882018-03-29 10:34:05 -040084 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
85 Conditional(), index(conditionIndex)
86 {
87 }
Brad Bishop4041d722017-05-21 10:06:07 -040088
Brad Bishopd1eac882018-03-29 10:34:05 -040089 /** @brief Test the condition. */
90 virtual bool operator()() override = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040091
Brad Bishopd1eac882018-03-29 10:34:05 -040092 protected:
93 /** @brief Property names and their associated storage. */
94 const PropertyIndex& index;
Brad Bishop4041d722017-05-21 10:06:07 -040095};
96
Brad Bishopc1283ae2017-05-20 21:42:38 -040097/** @class IndexedCallback
98 * @brief Callback with an index.
99 */
100class IndexedCallback : public Callback
101{
Brad Bishopd1eac882018-03-29 10:34:05 -0400102 public:
103 IndexedCallback() = delete;
104 IndexedCallback(const IndexedCallback&) = delete;
105 IndexedCallback(IndexedCallback&&) = default;
106 IndexedCallback& operator=(const IndexedCallback&) = delete;
107 IndexedCallback& operator=(IndexedCallback&&) = default;
108 virtual ~IndexedCallback() = default;
109 explicit IndexedCallback(const PropertyIndex& callbackIndex) :
110 Callback(), index(callbackIndex)
111 {
112 }
Brad Bishopc1283ae2017-05-20 21:42:38 -0400113
Brad Bishopd1eac882018-03-29 10:34:05 -0400114 /** @brief Run the callback. */
115 virtual void operator()(Context ctx) override = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400116
Brad Bishopd1eac882018-03-29 10:34:05 -0400117 protected:
118 /** @brief Property names and their associated storage. */
119 const PropertyIndex& index;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400120};
121
Brad Bishop49e66172017-05-23 19:16:21 -0400122/** @class GroupOfCallbacks
123 * @brief Invoke multiple callbacks.
124 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500125 * A group of callbacks is implemented as a vector of array indices
Brad Bishop49e66172017-05-23 19:16:21 -0400126 * into an external array of callbacks. The group function call
Gunnar Mills78199b42017-10-25 16:30:18 -0500127 * operator traverses the vector of indices, invoking each
Brad Bishop49e66172017-05-23 19:16:21 -0400128 * callback.
129 *
130 * @tparam CallbackAccess - Access to the array of callbacks.
131 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700132template <typename CallbackAccess>
133class GroupOfCallbacks : public Callback
Brad Bishop49e66172017-05-23 19:16:21 -0400134{
Brad Bishopd1eac882018-03-29 10:34:05 -0400135 public:
136 GroupOfCallbacks() = delete;
137 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
138 GroupOfCallbacks(GroupOfCallbacks&&) = default;
139 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
140 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
141 ~GroupOfCallbacks() = default;
142 explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
143 graph(graphEntry)
144 {
145 }
Brad Bishop49e66172017-05-23 19:16:21 -0400146
Brad Bishopd1eac882018-03-29 10:34:05 -0400147 /** @brief Run the callbacks. */
148 void operator()(Context ctx) override
149 {
150 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400151 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400152 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400153 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400154 }
Brad Bishop49e66172017-05-23 19:16:21 -0400155
Brad Bishopd1eac882018-03-29 10:34:05 -0400156 private:
157 /** @brief The offsets of the callbacks in the group. */
158 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400159};
160
Brad Bishop4041d722017-05-21 10:06:07 -0400161/** @class ConditionalCallback
162 * @brief Callback adaptor that asssociates a condition with a callback.
163 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700164template <typename CallbackAccess>
165class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400166{
Brad Bishopd1eac882018-03-29 10:34:05 -0400167 public:
168 ConditionalCallback() = delete;
169 ConditionalCallback(const ConditionalCallback&) = delete;
170 ConditionalCallback(ConditionalCallback&&) = default;
171 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
172 ConditionalCallback& operator=(ConditionalCallback&&) = default;
173 virtual ~ConditionalCallback() = default;
174 ConditionalCallback(const std::vector<size_t>& graphEntry,
175 Conditional& cond) :
176 graph(graphEntry),
177 condition(cond)
178 {
179 }
Brad Bishop4041d722017-05-21 10:06:07 -0400180
Brad Bishopd1eac882018-03-29 10:34:05 -0400181 /** @brief Run the callback if the condition is satisfied. */
182 virtual void operator()(Context ctx) override
183 {
184 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400185 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400186 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400187 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400188 }
Brad Bishop4041d722017-05-21 10:06:07 -0400189
Brad Bishopd1eac882018-03-29 10:34:05 -0400190 protected:
191 /** @brief The index of the callback to conditionally invoke. */
192 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400193
Brad Bishopd1eac882018-03-29 10:34:05 -0400194 /** @brief The condition to test. */
195 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400196};
197
Brad Bishop3539db62017-05-30 14:21:12 -0400198/** @class DeferrableCallback
199 *
200 * Deferrable callbacks wait a configurable period before
201 * invoking their associated callback.
202 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500203 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400204 * condition is tested again before the timer expires and it is not
205 * met cancel the timer. If the timer expires invoke the associated
206 * callback.
207 *
208 * @tparam CallbackAccess - Provide access to callback group instances.
Brad Bishop3539db62017-05-30 14:21:12 -0400209 */
William A. Kennington III223c4092018-10-19 15:56:09 -0700210template <typename CallbackAccess>
Brad Bishop3539db62017-05-30 14:21:12 -0400211class DeferrableCallback : public ConditionalCallback<CallbackAccess>
212{
Brad Bishopd1eac882018-03-29 10:34:05 -0400213 public:
William A. Kennington III223c4092018-10-19 15:56:09 -0700214 using TimerType =
215 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
216
Brad Bishopd1eac882018-03-29 10:34:05 -0400217 DeferrableCallback() = delete;
218 DeferrableCallback(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700219 DeferrableCallback(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400220 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700221 DeferrableCallback& operator=(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400222 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400223
Brad Bishopd1eac882018-03-29 10:34:05 -0400224 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
225 const std::chrono::microseconds& delay) :
226 ConditionalCallback<CallbackAccess>(graphEntry, cond),
227 delayInterval(delay), timer(nullptr)
228 {
229 }
Brad Bishop3539db62017-05-30 14:21:12 -0400230
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300231 /** @brief Start internal timer if the condition is satisfied.
232 *
233 * When the timer expires, it calls operator() for the
234 * ConditionalCallback with the context saved in
235 * DeferrableCallback instance.
236 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400237 void operator()(Context ctx) override
238 {
239 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400240 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400241 timer = std::make_unique<TimerType>(
William A. Kennington III223c4092018-10-19 15:56:09 -0700242 sdeventplus::Event::get_default(),
Brad Bishopd1eac882018-03-29 10:34:05 -0400243 // **INDENT-OFF**
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300244 [this](auto& source) {
245 // The timer uses the context saved on timer enable
246 this->ConditionalCallback<CallbackAccess>::operator()(
247 this->ctx);
Brad Bishopd1eac882018-03-29 10:34:05 -0400248 });
249 // **INDENT-ON**
Brad Bishop3539db62017-05-30 14:21:12 -0400250 }
251
Brad Bishopd1eac882018-03-29 10:34:05 -0400252 if (this->condition())
253 {
William A. Kennington III223c4092018-10-19 15:56:09 -0700254 if (!timer->isEnabled())
Brad Bishopd1eac882018-03-29 10:34:05 -0400255 {
256 // This is the first time the condition evaluated.
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300257 // Save current context for timer use.
258 this->ctx = ctx;
Brad Bishopd1eac882018-03-29 10:34:05 -0400259 // Start the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700260 timer->restartOnce(delayInterval);
Brad Bishopd1eac882018-03-29 10:34:05 -0400261 }
262 }
263 else
264 {
265 // The condition did not evaluate. Stop the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700266 timer->setEnabled(false);
Brad Bishopd1eac882018-03-29 10:34:05 -0400267 }
268 }
Brad Bishop3539db62017-05-30 14:21:12 -0400269
Brad Bishopd1eac882018-03-29 10:34:05 -0400270 private:
271 /** @brief The length to wait for the condition to stop evaluating. */
272 std::chrono::microseconds delayInterval;
273
274 /** @brief Delegated timer functions. */
275 std::unique_ptr<TimerType> timer;
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300276
277 /** @brief Current context for timer. */
278 Context ctx;
Brad Bishop3539db62017-05-30 14:21:12 -0400279};
280
Brad Bishopc1283ae2017-05-20 21:42:38 -0400281} // namespace monitoring
282} // namespace dbus
283} // namespace phosphor