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