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