blob: abc2cb43df3c05f4e3499ab543a484ed0236292a [file] [log] [blame]
#pragma once
#include "types.hpp"
#include <algorithm>
#include <vector>
namespace phosphor::fan::monitor
{
/**
* @class PowerOffCause
*
* This abstract class provides a satisfied() pure virtual method
* that is called to know if the system should be powered off due
* to fan health. Each type of class that is derived from this
* one provides different behavior, for example one may count
* missing fans, and another may count nonfunctional fans.
*/
class PowerOffCause
{
public:
PowerOffCause() = delete;
virtual ~PowerOffCause() = default;
PowerOffCause(const PowerOffCause&) = delete;
PowerOffCause& operator=(const PowerOffCause&) = delete;
PowerOffCause(PowerOffCause&&) = delete;
PowerOffCause& operator=(PowerOffCause&&) = delete;
/**
* @brief Constructor
*
* @param[in] count - The number of items that is compared
* against in the derived class.
* @param[in] name - The name of the cause. Used for tracing.
*/
PowerOffCause(size_t count, const std::string& name) :
_count(count), _name(std::to_string(count) + " " + name)
{}
/**
* @brief Pure virtual that says if the system should be powered
* off based on the fan health.
*
* @param[in] fanHealth - The FanHealth map
*
* @return bool - If system should be powered off
*/
virtual bool satisfied(const FanHealth& fanHealth) = 0;
/**
* @brief Returns the name of the cause.
*
* For example: "3 Missing Fans"
*
* @return std::string - The name
*/
const std::string& name() const
{
return _name;
}
protected:
/**
* @brief The number of fan health items that the derived
* class uses to compare to the fan health status.
* For example, a 3 for 3 missing fans.
*/
const size_t _count;
/**
* @brief The cause name
*/
const std::string _name;
};
/**
* @class MissingFanFRUCause
*
* This class provides a satisfied() method that checks for
* missing fans in the fan health map.
*
*/
class MissingFanFRUCause : public PowerOffCause
{
public:
MissingFanFRUCause() = delete;
~MissingFanFRUCause() = default;
MissingFanFRUCause(const MissingFanFRUCause&) = delete;
MissingFanFRUCause& operator=(const MissingFanFRUCause&) = delete;
MissingFanFRUCause(MissingFanFRUCause&&) = delete;
MissingFanFRUCause& operator=(MissingFanFRUCause&&) = delete;
/**
* @brief Constructor
*
* @param[in] count - The minimum number of fans that must be
* missing to need a power off.
*/
explicit MissingFanFRUCause(size_t count) :
PowerOffCause(count, "Missing Fan FRUs")
{}
/**
* @brief Returns true if 'count' or more fans are missing
* to require a power off.
*
* @param[in] fanHealth - The FanHealth map
*/
bool satisfied(const FanHealth& fanHealth) override
{
size_t count = std::count_if(
fanHealth.begin(), fanHealth.end(), [](const auto& fan) {
return !std::get<presentHealthPos>(fan.second);
});
return count >= _count;
}
};
/**
* @class NonfuncFanRotorCause
*
* This class provides a satisfied() method that checks for
* nonfunctional fan rotors in the fan health map.
*/
class NonfuncFanRotorCause : public PowerOffCause
{
public:
NonfuncFanRotorCause() = delete;
~NonfuncFanRotorCause() = default;
NonfuncFanRotorCause(const NonfuncFanRotorCause&) = delete;
NonfuncFanRotorCause& operator=(const NonfuncFanRotorCause&) = delete;
NonfuncFanRotorCause(NonfuncFanRotorCause&&) = delete;
NonfuncFanRotorCause& operator=(NonfuncFanRotorCause&&) = delete;
/**
* @brief Constructor
*
* @param[in] count - The minimum number of rotors that must be
* nonfunctional to need a power off.
*/
explicit NonfuncFanRotorCause(size_t count) :
PowerOffCause(count, "Nonfunctional Fan Rotors")
{}
/**
* @brief Returns true if 'count' or more rotors are nonfunctional
* to require a power off.
*
* @param[in] fanHealth - The FanHealth map
*/
bool satisfied(const FanHealth& fanHealth) override
{
size_t count = std::accumulate(
fanHealth.begin(), fanHealth.end(), 0,
[](int sum, const auto& fan) {
const auto& tachs = std::get<sensorFuncHealthPos>(fan.second);
auto nonFuncTachs =
std::count_if(tachs.begin(), tachs.end(),
[](bool tach) { return !tach; });
return sum + nonFuncTachs;
});
return count >= _count;
}
};
/**
* @class FanFRUsWithNonfuncRotorsCause
*
* This class provides a satisfied() method that checks for
* fans with nonfunctional fan rotors in the fan health map.
*/
class FanFRUsWithNonfuncRotorsCause : public PowerOffCause
{
public:
FanFRUsWithNonfuncRotorsCause() = delete;
~FanFRUsWithNonfuncRotorsCause() = default;
FanFRUsWithNonfuncRotorsCause(const FanFRUsWithNonfuncRotorsCause&) =
delete;
FanFRUsWithNonfuncRotorsCause&
operator=(const FanFRUsWithNonfuncRotorsCause&) = delete;
FanFRUsWithNonfuncRotorsCause(FanFRUsWithNonfuncRotorsCause&&) = delete;
FanFRUsWithNonfuncRotorsCause&
operator=(FanFRUsWithNonfuncRotorsCause&&) = delete;
/**
* @brief Constructor
*
* @param[in] count - The minimum number of fan FRUs with
* nonfunctional rotors to need a power off.
*/
explicit FanFRUsWithNonfuncRotorsCause(size_t count) :
PowerOffCause(count, "Fans with Nonfunctional Rotors")
{}
/**
* @brief Returns true if 'count' or more fan FRUs have
* nonfunctional rotors.
*
* @param[in] fanHealth - The FanHealth map
*/
bool satisfied(const FanHealth& fanHealth) override
{
size_t count = std::count_if(
fanHealth.begin(), fanHealth.end(), [](const auto& fan) {
const auto& tachs = std::get<sensorFuncHealthPos>(fan.second);
return std::any_of(tachs.begin(), tachs.end(),
[](bool func) { return !func; });
});
return count >= _count;
}
};
} // namespace phosphor::fan::monitor