blob: c79dcd0e8222b86c8a27fe73b03449b81a3aee40 [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>
6
Brad Bishopc1283ae2017-05-20 21:42:38 -04007namespace phosphor
8{
9namespace dbus
10{
11namespace monitoring
12{
13
14/** @class Callback
15 * @brief Callback interface.
16 *
17 * Callbacks of any type can be run.
18 */
19class Callback
20{
Brad Bishopd1eac882018-03-29 10:34:05 -040021 public:
22 Callback() = default;
23 Callback(const Callback&) = delete;
24 Callback(Callback&&) = default;
25 Callback& operator=(const Callback&) = delete;
26 Callback& operator=(Callback&&) = default;
27 virtual ~Callback() = default;
Brad Bishopc1283ae2017-05-20 21:42:38 -040028
Brad Bishopd1eac882018-03-29 10:34:05 -040029 /** @brief Run the callback.
30 * @param[in] ctx - caller context
31 * Context could be Startup or Signal
32 * Startup: Callback is called as part of process startup.
33 * Signal: Callback is called as part of watch condition has been met.
34 *
35 */
36 virtual void operator()(Context ctx) = 0;
Marri Devender Rao70aafbb2018-04-12 01:11:48 -050037
38 /** @brief Run the callback.
39 * @param[in] ctx - caller context
40 * Context could be Startup or Signal
41 * Startup: Callback is called as part of process startup.
42 * Signal: Callback is called as part of watch condition has been met.
43 * @param[in] msg - The sdbusplus signal message
44 */
45 virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
Brad Bishopc1283ae2017-05-20 21:42:38 -040046};
47
Brad Bishop4041d722017-05-21 10:06:07 -040048/** @class Conditional
49 * @brief Condition interface.
50 *
51 * Conditions of any type can be tested for true or false.
52 */
53class Conditional
54{
Brad Bishopd1eac882018-03-29 10:34:05 -040055 public:
56 Conditional() = default;
57 Conditional(const Conditional&) = delete;
58 Conditional(Conditional&&) = default;
59 Conditional& operator=(const Conditional&) = delete;
60 Conditional& operator=(Conditional&&) = default;
61 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040062
Brad Bishopd1eac882018-03-29 10:34:05 -040063 /** @brief Test the condition. */
64 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040065};
66
67/** @class IndexedConditional
68 * @brief Condition with an index.
69 */
70class IndexedConditional : public Conditional
71{
Brad Bishopd1eac882018-03-29 10:34:05 -040072 public:
73 IndexedConditional() = delete;
74 IndexedConditional(const IndexedConditional&) = delete;
75 IndexedConditional(IndexedConditional&&) = default;
76 IndexedConditional& operator=(const IndexedConditional&) = delete;
77 IndexedConditional& operator=(IndexedConditional&&) = default;
78 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040079
Brad Bishopd1eac882018-03-29 10:34:05 -040080 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
81 Conditional(), index(conditionIndex)
82 {
83 }
Brad Bishop4041d722017-05-21 10:06:07 -040084
Brad Bishopd1eac882018-03-29 10:34:05 -040085 /** @brief Test the condition. */
86 virtual bool operator()() override = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040087
Brad Bishopd1eac882018-03-29 10:34:05 -040088 protected:
89 /** @brief Property names and their associated storage. */
90 const PropertyIndex& index;
Brad Bishop4041d722017-05-21 10:06:07 -040091};
92
Brad Bishopc1283ae2017-05-20 21:42:38 -040093/** @class IndexedCallback
94 * @brief Callback with an index.
95 */
96class IndexedCallback : public Callback
97{
Brad Bishopd1eac882018-03-29 10:34:05 -040098 public:
99 IndexedCallback() = delete;
100 IndexedCallback(const IndexedCallback&) = delete;
101 IndexedCallback(IndexedCallback&&) = default;
102 IndexedCallback& operator=(const IndexedCallback&) = delete;
103 IndexedCallback& operator=(IndexedCallback&&) = default;
104 virtual ~IndexedCallback() = default;
105 explicit IndexedCallback(const PropertyIndex& callbackIndex) :
106 Callback(), index(callbackIndex)
107 {
108 }
Brad Bishopc1283ae2017-05-20 21:42:38 -0400109
Brad Bishopd1eac882018-03-29 10:34:05 -0400110 /** @brief Run the callback. */
111 virtual void operator()(Context ctx) override = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400112
Brad Bishopd1eac882018-03-29 10:34:05 -0400113 protected:
114 /** @brief Property names and their associated storage. */
115 const PropertyIndex& index;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400116};
117
Brad Bishop49e66172017-05-23 19:16:21 -0400118/** @class GroupOfCallbacks
119 * @brief Invoke multiple callbacks.
120 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500121 * A group of callbacks is implemented as a vector of array indices
Brad Bishop49e66172017-05-23 19:16:21 -0400122 * into an external array of callbacks. The group function call
Gunnar Mills78199b42017-10-25 16:30:18 -0500123 * operator traverses the vector of indices, invoking each
Brad Bishop49e66172017-05-23 19:16:21 -0400124 * callback.
125 *
126 * @tparam CallbackAccess - Access to the array of callbacks.
127 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700128template <typename CallbackAccess>
129class GroupOfCallbacks : public Callback
Brad Bishop49e66172017-05-23 19:16:21 -0400130{
Brad Bishopd1eac882018-03-29 10:34:05 -0400131 public:
132 GroupOfCallbacks() = delete;
133 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
134 GroupOfCallbacks(GroupOfCallbacks&&) = default;
135 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
136 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
137 ~GroupOfCallbacks() = default;
138 explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
139 graph(graphEntry)
140 {
141 }
Brad Bishop49e66172017-05-23 19:16:21 -0400142
Brad Bishopd1eac882018-03-29 10:34:05 -0400143 /** @brief Run the callbacks. */
144 void operator()(Context ctx) override
145 {
146 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400147 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400148 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400149 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400150 }
Brad Bishop49e66172017-05-23 19:16:21 -0400151
Brad Bishopd1eac882018-03-29 10:34:05 -0400152 private:
153 /** @brief The offsets of the callbacks in the group. */
154 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400155};
156
Brad Bishop4041d722017-05-21 10:06:07 -0400157/** @class ConditionalCallback
158 * @brief Callback adaptor that asssociates a condition with a callback.
159 */
Patrick Venture3d6d3182018-08-31 09:33:09 -0700160template <typename CallbackAccess>
161class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400162{
Brad Bishopd1eac882018-03-29 10:34:05 -0400163 public:
164 ConditionalCallback() = delete;
165 ConditionalCallback(const ConditionalCallback&) = delete;
166 ConditionalCallback(ConditionalCallback&&) = default;
167 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
168 ConditionalCallback& operator=(ConditionalCallback&&) = default;
169 virtual ~ConditionalCallback() = default;
170 ConditionalCallback(const std::vector<size_t>& graphEntry,
171 Conditional& cond) :
172 graph(graphEntry),
173 condition(cond)
174 {
175 }
Brad Bishop4041d722017-05-21 10:06:07 -0400176
Brad Bishopd1eac882018-03-29 10:34:05 -0400177 /** @brief Run the callback if the condition is satisfied. */
178 virtual void operator()(Context ctx) override
179 {
180 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400181 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400182 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400183 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400184 }
Brad Bishop4041d722017-05-21 10:06:07 -0400185
Brad Bishopd1eac882018-03-29 10:34:05 -0400186 protected:
187 /** @brief The index of the callback to conditionally invoke. */
188 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400189
Brad Bishopd1eac882018-03-29 10:34:05 -0400190 /** @brief The condition to test. */
191 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400192};
193
Brad Bishop3539db62017-05-30 14:21:12 -0400194/** @class DeferrableCallback
195 *
196 * Deferrable callbacks wait a configurable period before
197 * invoking their associated callback.
198 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500199 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400200 * condition is tested again before the timer expires and it is not
201 * met cancel the timer. If the timer expires invoke the associated
202 * callback.
203 *
204 * @tparam CallbackAccess - Provide access to callback group instances.
205 * @tparam TimerType - Delegated timer access methods.
206 */
207template <typename CallbackAccess, typename TimerType>
208class DeferrableCallback : public ConditionalCallback<CallbackAccess>
209{
Brad Bishopd1eac882018-03-29 10:34:05 -0400210 public:
211 DeferrableCallback() = delete;
212 DeferrableCallback(const DeferrableCallback&) = delete;
213 DeferrableCallback(DeferrableCallback&&) = default;
214 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
215 DeferrableCallback& operator=(DeferrableCallback&&) = default;
216 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400217
Brad Bishopd1eac882018-03-29 10:34:05 -0400218 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
219 const std::chrono::microseconds& delay) :
220 ConditionalCallback<CallbackAccess>(graphEntry, cond),
221 delayInterval(delay), timer(nullptr)
222 {
223 }
Brad Bishop3539db62017-05-30 14:21:12 -0400224
Brad Bishopd1eac882018-03-29 10:34:05 -0400225 void operator()(Context ctx) override
226 {
227 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400228 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400229 timer = std::make_unique<TimerType>(
230 // **INDENT-OFF**
231 [ctx, this](auto& source) {
232 this->ConditionalCallback<CallbackAccess>::operator()(ctx);
233 });
234 // **INDENT-ON**
235 timer->disable();
Brad Bishop3539db62017-05-30 14:21:12 -0400236 }
237
Brad Bishopd1eac882018-03-29 10:34:05 -0400238 if (this->condition())
239 {
240 if (!timer->enabled())
241 {
242 // This is the first time the condition evaluated.
243 // Start the countdown.
244 timer->update(timer->now() + delayInterval);
245 timer->enable();
246 }
247 }
248 else
249 {
250 // The condition did not evaluate. Stop the countdown.
251 timer->disable();
252 }
253 }
Brad Bishop3539db62017-05-30 14:21:12 -0400254
Brad Bishopd1eac882018-03-29 10:34:05 -0400255 private:
256 /** @brief The length to wait for the condition to stop evaluating. */
257 std::chrono::microseconds delayInterval;
258
259 /** @brief Delegated timer functions. */
260 std::unique_ptr<TimerType> timer;
Brad Bishop3539db62017-05-30 14:21:12 -0400261};
262
Brad Bishopc1283ae2017-05-20 21:42:38 -0400263} // namespace monitoring
264} // namespace dbus
265} // namespace phosphor