blob: e1e23259b27fc328fa42551a58e8cd43fd8119e8 [file] [log] [blame]
Brad Bishopc1283ae2017-05-20 21:42:38 -04001#pragma once
2
Brad Bishop3539db62017-05-30 14:21:12 -04003#include <chrono>
Brad Bishopc1283ae2017-05-20 21:42:38 -04004#include "data_types.hpp"
5
6namespace phosphor
7{
8namespace dbus
9{
10namespace monitoring
11{
12
13/** @class Callback
14 * @brief Callback interface.
15 *
16 * Callbacks of any type can be run.
17 */
18class Callback
19{
Brad Bishopd1eac882018-03-29 10:34:05 -040020 public:
21 Callback() = default;
22 Callback(const Callback&) = delete;
23 Callback(Callback&&) = default;
24 Callback& operator=(const Callback&) = delete;
25 Callback& operator=(Callback&&) = default;
26 virtual ~Callback() = default;
Brad Bishopc1283ae2017-05-20 21:42:38 -040027
Brad Bishopd1eac882018-03-29 10:34:05 -040028 /** @brief Run the callback.
29 * @param[in] ctx - caller context
30 * Context could be Startup or Signal
31 * Startup: Callback is called as part of process startup.
32 * Signal: Callback is called as part of watch condition has been met.
33 *
34 */
35 virtual void operator()(Context ctx) = 0;
Marri Devender Rao70aafbb2018-04-12 01:11:48 -050036
37 /** @brief Run the callback.
38 * @param[in] ctx - caller context
39 * Context could be Startup or Signal
40 * Startup: Callback is called as part of process startup.
41 * Signal: Callback is called as part of watch condition has been met.
42 * @param[in] msg - The sdbusplus signal message
43 */
44 virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
Brad Bishopc1283ae2017-05-20 21:42:38 -040045};
46
Brad Bishop4041d722017-05-21 10:06:07 -040047/** @class Conditional
48 * @brief Condition interface.
49 *
50 * Conditions of any type can be tested for true or false.
51 */
52class Conditional
53{
Brad Bishopd1eac882018-03-29 10:34:05 -040054 public:
55 Conditional() = default;
56 Conditional(const Conditional&) = delete;
57 Conditional(Conditional&&) = default;
58 Conditional& operator=(const Conditional&) = delete;
59 Conditional& operator=(Conditional&&) = default;
60 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040061
Brad Bishopd1eac882018-03-29 10:34:05 -040062 /** @brief Test the condition. */
63 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040064};
65
66/** @class IndexedConditional
67 * @brief Condition with an index.
68 */
69class IndexedConditional : public Conditional
70{
Brad Bishopd1eac882018-03-29 10:34:05 -040071 public:
72 IndexedConditional() = delete;
73 IndexedConditional(const IndexedConditional&) = delete;
74 IndexedConditional(IndexedConditional&&) = default;
75 IndexedConditional& operator=(const IndexedConditional&) = delete;
76 IndexedConditional& operator=(IndexedConditional&&) = default;
77 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040078
Brad Bishopd1eac882018-03-29 10:34:05 -040079 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
80 Conditional(), index(conditionIndex)
81 {
82 }
Brad Bishop4041d722017-05-21 10:06:07 -040083
Brad Bishopd1eac882018-03-29 10:34:05 -040084 /** @brief Test the condition. */
85 virtual bool operator()() override = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040086
Brad Bishopd1eac882018-03-29 10:34:05 -040087 protected:
88 /** @brief Property names and their associated storage. */
89 const PropertyIndex& index;
Brad Bishop4041d722017-05-21 10:06:07 -040090};
91
Brad Bishopc1283ae2017-05-20 21:42:38 -040092/** @class IndexedCallback
93 * @brief Callback with an index.
94 */
95class IndexedCallback : public Callback
96{
Brad Bishopd1eac882018-03-29 10:34:05 -040097 public:
98 IndexedCallback() = delete;
99 IndexedCallback(const IndexedCallback&) = delete;
100 IndexedCallback(IndexedCallback&&) = default;
101 IndexedCallback& operator=(const IndexedCallback&) = delete;
102 IndexedCallback& operator=(IndexedCallback&&) = default;
103 virtual ~IndexedCallback() = default;
104 explicit IndexedCallback(const PropertyIndex& callbackIndex) :
105 Callback(), index(callbackIndex)
106 {
107 }
Brad Bishopc1283ae2017-05-20 21:42:38 -0400108
Brad Bishopd1eac882018-03-29 10:34:05 -0400109 /** @brief Run the callback. */
110 virtual void operator()(Context ctx) override = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400111
Brad Bishopd1eac882018-03-29 10:34:05 -0400112 protected:
113 /** @brief Property names and their associated storage. */
114 const PropertyIndex& index;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400115};
116
Brad Bishop49e66172017-05-23 19:16:21 -0400117/** @class GroupOfCallbacks
118 * @brief Invoke multiple callbacks.
119 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500120 * A group of callbacks is implemented as a vector of array indices
Brad Bishop49e66172017-05-23 19:16:21 -0400121 * into an external array of callbacks. The group function call
Gunnar Mills78199b42017-10-25 16:30:18 -0500122 * operator traverses the vector of indices, invoking each
Brad Bishop49e66172017-05-23 19:16:21 -0400123 * callback.
124 *
125 * @tparam CallbackAccess - Access to the array of callbacks.
126 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400127template <typename CallbackAccess> class GroupOfCallbacks : public Callback
Brad Bishop49e66172017-05-23 19:16:21 -0400128{
Brad Bishopd1eac882018-03-29 10:34:05 -0400129 public:
130 GroupOfCallbacks() = delete;
131 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
132 GroupOfCallbacks(GroupOfCallbacks&&) = default;
133 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
134 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
135 ~GroupOfCallbacks() = default;
136 explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
137 graph(graphEntry)
138 {
139 }
Brad Bishop49e66172017-05-23 19:16:21 -0400140
Brad Bishopd1eac882018-03-29 10:34:05 -0400141 /** @brief Run the callbacks. */
142 void operator()(Context ctx) override
143 {
144 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400145 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400146 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400147 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400148 }
Brad Bishop49e66172017-05-23 19:16:21 -0400149
Brad Bishopd1eac882018-03-29 10:34:05 -0400150 private:
151 /** @brief The offsets of the callbacks in the group. */
152 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400153};
154
Brad Bishop4041d722017-05-21 10:06:07 -0400155/** @class ConditionalCallback
156 * @brief Callback adaptor that asssociates a condition with a callback.
157 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400158template <typename CallbackAccess> class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400159{
Brad Bishopd1eac882018-03-29 10:34:05 -0400160 public:
161 ConditionalCallback() = delete;
162 ConditionalCallback(const ConditionalCallback&) = delete;
163 ConditionalCallback(ConditionalCallback&&) = default;
164 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
165 ConditionalCallback& operator=(ConditionalCallback&&) = default;
166 virtual ~ConditionalCallback() = default;
167 ConditionalCallback(const std::vector<size_t>& graphEntry,
168 Conditional& cond) :
169 graph(graphEntry),
170 condition(cond)
171 {
172 }
Brad Bishop4041d722017-05-21 10:06:07 -0400173
Brad Bishopd1eac882018-03-29 10:34:05 -0400174 /** @brief Run the callback if the condition is satisfied. */
175 virtual void operator()(Context ctx) override
176 {
177 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400178 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400179 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400180 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400181 }
Brad Bishop4041d722017-05-21 10:06:07 -0400182
Brad Bishopd1eac882018-03-29 10:34:05 -0400183 protected:
184 /** @brief The index of the callback to conditionally invoke. */
185 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400186
Brad Bishopd1eac882018-03-29 10:34:05 -0400187 /** @brief The condition to test. */
188 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400189};
190
Brad Bishop3539db62017-05-30 14:21:12 -0400191/** @class DeferrableCallback
192 *
193 * Deferrable callbacks wait a configurable period before
194 * invoking their associated callback.
195 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500196 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400197 * condition is tested again before the timer expires and it is not
198 * met cancel the timer. If the timer expires invoke the associated
199 * callback.
200 *
201 * @tparam CallbackAccess - Provide access to callback group instances.
202 * @tparam TimerType - Delegated timer access methods.
203 */
204template <typename CallbackAccess, typename TimerType>
205class DeferrableCallback : public ConditionalCallback<CallbackAccess>
206{
Brad Bishopd1eac882018-03-29 10:34:05 -0400207 public:
208 DeferrableCallback() = delete;
209 DeferrableCallback(const DeferrableCallback&) = delete;
210 DeferrableCallback(DeferrableCallback&&) = default;
211 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
212 DeferrableCallback& operator=(DeferrableCallback&&) = default;
213 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400214
Brad Bishopd1eac882018-03-29 10:34:05 -0400215 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
216 const std::chrono::microseconds& delay) :
217 ConditionalCallback<CallbackAccess>(graphEntry, cond),
218 delayInterval(delay), timer(nullptr)
219 {
220 }
Brad Bishop3539db62017-05-30 14:21:12 -0400221
Brad Bishopd1eac882018-03-29 10:34:05 -0400222 void operator()(Context ctx) override
223 {
224 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400225 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400226 timer = std::make_unique<TimerType>(
227 // **INDENT-OFF**
228 [ctx, this](auto& source) {
229 this->ConditionalCallback<CallbackAccess>::operator()(ctx);
230 });
231 // **INDENT-ON**
232 timer->disable();
Brad Bishop3539db62017-05-30 14:21:12 -0400233 }
234
Brad Bishopd1eac882018-03-29 10:34:05 -0400235 if (this->condition())
236 {
237 if (!timer->enabled())
238 {
239 // This is the first time the condition evaluated.
240 // Start the countdown.
241 timer->update(timer->now() + delayInterval);
242 timer->enable();
243 }
244 }
245 else
246 {
247 // The condition did not evaluate. Stop the countdown.
248 timer->disable();
249 }
250 }
Brad Bishop3539db62017-05-30 14:21:12 -0400251
Brad Bishopd1eac882018-03-29 10:34:05 -0400252 private:
253 /** @brief The length to wait for the condition to stop evaluating. */
254 std::chrono::microseconds delayInterval;
255
256 /** @brief Delegated timer functions. */
257 std::unique_ptr<TimerType> timer;
Brad Bishop3539db62017-05-30 14:21:12 -0400258};
259
Brad Bishopc1283ae2017-05-20 21:42:38 -0400260} // namespace monitoring
261} // namespace dbus
262} // namespace phosphor