| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 1 | #pragma once | 
|  | 2 |  | 
|  | 3 | #include "callback.hpp" | 
|  | 4 | #include "data_types.hpp" | 
|  | 5 |  | 
| Ratan Gupta | 882d741 | 2018-02-19 23:43:44 +0530 | [diff] [blame] | 6 | #include <algorithm> | 
|  | 7 |  | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 8 | namespace phosphor | 
|  | 9 | { | 
|  | 10 | namespace dbus | 
|  | 11 | { | 
|  | 12 | namespace 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 Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 29 | * | 
|  | 30 | *  If the oneshot parameter is true, then this condition won't pass | 
|  | 31 | *  again until it fails at least once. | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 32 | */ | 
|  | 33 | template <typename T> | 
|  | 34 | class 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 Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 47 | const std::function<bool(T)>& _propertyOp, | 
|  | 48 | bool oneshot = false) : | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 49 | IndexedConditional(conditionIndex), | 
|  | 50 | countOp(_countOp), | 
| Matt Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 51 | propertyOp(_propertyOp), | 
|  | 52 | oneshot(oneshot) {} | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 53 |  | 
|  | 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 Spinler | 05a2ac3 | 2018-02-19 13:52:59 -0600 | [diff] [blame^] | 64 | //Get the property value from storage[0], | 
|  | 65 | //and save the op result in storage[1]. | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 66 | const auto& storage = std::get<2>( | 
|  | 67 | item.second); | 
|  | 68 | // Don't count properties that don't exist. | 
| Matt Spinler | abe43ab | 2018-02-19 13:34:43 -0600 | [diff] [blame] | 69 | if (std::get<0>(storage.get()).empty()) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 70 | { | 
|  | 71 | return false; | 
|  | 72 | } | 
|  | 73 | const auto& value = any_ns::any_cast<T>( | 
| Matt Spinler | abe43ab | 2018-02-19 13:34:43 -0600 | [diff] [blame] | 74 | std::get<0>(storage.get())); | 
| Matt Spinler | 05a2ac3 | 2018-02-19 13:52:59 -0600 | [diff] [blame^] | 75 | auto r = propertyOp(value); | 
|  | 76 |  | 
|  | 77 | std::get<1>(storage.get()) = r; | 
|  | 78 |  | 
|  | 79 | return r; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 80 | }); | 
|  | 81 | // *INDENT-ON* | 
|  | 82 |  | 
|  | 83 | // Now apply the count condition to the count. | 
| Matt Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 84 | 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 Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 96 | } | 
|  | 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 Spinler | c458dee | 2018-02-19 13:09:10 -0600 | [diff] [blame] | 103 | /** @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 Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 108 | }; | 
|  | 109 | } // namespace monitoring | 
|  | 110 | } // namespace dbus | 
|  | 111 | } // namespace phosphor |