14041d720SBrad Bishop #pragma once 24041d720SBrad Bishop 34041d720SBrad Bishop #include "callback.hpp" 44041d720SBrad Bishop #include "data_types.hpp" 54041d720SBrad Bishop 6882d741cSRatan Gupta #include <algorithm> 7f3367686SAndrew Geissler #include <cstddef> 835e75f0aSBrad Bishop #include <functional> 9882d741cSRatan Gupta 104041d720SBrad Bishop namespace phosphor 114041d720SBrad Bishop { 124041d720SBrad Bishop namespace dbus 134041d720SBrad Bishop { 144041d720SBrad Bishop namespace monitoring 154041d720SBrad Bishop { 164041d720SBrad Bishop 174041d720SBrad Bishop /** @class CountCondition 184041d720SBrad Bishop * @brief Count properties that satisfy a condition. 194041d720SBrad Bishop * 204041d720SBrad Bishop * When invoked, a count class instance performs its condition 214041d720SBrad Bishop * test in two passes. 224041d720SBrad Bishop * 234041d720SBrad Bishop * In pass one, apply a C++ relational operator to the value of 244041d720SBrad Bishop * each property in the index and a value provided by the 254041d720SBrad Bishop * configuration file. 264041d720SBrad Bishop * 274041d720SBrad Bishop * Count the number of properties that pass the test in pass 284041d720SBrad Bishop * one. In pass two, apply a second C++ relational operator 294041d720SBrad Bishop * to the number of properties that pass the test from pass one 304041d720SBrad Bishop * to a count provided by the configuration file. 31c458deeaSMatt Spinler * 32c458deeaSMatt Spinler * If the oneshot parameter is true, then this condition won't pass 33c458deeaSMatt Spinler * again until it fails at least once. 344041d720SBrad Bishop */ 353d6d3182SPatrick Venture template <typename T> 363d6d3182SPatrick Venture class CountCondition : public IndexedConditional 374041d720SBrad Bishop { 384041d720SBrad Bishop public: 394041d720SBrad Bishop CountCondition() = delete; 404041d720SBrad Bishop CountCondition(const CountCondition&) = default; 414041d720SBrad Bishop CountCondition(CountCondition&&) = default; 424041d720SBrad Bishop CountCondition& operator=(const CountCondition&) = default; 434041d720SBrad Bishop CountCondition& operator=(CountCondition&&) = default; 444041d720SBrad Bishop ~CountCondition() = default; 454041d720SBrad Bishop CountCondition(const PropertyIndex & conditionIndex,const std::function<bool (size_t)> & _countOp,const std::function<bool (T)> & _propertyOp,bool oneshot=false)46d1eac88dSBrad Bishop CountCondition(const PropertyIndex& conditionIndex, 474041d720SBrad Bishop const std::function<bool(size_t)>& _countOp, 48c458deeaSMatt Spinler const std::function<bool(T)>& _propertyOp, 49c458deeaSMatt Spinler bool oneshot = false) : 50*eab4f8c0SPatrick Williams IndexedConditional(conditionIndex), countOp(_countOp), 51*eab4f8c0SPatrick Williams propertyOp(_propertyOp), oneshot(oneshot) 523fe976ccSGeorge Liu {} 534041d720SBrad Bishop operator ()()544041d720SBrad Bishop bool operator()() override 554041d720SBrad Bishop { 564041d720SBrad Bishop // Count the number of properties in the index that 574041d720SBrad Bishop // pass the condition specified in the config file. 58*eab4f8c0SPatrick Williams auto count = std::count_if( 59*eab4f8c0SPatrick Williams index.cbegin(), index.cend(), 604041d720SBrad Bishop [this](const auto& item) 614041d720SBrad Bishop // *INDENT-OFF* 624041d720SBrad Bishop { 6305a2ac3aSMatt Spinler // Get the property value from storage[0], 6405a2ac3aSMatt Spinler // and save the op result in storage[1]. 65d1eac88dSBrad Bishop const auto& storage = std::get<storageIndex>(item.second); 664041d720SBrad Bishop // Don't count properties that don't exist. 6726dc0bcbSPatrick Williams if (!std::get<valueIndex>(storage.get()).has_value()) 684041d720SBrad Bishop { 694041d720SBrad Bishop return false; 704041d720SBrad Bishop } 71d1eac88dSBrad Bishop const auto& value = 7226dc0bcbSPatrick Williams std::any_cast<T>(std::get<valueIndex>(storage.get())); 7305a2ac3aSMatt Spinler auto r = propertyOp(value); 7405a2ac3aSMatt Spinler 751abcb06bSMatt Spinler std::get<resultIndex>(storage.get()) = r; 7605a2ac3aSMatt Spinler 7705a2ac3aSMatt Spinler return r; 784041d720SBrad Bishop }); 794041d720SBrad Bishop // *INDENT-ON* 804041d720SBrad Bishop 814041d720SBrad Bishop // Now apply the count condition to the count. 82c458deeaSMatt Spinler auto result = countOp(count); 83c458deeaSMatt Spinler 84c458deeaSMatt Spinler // If this was a oneshot and the the condition has already 85c458deeaSMatt Spinler // passed, then don't let it pass again until the condition 86c458deeaSMatt Spinler // has gone back to false. 87c458deeaSMatt Spinler if (oneshot && result && lastResult) 88c458deeaSMatt Spinler { 89c458deeaSMatt Spinler return false; 90c458deeaSMatt Spinler } 91c458deeaSMatt Spinler 92c458deeaSMatt Spinler lastResult = result; 93c458deeaSMatt Spinler return result; 944041d720SBrad Bishop } 954041d720SBrad Bishop 964041d720SBrad Bishop private: 974041d720SBrad Bishop /** @brief The comparison to perform on the count. */ 984041d720SBrad Bishop std::function<bool(size_t)> countOp; 994041d720SBrad Bishop /** @brief The comparison to perform on each property. */ 1004041d720SBrad Bishop std::function<bool(T)> propertyOp; 101c458deeaSMatt Spinler /** @brief If the condition can be allowed to pass again 102c458deeaSMatt Spinler on subsequent checks that are also true. */ 103c458deeaSMatt Spinler const bool oneshot; 104c458deeaSMatt Spinler /** @brief The result of the previous check. */ 105c458deeaSMatt Spinler bool lastResult = false; 1064041d720SBrad Bishop }; 1074041d720SBrad Bishop } // namespace monitoring 1084041d720SBrad Bishop } // namespace dbus 1094041d720SBrad Bishop } // namespace phosphor 110