blob: bc3ec48e15633170b8ea3eb4238451d88a27692b [file] [log] [blame]
Brad Bishopc1283ae2017-05-20 21:42:38 -04001#pragma once
2
3#include "data_types.hpp"
4
William A. Kennington III223c4092018-10-19 15:56:09 -07005#include <sdeventplus/clock.hpp>
6#include <sdeventplus/event.hpp>
7#include <sdeventplus/utility/timer.hpp>
Patrick Venture3d6d3182018-08-31 09:33:09 -07008
George Liu3fe976c2022-06-21 09:37:04 +08009#include <chrono>
10#include <cstddef>
11
Brad Bishopc1283ae2017-05-20 21:42:38 -040012namespace phosphor
13{
14namespace dbus
15{
16namespace monitoring
17{
18
19/** @class Callback
20 * @brief Callback interface.
21 *
22 * Callbacks of any type can be run.
23 */
24class Callback
25{
Brad Bishopd1eac882018-03-29 10:34:05 -040026 public:
27 Callback() = default;
28 Callback(const Callback&) = delete;
29 Callback(Callback&&) = default;
30 Callback& operator=(const Callback&) = delete;
31 Callback& operator=(Callback&&) = default;
32 virtual ~Callback() = default;
Brad Bishopc1283ae2017-05-20 21:42:38 -040033
Brad Bishopd1eac882018-03-29 10:34:05 -040034 /** @brief Run the callback.
35 * @param[in] ctx - caller context
36 * Context could be Startup or Signal
37 * Startup: Callback is called as part of process startup.
38 * Signal: Callback is called as part of watch condition has been met.
39 *
40 */
41 virtual void operator()(Context ctx) = 0;
Marri Devender Rao70aafbb2018-04-12 01:11:48 -050042
43 /** @brief Run the callback.
44 * @param[in] ctx - caller context
45 * Context could be Startup or Signal
46 * Startup: Callback is called as part of process startup.
47 * Signal: Callback is called as part of watch condition has been met.
48 * @param[in] msg - The sdbusplus signal message
49 */
50 virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
Brad Bishopc1283ae2017-05-20 21:42:38 -040051};
52
Brad Bishop4041d722017-05-21 10:06:07 -040053/** @class Conditional
54 * @brief Condition interface.
55 *
56 * Conditions of any type can be tested for true or false.
57 */
58class Conditional
59{
Brad Bishopd1eac882018-03-29 10:34:05 -040060 public:
61 Conditional() = default;
62 Conditional(const Conditional&) = delete;
63 Conditional(Conditional&&) = default;
64 Conditional& operator=(const Conditional&) = delete;
65 Conditional& operator=(Conditional&&) = default;
66 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040067
Brad Bishopd1eac882018-03-29 10:34:05 -040068 /** @brief Test the condition. */
69 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040070};
71
72/** @class IndexedConditional
73 * @brief Condition with an index.
74 */
75class IndexedConditional : public Conditional
76{
Brad Bishopd1eac882018-03-29 10:34:05 -040077 public:
78 IndexedConditional() = delete;
79 IndexedConditional(const IndexedConditional&) = delete;
80 IndexedConditional(IndexedConditional&&) = default;
81 IndexedConditional& operator=(const IndexedConditional&) = delete;
82 IndexedConditional& operator=(IndexedConditional&&) = default;
83 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040084
Brad Bishopd1eac882018-03-29 10:34:05 -040085 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
86 Conditional(), index(conditionIndex)
George Liu3fe976c2022-06-21 09:37:04 +080087 {}
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)
George Liu3fe976c2022-06-21 09:37:04 +0800111 {}
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)
George Liu3fe976c2022-06-21 09:37:04 +0800143 {}
Brad Bishop49e66172017-05-23 19:16:21 -0400144
Brad Bishopd1eac882018-03-29 10:34:05 -0400145 /** @brief Run the callbacks. */
146 void operator()(Context ctx) override
147 {
148 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400149 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400150 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400151 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400152 }
Brad Bishop49e66172017-05-23 19:16:21 -0400153
Brad Bishopd1eac882018-03-29 10:34:05 -0400154 private:
155 /** @brief The offsets of the callbacks in the group. */
156 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400157};
158
Brad Bishop4041d722017-05-21 10:06:07 -0400159/** @class ConditionalCallback
160 * @brief Callback adaptor that asssociates a condition with a callback.
161 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700162template <typename CallbackAccess>
163class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400164{
Brad Bishopd1eac882018-03-29 10:34:05 -0400165 public:
166 ConditionalCallback() = delete;
167 ConditionalCallback(const ConditionalCallback&) = delete;
168 ConditionalCallback(ConditionalCallback&&) = default;
169 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
170 ConditionalCallback& operator=(ConditionalCallback&&) = default;
171 virtual ~ConditionalCallback() = default;
172 ConditionalCallback(const std::vector<size_t>& graphEntry,
173 Conditional& cond) :
174 graph(graphEntry),
175 condition(cond)
George Liu3fe976c2022-06-21 09:37:04 +0800176 {}
Brad Bishop4041d722017-05-21 10:06:07 -0400177
Brad Bishopd1eac882018-03-29 10:34:05 -0400178 /** @brief Run the callback if the condition is satisfied. */
179 virtual void operator()(Context ctx) override
180 {
181 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400182 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400183 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400184 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400185 }
Brad Bishop4041d722017-05-21 10:06:07 -0400186
Brad Bishopd1eac882018-03-29 10:34:05 -0400187 protected:
188 /** @brief The index of the callback to conditionally invoke. */
189 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400190
Brad Bishopd1eac882018-03-29 10:34:05 -0400191 /** @brief The condition to test. */
192 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400193};
194
Brad Bishop3539db62017-05-30 14:21:12 -0400195/** @class DeferrableCallback
196 *
197 * Deferrable callbacks wait a configurable period before
198 * invoking their associated callback.
199 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500200 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400201 * condition is tested again before the timer expires and it is not
202 * met cancel the timer. If the timer expires invoke the associated
203 * callback.
204 *
205 * @tparam CallbackAccess - Provide access to callback group instances.
Brad Bishop3539db62017-05-30 14:21:12 -0400206 */
William A. Kennington III223c4092018-10-19 15:56:09 -0700207template <typename CallbackAccess>
Brad Bishop3539db62017-05-30 14:21:12 -0400208class DeferrableCallback : public ConditionalCallback<CallbackAccess>
209{
Brad Bishopd1eac882018-03-29 10:34:05 -0400210 public:
William A. Kennington III223c4092018-10-19 15:56:09 -0700211 using TimerType =
212 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
213
Brad Bishopd1eac882018-03-29 10:34:05 -0400214 DeferrableCallback() = delete;
215 DeferrableCallback(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700216 DeferrableCallback(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400217 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
William A. Kennington III223c4092018-10-19 15:56:09 -0700218 DeferrableCallback& operator=(DeferrableCallback&&) = delete;
Brad Bishopd1eac882018-03-29 10:34:05 -0400219 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400220
Brad Bishopd1eac882018-03-29 10:34:05 -0400221 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
222 const std::chrono::microseconds& delay) :
223 ConditionalCallback<CallbackAccess>(graphEntry, cond),
224 delayInterval(delay), timer(nullptr)
George Liu3fe976c2022-06-21 09:37:04 +0800225 {}
Brad Bishop3539db62017-05-30 14:21:12 -0400226
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300227 /** @brief Start internal timer if the condition is satisfied.
228 *
229 * When the timer expires, it calls operator() for the
230 * ConditionalCallback with the context saved in
231 * DeferrableCallback instance.
232 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400233 void operator()(Context ctx) override
234 {
235 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400236 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400237 timer = std::make_unique<TimerType>(
William A. Kennington III223c4092018-10-19 15:56:09 -0700238 sdeventplus::Event::get_default(),
Brad Bishopd1eac882018-03-29 10:34:05 -0400239 // **INDENT-OFF**
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300240 [this](auto& source) {
241 // The timer uses the context saved on timer enable
242 this->ConditionalCallback<CallbackAccess>::operator()(
243 this->ctx);
Brad Bishopd1eac882018-03-29 10:34:05 -0400244 });
245 // **INDENT-ON**
Brad Bishop3539db62017-05-30 14:21:12 -0400246 }
247
Brad Bishopd1eac882018-03-29 10:34:05 -0400248 if (this->condition())
249 {
William A. Kennington III223c4092018-10-19 15:56:09 -0700250 if (!timer->isEnabled())
Brad Bishopd1eac882018-03-29 10:34:05 -0400251 {
252 // This is the first time the condition evaluated.
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300253 // Save current context for timer use.
254 this->ctx = ctx;
Brad Bishopd1eac882018-03-29 10:34:05 -0400255 // Start the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700256 timer->restartOnce(delayInterval);
Brad Bishopd1eac882018-03-29 10:34:05 -0400257 }
258 }
259 else
260 {
261 // The condition did not evaluate. Stop the countdown.
William A. Kennington III223c4092018-10-19 15:56:09 -0700262 timer->setEnabled(false);
Brad Bishopd1eac882018-03-29 10:34:05 -0400263 }
264 }
Brad Bishop3539db62017-05-30 14:21:12 -0400265
Brad Bishopd1eac882018-03-29 10:34:05 -0400266 private:
267 /** @brief The length to wait for the condition to stop evaluating. */
268 std::chrono::microseconds delayInterval;
269
270 /** @brief Delegated timer functions. */
271 std::unique_ptr<TimerType> timer;
Alexander Soldatov78a5df92018-11-23 14:37:50 +0300272
273 /** @brief Current context for timer. */
274 Context ctx;
Brad Bishop3539db62017-05-30 14:21:12 -0400275};
276
Brad Bishopc1283ae2017-05-20 21:42:38 -0400277} // namespace monitoring
278} // namespace dbus
279} // namespace phosphor