blob: abc2cb43df3c05f4e3499ab543a484ed0236292a [file] [log] [blame]
Matt Spinler00237432020-10-14 10:36:41 -05001#pragma once
2
3#include "types.hpp"
4
5#include <algorithm>
6#include <vector>
7
8namespace 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 */
20class 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 */
84class 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 Williamsdfddd642024-08-16 15:21:51 -0400112 size_t count = std::count_if(
113 fanHealth.begin(), fanHealth.end(), [](const auto& fan) {
114 return !std::get<presentHealthPos>(fan.second);
115 });
Matt Spinler00237432020-10-14 10:36:41 -0500116
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 */
127class 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 Spinler4c62fc72024-02-14 16:10:19 -0600141 * nonfunctional to need a power off.
Matt Spinler00237432020-10-14 10:36:41 -0500142 */
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 Williamsdfddd642024-08-16 15:21:51 -0400155 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 Spinler00237432020-10-14 10:36:41 -0500164
165 return count >= _count;
166 }
167};
168
Matt Spinler4c62fc72024-02-14 16:10:19 -0600169/**
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 */
175class 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 Williamsdfddd642024-08-16 15:21:51 -0400206 size_t count = std::count_if(
207 fanHealth.begin(), fanHealth.end(), [](const auto& fan) {
208 const auto& tachs = std::get<sensorFuncHealthPos>(fan.second);
Matt Spinler4c62fc72024-02-14 16:10:19 -0600209
Patrick Williamsdfddd642024-08-16 15:21:51 -0400210 return std::any_of(tachs.begin(), tachs.end(),
211 [](bool func) { return !func; });
212 });
Matt Spinler4c62fc72024-02-14 16:10:19 -0600213
214 return count >= _count;
215 }
216};
217
Matt Spinler00237432020-10-14 10:36:41 -0500218} // namespace phosphor::fan::monitor