xref: /openbmc/phosphor-dbus-monitor/src/count.hpp (revision eab4f8c0a047e1aaedf74d6144d83132d1b003de)
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