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