blob: 7f28f6cfd127d9ee77c3767cb28711634a81ed78 [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
Matt Spinler78689dd2017-09-28 10:12:07 -050017/**
18 * @class Group
19 *
20 * An abstract sensor trust group base class.
21 *
22 * Supports the ability to know if a fan speed sensor value can
23 * be trusted or not, where if it isn't trusted then it shouldn't
24 * be used to determine if the fan is faulted or not.
25 *
26 * It's a group in that there can be multiple sensors in the group
27 * and the trust of all sensors depends on something about those sensors.
28 * For example, if all sensors in the group report a speed of zero,
29 * then no sensor in the group is trusted. All sensors in the group
30 * have the same trust value.
31 *
32 * Trust is calculated when checkTrust() is called after a group
33 * sensor's tach value changes.
34 *
35 * A derived class must override checkGroupTrust().
36 */
37class Group
38{
39 public:
40
41 Group() = delete;
42 virtual ~Group() = default;
43 Group(const Group&) = delete;
44 Group& operator=(const Group&) = delete;
45 Group(Group&&) = default;
46 Group& operator=(Group&&) = default;
47
48 /**
49 * Constructor
50 *
Matthew Barth6f31d192018-01-30 13:06:27 -060051 * @param[in] names - the names and inclusion of sensors in the group
Matt Spinler78689dd2017-09-28 10:12:07 -050052 */
Matthew Barth6f31d192018-01-30 13:06:27 -060053 explicit Group(const std::vector<GroupDefinition>& names) :
Matt Spinler78689dd2017-09-28 10:12:07 -050054 _names(names)
55 {
56 }
57
58 /**
59 * Used to register a TachSensor object with the group.
60 * It's only added to the group if the sensor's name is
61 * in the group's list of names.
62 *
63 * @param[in] sensor - the TachSensor to register
64 */
Matthew Barth32affb92018-02-16 16:11:13 -060065 void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor)
Matt Spinler78689dd2017-09-28 10:12:07 -050066 {
67 auto found = std::find_if(
68 _names.begin(),
69 _names.end(),
70 [&sensor](const auto& name)
71 {
72 return monitor::FAN_SENSOR_PATH +
Matthew Barth6f31d192018-01-30 13:06:27 -060073 std::get<sensorName>(name) == sensor->name();
Matt Spinler78689dd2017-09-28 10:12:07 -050074 });
75
76 if (found != _names.end())
77 {
Matthew Barth6f31d192018-01-30 13:06:27 -060078 auto gs = std::make_tuple(sensor, std::get<inTrust>(*found));
79 _sensors.push_back(gs);
Matt Spinler78689dd2017-09-28 10:12:07 -050080 }
81 }
82
83 /**
84 * Says if a sensor belongs to the group.
85 *
86 * After all sensors have registered, this can be
87 * used to say if a TachSensor is in the group.
88 *
89 * @param[in] sensor - the TachSensor object
90 */
91 bool inGroup(const monitor::TachSensor& sensor)
92 {
93 return (std::find_if(
94 _sensors.begin(),
95 _sensors.end(),
96 [&sensor](const auto& s)
97 {
Matthew Barth6f31d192018-01-30 13:06:27 -060098 return sensor.name() == std::get<0>(s)->name();
Matt Spinler78689dd2017-09-28 10:12:07 -050099 }) != _sensors.end());
100 }
101
102 /**
103 * Stops the timers on all sensors in the group.
104 *
105 * Called when the group just changed to not trusted,
106 * so that its sensors' timers can't fire a callback
107 * that may cause them to be considered faulted.
108 */
109 void stopTimers()
110 {
111 std::for_each(
112 _sensors.begin(),
113 _sensors.end(),
114 [](const auto& s)
115 {
Matthew Barth6f31d192018-01-30 13:06:27 -0600116 std::get<0>(s)->stopTimer();
Matt Spinler78689dd2017-09-28 10:12:07 -0500117 });
118 }
119
120 /**
Matthew Barth58560232017-11-22 14:52:12 -0600121 * Starts the timers on all functional sensors in the group if
122 * their target and input values do not match.
Matt Spinler78689dd2017-09-28 10:12:07 -0500123 *
124 * Called when the group just changed to trusted.
125 */
126 void startTimers()
127 {
128 std::for_each(
129 _sensors.begin(),
130 _sensors.end(),
131 [](const auto& s)
132 {
133 //If a sensor isn't functional, then its timer
134 //already expired so don't bother starting it again
Matthew Barth6f31d192018-01-30 13:06:27 -0600135 if (std::get<0>(s)->functional() &&
136 static_cast<uint64_t>(std::get<0>(s)->getInput()) !=
137 std::get<0>(s)->getTarget())
Matt Spinler78689dd2017-09-28 10:12:07 -0500138 {
Matthew Barth6f31d192018-01-30 13:06:27 -0600139 std::get<0>(s)->startTimer();
Matt Spinler78689dd2017-09-28 10:12:07 -0500140 }
141 });
142 }
143
144 /**
145 * Determines the trust for this group based on this
146 * sensor's latest status.
147 *
148 * Calls the derived class's checkGroupTrust function
149 * and updates the class with the results.
150 *
151 * If this is called with a sensor not in the group,
152 * it will be considered trusted.
153 *
154 * @param[in] sensor - TachSensor object
155 *
156 * @return tuple<bool, bool> -
157 * field 0 - the trust value
158 * field 1 - if that trust value changed since last call
159 * to checkTrust
160 */
161 auto checkTrust(const monitor::TachSensor& sensor)
162 {
163 if (inGroup(sensor))
164 {
165 auto trust = checkGroupTrust();
166
167 setTrust(trust);
168
169 return std::tuple<bool, bool>(_trusted, _stateChange);
170 }
171 return std::tuple<bool, bool>(true, false);
172 }
173
174 /**
175 * Says if all sensors in the group are currently trusted,
176 * as determined by the last call to checkTrust().
177 *
178 * @return bool - if the group's sensors are trusted or not
179 */
180 inline auto getTrust() const
181 {
182 return _trusted;
183 }
184
185 /**
186 * Says if the trust value changed in the last call to
187 * checkTrust()
188 *
189 * @return bool - if the trust changed or not
190 */
191 inline auto trustChanged() const
192 {
193 return _stateChange;
194 }
195
196 protected:
197
198 /**
Matthew Barth6f31d192018-01-30 13:06:27 -0600199 * The sensor objects and their trust inclusion in the group.
Matt Spinler78689dd2017-09-28 10:12:07 -0500200 *
201 * Added by registerSensor().
202 */
Matthew Barth6f31d192018-01-30 13:06:27 -0600203 std::vector<std::tuple<
204 std::shared_ptr<monitor::TachSensor>,
205 bool>> _sensors;
Matt Spinler78689dd2017-09-28 10:12:07 -0500206
207 private:
208
209 /**
210 * Checks if the group's sensors are trusted.
211 *
212 * The derived class must override this function
213 * to provide custom functionality.
214 *
215 * @return bool - if group is trusted or not
216 */
217 virtual bool checkGroupTrust() = 0;
218
219 /**
220 * Sets the trust value on the object.
221 *
222 * @param[in] trust - the new trust value
223 */
224 inline void setTrust(bool trust)
225 {
226 _stateChange = (trust != _trusted);
227 _trusted = trust;
228 }
229
230 /**
231 * The current trust state of the group
232 */
233 bool _trusted = true;
234
235 /**
236 * If the trust value changed in the last call to checkTrust
237 */
238 bool _stateChange = false;
239
240 /**
Matthew Barth6f31d192018-01-30 13:06:27 -0600241 * The names of the sensors and whether it is included in
242 * determining trust for this group
Matt Spinler78689dd2017-09-28 10:12:07 -0500243 */
Matthew Barth6f31d192018-01-30 13:06:27 -0600244 const std::vector<GroupDefinition> _names;
Matt Spinler78689dd2017-09-28 10:12:07 -0500245};
246
247}
248}
249}