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 */ PowerOffCause(size_t count,const std::string & name)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 */ name() const58 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 */ MissingFanFRUCause(size_t count)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 */ satisfied(const FanHealth & fanHealth)110 bool satisfied(const FanHealth& fanHealth) override 111 { 112 size_t count = std::count_if( 113 fanHealth.begin(), fanHealth.end(), [](const auto& fan) { 114 return !std::get<presentHealthPos>(fan.second); 115 }); 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 141 * nonfunctional to need a power off. 142 */ NonfuncFanRotorCause(size_t count)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 */ satisfied(const FanHealth & fanHealth)153 bool satisfied(const FanHealth& fanHealth) override 154 { 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 }); 164 165 return count >= _count; 166 } 167 }; 168 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 */ FanFRUsWithNonfuncRotorsCause(size_t count)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 */ satisfied(const FanHealth & fanHealth)204 bool satisfied(const FanHealth& fanHealth) override 205 { 206 size_t count = std::count_if( 207 fanHealth.begin(), fanHealth.end(), [](const auto& fan) { 208 const auto& tachs = std::get<sensorFuncHealthPos>(fan.second); 209 210 return std::any_of(tachs.begin(), tachs.end(), 211 [](bool func) { return !func; }); 212 }); 213 214 return count >= _count; 215 } 216 }; 217 218 } // namespace phosphor::fan::monitor 219