blob: 07d6a0e85b8db2e8a3a9d0be5a3aa33156ce8022 [file] [log] [blame]
Matt Spinler78689dd2017-09-28 10:12:07 -05001#pragma once
2#include <memory>
3#include "tach_sensor.hpp"
4
5namespace phosphor
6{
7namespace fan
8{
9namespace trust
10{
11
Matthew Barth6f31d192018-01-30 13:06:27 -060012constexpr auto sensorName = 0;
13constexpr auto inTrust = 1;
14using GroupDefinition = std::tuple<std::string,
15 bool>;
16
Matthew Bartha1c88322018-02-16 12:38:27 -060017struct GroupSensor
18{
19 std::shared_ptr<monitor::TachSensor> sensor;
20 bool inTrust;
21};
22
Matt Spinler78689dd2017-09-28 10:12:07 -050023/**
24 * @class Group
25 *
26 * An abstract sensor trust group base class.
27 *
28 * Supports the ability to know if a fan speed sensor value can
29 * be trusted or not, where if it isn't trusted then it shouldn't
30 * be used to determine if the fan is faulted or not.
31 *
32 * It's a group in that there can be multiple sensors in the group
33 * and the trust of all sensors depends on something about those sensors.
34 * For example, if all sensors in the group report a speed of zero,
35 * then no sensor in the group is trusted. All sensors in the group
36 * have the same trust value.
37 *
38 * Trust is calculated when checkTrust() is called after a group
39 * sensor's tach value changes.
40 *
41 * A derived class must override checkGroupTrust().
42 */
43class Group
44{
45 public:
46
47 Group() = delete;
48 virtual ~Group() = default;
49 Group(const Group&) = delete;
50 Group& operator=(const Group&) = delete;
51 Group(Group&&) = default;
52 Group& operator=(Group&&) = default;
53
54 /**
55 * Constructor
56 *
Matthew Barth6f31d192018-01-30 13:06:27 -060057 * @param[in] names - the names and inclusion of sensors in the group
Matt Spinler78689dd2017-09-28 10:12:07 -050058 */
Matthew Barth6f31d192018-01-30 13:06:27 -060059 explicit Group(const std::vector<GroupDefinition>& names) :
Matt Spinler78689dd2017-09-28 10:12:07 -050060 _names(names)
61 {
62 }
63
64 /**
65 * Used to register a TachSensor object with the group.
66 * It's only added to the group if the sensor's name is
67 * in the group's list of names.
68 *
69 * @param[in] sensor - the TachSensor to register
70 */
Matthew Barth32affb92018-02-16 16:11:13 -060071 void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor)
Matt Spinler78689dd2017-09-28 10:12:07 -050072 {
73 auto found = std::find_if(
74 _names.begin(),
75 _names.end(),
76 [&sensor](const auto& name)
77 {
78 return monitor::FAN_SENSOR_PATH +
Matthew Barth6f31d192018-01-30 13:06:27 -060079 std::get<sensorName>(name) == sensor->name();
Matt Spinler78689dd2017-09-28 10:12:07 -050080 });
81
82 if (found != _names.end())
83 {
Matthew Bartha1c88322018-02-16 12:38:27 -060084 _sensors.push_back({sensor, std::get<inTrust>(*found)});
Matt Spinler78689dd2017-09-28 10:12:07 -050085 }
86 }
87
88 /**
89 * Says if a sensor belongs to the group.
90 *
91 * After all sensors have registered, this can be
92 * used to say if a TachSensor is in the group.
93 *
94 * @param[in] sensor - the TachSensor object
95 */
96 bool inGroup(const monitor::TachSensor& sensor)
97 {
98 return (std::find_if(
99 _sensors.begin(),
100 _sensors.end(),
101 [&sensor](const auto& s)
102 {
Matthew Bartha1c88322018-02-16 12:38:27 -0600103 return sensor.name() == s.sensor->name();
Matt Spinler78689dd2017-09-28 10:12:07 -0500104 }) != _sensors.end());
105 }
106
107 /**
108 * Stops the timers on all sensors in the group.
109 *
110 * Called when the group just changed to not trusted,
111 * so that its sensors' timers can't fire a callback
112 * that may cause them to be considered faulted.
113 */
114 void stopTimers()
115 {
116 std::for_each(
117 _sensors.begin(),
118 _sensors.end(),
119 [](const auto& s)
120 {
Matthew Bartha1c88322018-02-16 12:38:27 -0600121 s.sensor->stopTimer();
Matt Spinler78689dd2017-09-28 10:12:07 -0500122 });
123 }
124
125 /**
Matthew Barth58560232017-11-22 14:52:12 -0600126 * Starts the timers on all functional sensors in the group if
127 * their target and input values do not match.
Matt Spinler78689dd2017-09-28 10:12:07 -0500128 *
129 * Called when the group just changed to trusted.
130 */
131 void startTimers()
132 {
133 std::for_each(
134 _sensors.begin(),
135 _sensors.end(),
136 [](const auto& s)
137 {
138 //If a sensor isn't functional, then its timer
139 //already expired so don't bother starting it again
Matthew Bartha1c88322018-02-16 12:38:27 -0600140 if (s.sensor->functional() &&
141 static_cast<uint64_t>(
142 s.sensor->getInput()) !=
143 s.sensor->getTarget())
Matt Spinler78689dd2017-09-28 10:12:07 -0500144 {
Matthew Barth3800ae72018-02-19 16:08:04 -0600145 s.sensor->startTimer(
146 phosphor::fan::monitor::TimerMode::nonfunc);
Matt Spinler78689dd2017-09-28 10:12:07 -0500147 }
148 });
149 }
150
151 /**
152 * Determines the trust for this group based on this
153 * sensor's latest status.
154 *
155 * Calls the derived class's checkGroupTrust function
156 * and updates the class with the results.
157 *
158 * If this is called with a sensor not in the group,
159 * it will be considered trusted.
160 *
161 * @param[in] sensor - TachSensor object
162 *
163 * @return tuple<bool, bool> -
164 * field 0 - the trust value
165 * field 1 - if that trust value changed since last call
166 * to checkTrust
167 */
168 auto checkTrust(const monitor::TachSensor& sensor)
169 {
170 if (inGroup(sensor))
171 {
172 auto trust = checkGroupTrust();
173
174 setTrust(trust);
175
176 return std::tuple<bool, bool>(_trusted, _stateChange);
177 }
178 return std::tuple<bool, bool>(true, false);
179 }
180
181 /**
182 * Says if all sensors in the group are currently trusted,
183 * as determined by the last call to checkTrust().
184 *
185 * @return bool - if the group's sensors are trusted or not
186 */
187 inline auto getTrust() const
188 {
189 return _trusted;
190 }
191
192 /**
193 * Says if the trust value changed in the last call to
194 * checkTrust()
195 *
196 * @return bool - if the trust changed or not
197 */
198 inline auto trustChanged() const
199 {
200 return _stateChange;
201 }
202
203 protected:
204
205 /**
Matthew Barth6f31d192018-01-30 13:06:27 -0600206 * The sensor objects and their trust inclusion in the group.
Matt Spinler78689dd2017-09-28 10:12:07 -0500207 *
208 * Added by registerSensor().
209 */
Matthew Bartha1c88322018-02-16 12:38:27 -0600210 std::vector<GroupSensor> _sensors;
Matt Spinler78689dd2017-09-28 10:12:07 -0500211
212 private:
213
214 /**
215 * Checks if the group's sensors are trusted.
216 *
217 * The derived class must override this function
218 * to provide custom functionality.
219 *
220 * @return bool - if group is trusted or not
221 */
222 virtual bool checkGroupTrust() = 0;
223
224 /**
225 * Sets the trust value on the object.
226 *
227 * @param[in] trust - the new trust value
228 */
229 inline void setTrust(bool trust)
230 {
231 _stateChange = (trust != _trusted);
232 _trusted = trust;
233 }
234
235 /**
236 * The current trust state of the group
237 */
238 bool _trusted = true;
239
240 /**
241 * If the trust value changed in the last call to checkTrust
242 */
243 bool _stateChange = false;
244
245 /**
Matthew Barth6f31d192018-01-30 13:06:27 -0600246 * The names of the sensors and whether it is included in
247 * determining trust for this group
Matt Spinler78689dd2017-09-28 10:12:07 -0500248 */
Matthew Barth6f31d192018-01-30 13:06:27 -0600249 const std::vector<GroupDefinition> _names;
Matt Spinler78689dd2017-09-28 10:12:07 -0500250};
251
252}
253}
254}