1 #pragma once 2 3 #include "callback.hpp" 4 #include "data_types.hpp" 5 6 #include <algorithm> 7 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. 29 * 30 * If the oneshot parameter is true, then this condition won't pass 31 * again until it fails at least once. 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, 47 const std::function<bool(T)>& _propertyOp, 48 bool oneshot = false) : 49 IndexedConditional(conditionIndex), 50 countOp(_countOp), 51 propertyOp(_propertyOp), 52 oneshot(oneshot) {} 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 { 64 const auto& storage = std::get<2>( 65 item.second); 66 // Don't count properties that don't exist. 67 if (std::get<0>(storage.get()).empty()) 68 { 69 return false; 70 } 71 const auto& value = any_ns::any_cast<T>( 72 std::get<0>(storage.get())); 73 return propertyOp(value); 74 }); 75 // *INDENT-ON* 76 77 // Now apply the count condition to the count. 78 auto result = countOp(count); 79 80 // If this was a oneshot and the the condition has already 81 // passed, then don't let it pass again until the condition 82 // has gone back to false. 83 if (oneshot && result && lastResult) 84 { 85 return false; 86 } 87 88 lastResult = result; 89 return result; 90 } 91 92 private: 93 /** @brief The comparison to perform on the count. */ 94 std::function<bool(size_t)> countOp; 95 /** @brief The comparison to perform on each property. */ 96 std::function<bool(T)> propertyOp; 97 /** @brief If the condition can be allowed to pass again 98 on subsequent checks that are also true. */ 99 const bool oneshot; 100 /** @brief The result of the previous check. */ 101 bool lastResult = false; 102 }; 103 } // namespace monitoring 104 } // namespace dbus 105 } // namespace phosphor 106