blob: bde8a91ea548a3acd7624a9ab987e23d6de6766a [file] [log] [blame]
Brad Bishop4041d722017-05-21 10:06:07 -04001#pragma once
2
3#include "callback.hpp"
4#include "data_types.hpp"
5
Ratan Gupta882d7412018-02-19 23:43:44 +05306#include <algorithm>
7
Brad Bishop4041d722017-05-21 10:06:07 -04008namespace phosphor
9{
10namespace dbus
11{
12namespace monitoring
13{
14
15/** @class CountCondition
16 * @brief Count properties that satisfy a condition.
17 *
18 * When invoked, a count class instance performs its condition
19 * test in two passes.
20 *
21 * In pass one, apply a C++ relational operator to the value of
22 * each property in the index and a value provided by the
23 * configuration file.
24 *
25 * Count the number of properties that pass the test in pass
26 * one. In pass two, apply a second C++ relational operator
27 * to the number of properties that pass the test from pass one
28 * to a count provided by the configuration file.
Matt Spinlerc458dee2018-02-19 13:09:10 -060029 *
30 * If the oneshot parameter is true, then this condition won't pass
31 * again until it fails at least once.
Brad Bishop4041d722017-05-21 10:06:07 -040032 */
33template <typename T>
34class CountCondition : public IndexedConditional
35{
36 public:
37 CountCondition() = delete;
38 CountCondition(const CountCondition&) = default;
39 CountCondition(CountCondition&&) = default;
40 CountCondition& operator=(const CountCondition&) = default;
41 CountCondition& operator=(CountCondition&&) = default;
42 ~CountCondition() = default;
43
44 CountCondition(
45 const PropertyIndex& conditionIndex,
46 const std::function<bool(size_t)>& _countOp,
Matt Spinlerc458dee2018-02-19 13:09:10 -060047 const std::function<bool(T)>& _propertyOp,
48 bool oneshot = false) :
Brad Bishop4041d722017-05-21 10:06:07 -040049 IndexedConditional(conditionIndex),
50 countOp(_countOp),
Matt Spinlerc458dee2018-02-19 13:09:10 -060051 propertyOp(_propertyOp),
52 oneshot(oneshot) {}
Brad Bishop4041d722017-05-21 10:06:07 -040053
54 bool operator()() override
55 {
56 // Count the number of properties in the index that
57 // pass the condition specified in the config file.
58 auto count = std::count_if(
59 index.cbegin(),
60 index.cend(),
61 [this](const auto & item)
62 // *INDENT-OFF*
63 {
Matt Spinler05a2ac32018-02-19 13:52:59 -060064 //Get the property value from storage[0],
65 //and save the op result in storage[1].
Brad Bishop4041d722017-05-21 10:06:07 -040066 const auto& storage = std::get<2>(
67 item.second);
68 // Don't count properties that don't exist.
Matt Spinlerabe43ab2018-02-19 13:34:43 -060069 if (std::get<0>(storage.get()).empty())
Brad Bishop4041d722017-05-21 10:06:07 -040070 {
71 return false;
72 }
73 const auto& value = any_ns::any_cast<T>(
Matt Spinlerabe43ab2018-02-19 13:34:43 -060074 std::get<0>(storage.get()));
Matt Spinler05a2ac32018-02-19 13:52:59 -060075 auto r = propertyOp(value);
76
77 std::get<1>(storage.get()) = r;
78
79 return r;
Brad Bishop4041d722017-05-21 10:06:07 -040080 });
81 // *INDENT-ON*
82
83 // Now apply the count condition to the count.
Matt Spinlerc458dee2018-02-19 13:09:10 -060084 auto result = countOp(count);
85
86 // If this was a oneshot and the the condition has already
87 // passed, then don't let it pass again until the condition
88 // has gone back to false.
89 if (oneshot && result && lastResult)
90 {
91 return false;
92 }
93
94 lastResult = result;
95 return result;
Brad Bishop4041d722017-05-21 10:06:07 -040096 }
97
98 private:
99 /** @brief The comparison to perform on the count. */
100 std::function<bool(size_t)> countOp;
101 /** @brief The comparison to perform on each property. */
102 std::function<bool(T)> propertyOp;
Matt Spinlerc458dee2018-02-19 13:09:10 -0600103 /** @brief If the condition can be allowed to pass again
104 on subsequent checks that are also true. */
105 const bool oneshot;
106 /** @brief The result of the previous check. */
107 bool lastResult = false;
Brad Bishop4041d722017-05-21 10:06:07 -0400108};
109} // namespace monitoring
110} // namespace dbus
111} // namespace phosphor