100237439SMatt Spinler #pragma once 200237439SMatt Spinler 300237439SMatt Spinler #include "types.hpp" 400237439SMatt Spinler 500237439SMatt Spinler #include <algorithm> 600237439SMatt Spinler #include <vector> 700237439SMatt Spinler 800237439SMatt Spinler namespace phosphor::fan::monitor 900237439SMatt Spinler { 1000237439SMatt Spinler 1100237439SMatt Spinler /** 1200237439SMatt Spinler * @class PowerOffCause 1300237439SMatt Spinler * 1400237439SMatt Spinler * This abstract class provides a satisfied() pure virtual method 1500237439SMatt Spinler * that is called to know if the system should be powered off due 1600237439SMatt Spinler * to fan health. Each type of class that is derived from this 1700237439SMatt Spinler * one provides different behavior, for example one may count 1800237439SMatt Spinler * missing fans, and another may count nonfunctional fans. 1900237439SMatt Spinler */ 2000237439SMatt Spinler class PowerOffCause 2100237439SMatt Spinler { 2200237439SMatt Spinler public: 2300237439SMatt Spinler PowerOffCause() = delete; 2400237439SMatt Spinler virtual ~PowerOffCause() = default; 2500237439SMatt Spinler PowerOffCause(const PowerOffCause&) = delete; 2600237439SMatt Spinler PowerOffCause& operator=(const PowerOffCause&) = delete; 2700237439SMatt Spinler PowerOffCause(PowerOffCause&&) = delete; 2800237439SMatt Spinler PowerOffCause& operator=(PowerOffCause&&) = delete; 2900237439SMatt Spinler 3000237439SMatt Spinler /** 3100237439SMatt Spinler * @brief Constructor 3200237439SMatt Spinler * 3300237439SMatt Spinler * @param[in] count - The number of items that is compared 3400237439SMatt Spinler * against in the derived class. 3500237439SMatt Spinler * @param[in] name - The name of the cause. Used for tracing. 3600237439SMatt Spinler */ PowerOffCause(size_t count,const std::string & name)3700237439SMatt Spinler PowerOffCause(size_t count, const std::string& name) : 3800237439SMatt Spinler _count(count), _name(std::to_string(count) + " " + name) 3900237439SMatt Spinler {} 4000237439SMatt Spinler 4100237439SMatt Spinler /** 4200237439SMatt Spinler * @brief Pure virtual that says if the system should be powered 4300237439SMatt Spinler * off based on the fan health. 4400237439SMatt Spinler * 4500237439SMatt Spinler * @param[in] fanHealth - The FanHealth map 4600237439SMatt Spinler * 4700237439SMatt Spinler * @return bool - If system should be powered off 4800237439SMatt Spinler */ 4900237439SMatt Spinler virtual bool satisfied(const FanHealth& fanHealth) = 0; 5000237439SMatt Spinler 5100237439SMatt Spinler /** 5200237439SMatt Spinler * @brief Returns the name of the cause. 5300237439SMatt Spinler * 5400237439SMatt Spinler * For example: "3 Missing Fans" 5500237439SMatt Spinler * 5600237439SMatt Spinler * @return std::string - The name 5700237439SMatt Spinler */ name() const5800237439SMatt Spinler const std::string& name() const 5900237439SMatt Spinler { 6000237439SMatt Spinler return _name; 6100237439SMatt Spinler } 6200237439SMatt Spinler 6300237439SMatt Spinler protected: 6400237439SMatt Spinler /** 6500237439SMatt Spinler * @brief The number of fan health items that the derived 6600237439SMatt Spinler * class uses to compare to the fan health status. 6700237439SMatt Spinler * For example, a 3 for 3 missing fans. 6800237439SMatt Spinler */ 6900237439SMatt Spinler const size_t _count; 7000237439SMatt Spinler 7100237439SMatt Spinler /** 7200237439SMatt Spinler * @brief The cause name 7300237439SMatt Spinler */ 7400237439SMatt Spinler const std::string _name; 7500237439SMatt Spinler }; 7600237439SMatt Spinler 7700237439SMatt Spinler /** 7800237439SMatt Spinler * @class MissingFanFRUCause 7900237439SMatt Spinler * 8000237439SMatt Spinler * This class provides a satisfied() method that checks for 8100237439SMatt Spinler * missing fans in the fan health map. 8200237439SMatt Spinler * 8300237439SMatt Spinler */ 8400237439SMatt Spinler class MissingFanFRUCause : public PowerOffCause 8500237439SMatt Spinler { 8600237439SMatt Spinler public: 8700237439SMatt Spinler MissingFanFRUCause() = delete; 8800237439SMatt Spinler ~MissingFanFRUCause() = default; 8900237439SMatt Spinler MissingFanFRUCause(const MissingFanFRUCause&) = delete; 9000237439SMatt Spinler MissingFanFRUCause& operator=(const MissingFanFRUCause&) = delete; 9100237439SMatt Spinler MissingFanFRUCause(MissingFanFRUCause&&) = delete; 9200237439SMatt Spinler MissingFanFRUCause& operator=(MissingFanFRUCause&&) = delete; 9300237439SMatt Spinler 9400237439SMatt Spinler /** 9500237439SMatt Spinler * @brief Constructor 9600237439SMatt Spinler * 9700237439SMatt Spinler * @param[in] count - The minimum number of fans that must be 9800237439SMatt Spinler * missing to need a power off. 9900237439SMatt Spinler */ MissingFanFRUCause(size_t count)10000237439SMatt Spinler explicit MissingFanFRUCause(size_t count) : 10100237439SMatt Spinler PowerOffCause(count, "Missing Fan FRUs") 10200237439SMatt Spinler {} 10300237439SMatt Spinler 10400237439SMatt Spinler /** 10500237439SMatt Spinler * @brief Returns true if 'count' or more fans are missing 10600237439SMatt Spinler * to require a power off. 10700237439SMatt Spinler * 10800237439SMatt Spinler * @param[in] fanHealth - The FanHealth map 10900237439SMatt Spinler */ satisfied(const FanHealth & fanHealth)11000237439SMatt Spinler bool satisfied(const FanHealth& fanHealth) override 11100237439SMatt Spinler { 112*dfddd648SPatrick Williams size_t count = std::count_if( 113*dfddd648SPatrick Williams fanHealth.begin(), fanHealth.end(), [](const auto& fan) { 11400237439SMatt Spinler return !std::get<presentHealthPos>(fan.second); 11500237439SMatt Spinler }); 11600237439SMatt Spinler 11700237439SMatt Spinler return count >= _count; 11800237439SMatt Spinler } 11900237439SMatt Spinler }; 12000237439SMatt Spinler 12100237439SMatt Spinler /** 12200237439SMatt Spinler * @class NonfuncFanRotorCause 12300237439SMatt Spinler * 12400237439SMatt Spinler * This class provides a satisfied() method that checks for 12500237439SMatt Spinler * nonfunctional fan rotors in the fan health map. 12600237439SMatt Spinler */ 12700237439SMatt Spinler class NonfuncFanRotorCause : public PowerOffCause 12800237439SMatt Spinler { 12900237439SMatt Spinler public: 13000237439SMatt Spinler NonfuncFanRotorCause() = delete; 13100237439SMatt Spinler ~NonfuncFanRotorCause() = default; 13200237439SMatt Spinler NonfuncFanRotorCause(const NonfuncFanRotorCause&) = delete; 13300237439SMatt Spinler NonfuncFanRotorCause& operator=(const NonfuncFanRotorCause&) = delete; 13400237439SMatt Spinler NonfuncFanRotorCause(NonfuncFanRotorCause&&) = delete; 13500237439SMatt Spinler NonfuncFanRotorCause& operator=(NonfuncFanRotorCause&&) = delete; 13600237439SMatt Spinler 13700237439SMatt Spinler /** 13800237439SMatt Spinler * @brief Constructor 13900237439SMatt Spinler * 14000237439SMatt Spinler * @param[in] count - The minimum number of rotors that must be 1414c62fc77SMatt Spinler * nonfunctional to need a power off. 14200237439SMatt Spinler */ NonfuncFanRotorCause(size_t count)14300237439SMatt Spinler explicit NonfuncFanRotorCause(size_t count) : 14400237439SMatt Spinler PowerOffCause(count, "Nonfunctional Fan Rotors") 14500237439SMatt Spinler {} 14600237439SMatt Spinler 14700237439SMatt Spinler /** 14800237439SMatt Spinler * @brief Returns true if 'count' or more rotors are nonfunctional 14900237439SMatt Spinler * to require a power off. 15000237439SMatt Spinler * 15100237439SMatt Spinler * @param[in] fanHealth - The FanHealth map 15200237439SMatt Spinler */ satisfied(const FanHealth & fanHealth)15300237439SMatt Spinler bool satisfied(const FanHealth& fanHealth) override 15400237439SMatt Spinler { 155*dfddd648SPatrick Williams size_t count = std::accumulate( 156*dfddd648SPatrick Williams fanHealth.begin(), fanHealth.end(), 0, 15700237439SMatt Spinler [](int sum, const auto& fan) { 15800237439SMatt Spinler const auto& tachs = std::get<sensorFuncHealthPos>(fan.second); 159*dfddd648SPatrick Williams auto nonFuncTachs = 160*dfddd648SPatrick Williams std::count_if(tachs.begin(), tachs.end(), 16100237439SMatt Spinler [](bool tach) { return !tach; }); 16200237439SMatt Spinler return sum + nonFuncTachs; 16300237439SMatt Spinler }); 16400237439SMatt Spinler 16500237439SMatt Spinler return count >= _count; 16600237439SMatt Spinler } 16700237439SMatt Spinler }; 16800237439SMatt Spinler 1694c62fc77SMatt Spinler /** 1704c62fc77SMatt Spinler * @class FanFRUsWithNonfuncRotorsCause 1714c62fc77SMatt Spinler * 1724c62fc77SMatt Spinler * This class provides a satisfied() method that checks for 1734c62fc77SMatt Spinler * fans with nonfunctional fan rotors in the fan health map. 1744c62fc77SMatt Spinler */ 1754c62fc77SMatt Spinler class FanFRUsWithNonfuncRotorsCause : public PowerOffCause 1764c62fc77SMatt Spinler { 1774c62fc77SMatt Spinler public: 1784c62fc77SMatt Spinler FanFRUsWithNonfuncRotorsCause() = delete; 1794c62fc77SMatt Spinler ~FanFRUsWithNonfuncRotorsCause() = default; 1804c62fc77SMatt Spinler FanFRUsWithNonfuncRotorsCause(const FanFRUsWithNonfuncRotorsCause&) = 1814c62fc77SMatt Spinler delete; 1824c62fc77SMatt Spinler FanFRUsWithNonfuncRotorsCause& 1834c62fc77SMatt Spinler operator=(const FanFRUsWithNonfuncRotorsCause&) = delete; 1844c62fc77SMatt Spinler FanFRUsWithNonfuncRotorsCause(FanFRUsWithNonfuncRotorsCause&&) = delete; 1854c62fc77SMatt Spinler FanFRUsWithNonfuncRotorsCause& 1864c62fc77SMatt Spinler operator=(FanFRUsWithNonfuncRotorsCause&&) = delete; 1874c62fc77SMatt Spinler 1884c62fc77SMatt Spinler /** 1894c62fc77SMatt Spinler * @brief Constructor 1904c62fc77SMatt Spinler * 1914c62fc77SMatt Spinler * @param[in] count - The minimum number of fan FRUs with 1924c62fc77SMatt Spinler * nonfunctional rotors to need a power off. 1934c62fc77SMatt Spinler */ FanFRUsWithNonfuncRotorsCause(size_t count)1944c62fc77SMatt Spinler explicit FanFRUsWithNonfuncRotorsCause(size_t count) : 1954c62fc77SMatt Spinler PowerOffCause(count, "Fans with Nonfunctional Rotors") 1964c62fc77SMatt Spinler {} 1974c62fc77SMatt Spinler 1984c62fc77SMatt Spinler /** 1994c62fc77SMatt Spinler * @brief Returns true if 'count' or more fan FRUs have 2004c62fc77SMatt Spinler * nonfunctional rotors. 2014c62fc77SMatt Spinler * 2024c62fc77SMatt Spinler * @param[in] fanHealth - The FanHealth map 2034c62fc77SMatt Spinler */ satisfied(const FanHealth & fanHealth)2044c62fc77SMatt Spinler bool satisfied(const FanHealth& fanHealth) override 2054c62fc77SMatt Spinler { 206*dfddd648SPatrick Williams size_t count = std::count_if( 207*dfddd648SPatrick Williams fanHealth.begin(), fanHealth.end(), [](const auto& fan) { 2084c62fc77SMatt Spinler const auto& tachs = std::get<sensorFuncHealthPos>(fan.second); 2094c62fc77SMatt Spinler 2104c62fc77SMatt Spinler return std::any_of(tachs.begin(), tachs.end(), 2114c62fc77SMatt Spinler [](bool func) { return !func; }); 2124c62fc77SMatt Spinler }); 2134c62fc77SMatt Spinler 2144c62fc77SMatt Spinler return count >= _count; 2154c62fc77SMatt Spinler } 2164c62fc77SMatt Spinler }; 2174c62fc77SMatt Spinler 21800237439SMatt Spinler } // namespace phosphor::fan::monitor 219