blob: bc3704f54d47f83db80bbbe0addd9cf120df0c13 [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 Williams61b73292023-05-10 07:50:12 -0500112 size_t count = std::count_if(fanHealth.begin(), fanHealth.end(),
113 [](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 Williams61b73292023-05-10 07:50:12 -0500155 size_t count = std::accumulate(fanHealth.begin(), fanHealth.end(), 0,
156 [](int sum, const auto& fan) {
157 const auto& tachs = std::get<sensorFuncHealthPos>(fan.second);
158 auto nonFuncTachs = std::count_if(tachs.begin(), tachs.end(),
159 [](bool tach) { return !tach; });
160 return sum + nonFuncTachs;
161 });
Matt Spinler00237432020-10-14 10:36:41 -0500162
163 return count >= _count;
164 }
165};
166
Matt Spinler4c62fc72024-02-14 16:10:19 -0600167/**
168 * @class FanFRUsWithNonfuncRotorsCause
169 *
170 * This class provides a satisfied() method that checks for
171 * fans with nonfunctional fan rotors in the fan health map.
172 */
173class FanFRUsWithNonfuncRotorsCause : public PowerOffCause
174{
175 public:
176 FanFRUsWithNonfuncRotorsCause() = delete;
177 ~FanFRUsWithNonfuncRotorsCause() = default;
178 FanFRUsWithNonfuncRotorsCause(const FanFRUsWithNonfuncRotorsCause&) =
179 delete;
180 FanFRUsWithNonfuncRotorsCause&
181 operator=(const FanFRUsWithNonfuncRotorsCause&) = delete;
182 FanFRUsWithNonfuncRotorsCause(FanFRUsWithNonfuncRotorsCause&&) = delete;
183 FanFRUsWithNonfuncRotorsCause&
184 operator=(FanFRUsWithNonfuncRotorsCause&&) = delete;
185
186 /**
187 * @brief Constructor
188 *
189 * @param[in] count - The minimum number of fan FRUs with
190 * nonfunctional rotors to need a power off.
191 */
192 explicit FanFRUsWithNonfuncRotorsCause(size_t count) :
193 PowerOffCause(count, "Fans with Nonfunctional Rotors")
194 {}
195
196 /**
197 * @brief Returns true if 'count' or more fan FRUs have
198 * nonfunctional rotors.
199 *
200 * @param[in] fanHealth - The FanHealth map
201 */
202 bool satisfied(const FanHealth& fanHealth) override
203 {
204 size_t count = std::count_if(fanHealth.begin(), fanHealth.end(),
205 [](const auto& fan) {
206 const auto& tachs = std::get<sensorFuncHealthPos>(fan.second);
207
208 return std::any_of(tachs.begin(), tachs.end(),
209 [](bool func) { return !func; });
210 });
211
212 return count >= _count;
213 }
214};
215
Matt Spinler00237432020-10-14 10:36:41 -0500216} // namespace phosphor::fan::monitor