Matt Spinler | 0023743 | 2020-10-14 10:36:41 -0500 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include "types.hpp" |
| 4 | |
| 5 | #include <algorithm> |
| 6 | #include <vector> |
| 7 | |
| 8 | namespace phosphor::fan::monitor |
| 9 | { |
| 10 | |
| 11 | /** |
| 12 | * @class PowerOffCause |
| 13 | * |
| 14 | * This abstract class provides a satisfied() pure virtual method |
| 15 | * that is called to know if the system should be powered off due |
| 16 | * to fan health. Each type of class that is derived from this |
| 17 | * one provides different behavior, for example one may count |
| 18 | * missing fans, and another may count nonfunctional fans. |
| 19 | */ |
| 20 | class PowerOffCause |
| 21 | { |
| 22 | public: |
| 23 | PowerOffCause() = delete; |
| 24 | virtual ~PowerOffCause() = default; |
| 25 | PowerOffCause(const PowerOffCause&) = delete; |
| 26 | PowerOffCause& operator=(const PowerOffCause&) = delete; |
| 27 | PowerOffCause(PowerOffCause&&) = delete; |
| 28 | PowerOffCause& operator=(PowerOffCause&&) = delete; |
| 29 | |
| 30 | /** |
| 31 | * @brief Constructor |
| 32 | * |
| 33 | * @param[in] count - The number of items that is compared |
| 34 | * against in the derived class. |
| 35 | * @param[in] name - The name of the cause. Used for tracing. |
| 36 | */ |
| 37 | PowerOffCause(size_t count, const std::string& name) : |
| 38 | _count(count), _name(std::to_string(count) + " " + name) |
| 39 | {} |
| 40 | |
| 41 | /** |
| 42 | * @brief Pure virtual that says if the system should be powered |
| 43 | * off based on the fan health. |
| 44 | * |
| 45 | * @param[in] fanHealth - The FanHealth map |
| 46 | * |
| 47 | * @return bool - If system should be powered off |
| 48 | */ |
| 49 | virtual bool satisfied(const FanHealth& fanHealth) = 0; |
| 50 | |
| 51 | /** |
| 52 | * @brief Returns the name of the cause. |
| 53 | * |
| 54 | * For example: "3 Missing Fans" |
| 55 | * |
| 56 | * @return std::string - The name |
| 57 | */ |
| 58 | const std::string& name() const |
| 59 | { |
| 60 | return _name; |
| 61 | } |
| 62 | |
| 63 | protected: |
| 64 | /** |
| 65 | * @brief The number of fan health items that the derived |
| 66 | * class uses to compare to the fan health status. |
| 67 | * For example, a 3 for 3 missing fans. |
| 68 | */ |
| 69 | const size_t _count; |
| 70 | |
| 71 | /** |
| 72 | * @brief The cause name |
| 73 | */ |
| 74 | const std::string _name; |
| 75 | }; |
| 76 | |
| 77 | /** |
| 78 | * @class MissingFanFRUCause |
| 79 | * |
| 80 | * This class provides a satisfied() method that checks for |
| 81 | * missing fans in the fan health map. |
| 82 | * |
| 83 | */ |
| 84 | class MissingFanFRUCause : public PowerOffCause |
| 85 | { |
| 86 | public: |
| 87 | MissingFanFRUCause() = delete; |
| 88 | ~MissingFanFRUCause() = default; |
| 89 | MissingFanFRUCause(const MissingFanFRUCause&) = delete; |
| 90 | MissingFanFRUCause& operator=(const MissingFanFRUCause&) = delete; |
| 91 | MissingFanFRUCause(MissingFanFRUCause&&) = delete; |
| 92 | MissingFanFRUCause& operator=(MissingFanFRUCause&&) = delete; |
| 93 | |
| 94 | /** |
| 95 | * @brief Constructor |
| 96 | * |
| 97 | * @param[in] count - The minimum number of fans that must be |
| 98 | * missing to need a power off. |
| 99 | */ |
| 100 | explicit MissingFanFRUCause(size_t count) : |
| 101 | PowerOffCause(count, "Missing Fan FRUs") |
| 102 | {} |
| 103 | |
| 104 | /** |
| 105 | * @brief Returns true if 'count' or more fans are missing |
| 106 | * to require a power off. |
| 107 | * |
| 108 | * @param[in] fanHealth - The FanHealth map |
| 109 | */ |
| 110 | bool satisfied(const FanHealth& fanHealth) override |
| 111 | { |
Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 112 | size_t count = std::count_if( |
| 113 | fanHealth.begin(), fanHealth.end(), [](const auto& fan) { |
| 114 | return !std::get<presentHealthPos>(fan.second); |
| 115 | }); |
Matt Spinler | 0023743 | 2020-10-14 10:36:41 -0500 | [diff] [blame] | 116 | |
| 117 | return count >= _count; |
| 118 | } |
| 119 | }; |
| 120 | |
| 121 | /** |
| 122 | * @class NonfuncFanRotorCause |
| 123 | * |
| 124 | * This class provides a satisfied() method that checks for |
| 125 | * nonfunctional fan rotors in the fan health map. |
| 126 | */ |
| 127 | class NonfuncFanRotorCause : public PowerOffCause |
| 128 | { |
| 129 | public: |
| 130 | NonfuncFanRotorCause() = delete; |
| 131 | ~NonfuncFanRotorCause() = default; |
| 132 | NonfuncFanRotorCause(const NonfuncFanRotorCause&) = delete; |
| 133 | NonfuncFanRotorCause& operator=(const NonfuncFanRotorCause&) = delete; |
| 134 | NonfuncFanRotorCause(NonfuncFanRotorCause&&) = delete; |
| 135 | NonfuncFanRotorCause& operator=(NonfuncFanRotorCause&&) = delete; |
| 136 | |
| 137 | /** |
| 138 | * @brief Constructor |
| 139 | * |
| 140 | * @param[in] count - The minimum number of rotors that must be |
Matt Spinler | 4c62fc7 | 2024-02-14 16:10:19 -0600 | [diff] [blame] | 141 | * nonfunctional to need a power off. |
Matt Spinler | 0023743 | 2020-10-14 10:36:41 -0500 | [diff] [blame] | 142 | */ |
| 143 | explicit NonfuncFanRotorCause(size_t count) : |
| 144 | PowerOffCause(count, "Nonfunctional Fan Rotors") |
| 145 | {} |
| 146 | |
| 147 | /** |
| 148 | * @brief Returns true if 'count' or more rotors are nonfunctional |
| 149 | * to require a power off. |
| 150 | * |
| 151 | * @param[in] fanHealth - The FanHealth map |
| 152 | */ |
| 153 | bool satisfied(const FanHealth& fanHealth) override |
| 154 | { |
Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 155 | size_t count = std::accumulate( |
| 156 | fanHealth.begin(), fanHealth.end(), 0, |
| 157 | [](int sum, const auto& fan) { |
| 158 | const auto& tachs = std::get<sensorFuncHealthPos>(fan.second); |
| 159 | auto nonFuncTachs = |
| 160 | std::count_if(tachs.begin(), tachs.end(), |
| 161 | [](bool tach) { return !tach; }); |
| 162 | return sum + nonFuncTachs; |
| 163 | }); |
Matt Spinler | 0023743 | 2020-10-14 10:36:41 -0500 | [diff] [blame] | 164 | |
| 165 | return count >= _count; |
| 166 | } |
| 167 | }; |
| 168 | |
Matt Spinler | 4c62fc7 | 2024-02-14 16:10:19 -0600 | [diff] [blame] | 169 | /** |
| 170 | * @class FanFRUsWithNonfuncRotorsCause |
| 171 | * |
| 172 | * This class provides a satisfied() method that checks for |
| 173 | * fans with nonfunctional fan rotors in the fan health map. |
| 174 | */ |
| 175 | class FanFRUsWithNonfuncRotorsCause : public PowerOffCause |
| 176 | { |
| 177 | public: |
| 178 | FanFRUsWithNonfuncRotorsCause() = delete; |
| 179 | ~FanFRUsWithNonfuncRotorsCause() = default; |
| 180 | FanFRUsWithNonfuncRotorsCause(const FanFRUsWithNonfuncRotorsCause&) = |
| 181 | delete; |
| 182 | FanFRUsWithNonfuncRotorsCause& |
| 183 | operator=(const FanFRUsWithNonfuncRotorsCause&) = delete; |
| 184 | FanFRUsWithNonfuncRotorsCause(FanFRUsWithNonfuncRotorsCause&&) = delete; |
| 185 | FanFRUsWithNonfuncRotorsCause& |
| 186 | operator=(FanFRUsWithNonfuncRotorsCause&&) = delete; |
| 187 | |
| 188 | /** |
| 189 | * @brief Constructor |
| 190 | * |
| 191 | * @param[in] count - The minimum number of fan FRUs with |
| 192 | * nonfunctional rotors to need a power off. |
| 193 | */ |
| 194 | explicit FanFRUsWithNonfuncRotorsCause(size_t count) : |
| 195 | PowerOffCause(count, "Fans with Nonfunctional Rotors") |
| 196 | {} |
| 197 | |
| 198 | /** |
| 199 | * @brief Returns true if 'count' or more fan FRUs have |
| 200 | * nonfunctional rotors. |
| 201 | * |
| 202 | * @param[in] fanHealth - The FanHealth map |
| 203 | */ |
| 204 | bool satisfied(const FanHealth& fanHealth) override |
| 205 | { |
Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 206 | size_t count = std::count_if( |
| 207 | fanHealth.begin(), fanHealth.end(), [](const auto& fan) { |
| 208 | const auto& tachs = std::get<sensorFuncHealthPos>(fan.second); |
Matt Spinler | 4c62fc7 | 2024-02-14 16:10:19 -0600 | [diff] [blame] | 209 | |
Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 210 | return std::any_of(tachs.begin(), tachs.end(), |
| 211 | [](bool func) { return !func; }); |
| 212 | }); |
Matt Spinler | 4c62fc7 | 2024-02-14 16:10:19 -0600 | [diff] [blame] | 213 | |
| 214 | return count >= _count; |
| 215 | } |
| 216 | }; |
| 217 | |
Matt Spinler | 0023743 | 2020-10-14 10:36:41 -0500 | [diff] [blame] | 218 | } // namespace phosphor::fan::monitor |