summaryrefslogtreecommitdiffstats
path: root/monitor/trust_group.hpp
blob: 7f28f6cfd127d9ee77c3767cb28711634a81ed78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#pragma once
#include <memory>
#include "tach_sensor.hpp"

namespace phosphor
{
namespace fan
{
namespace trust
{

constexpr auto sensorName = 0;
constexpr auto inTrust = 1;
using GroupDefinition = std::tuple<std::string,
                                        bool>;

/**
 * @class Group
 *
 * An abstract sensor trust group base class.
 *
 * Supports the ability to know if a fan speed sensor value can
 * be trusted or not, where if it isn't trusted then it shouldn't
 * be used to determine if the fan is faulted or not.
 *
 * It's a group in that there can be multiple sensors in the group
 * and the trust of all sensors depends on something about those sensors.
 * For example, if all sensors in the group report a speed of zero,
 * then no sensor in the group is trusted.  All sensors in the group
 * have the same trust value.
 *
 * Trust is calculated when checkTrust() is called after a group
 * sensor's tach value changes.
 *
 * A derived class must override checkGroupTrust().
 */
class Group
{
    public:

        Group() = delete;
        virtual ~Group() = default;
        Group(const Group&) = delete;
        Group& operator=(const Group&) = delete;
        Group(Group&&) = default;
        Group& operator=(Group&&) = default;

        /**
         * Constructor
         *
         * @param[in] names - the names and inclusion of sensors in the group
         */
        explicit Group(const std::vector<GroupDefinition>& names) :
                _names(names)
        {
        }

        /**
         * Used to register a TachSensor object with the group.
         * It's only added to the group if the sensor's name is
         * in the group's list of names.
         *
         * @param[in] sensor - the TachSensor to register
         */
        void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor)
        {
            auto found = std::find_if(
                    _names.begin(),
                    _names.end(),
                    [&sensor](const auto& name)
                    {
                        return monitor::FAN_SENSOR_PATH +
                                std::get<sensorName>(name) == sensor->name();
                    });

            if (found != _names.end())
            {
                auto gs = std::make_tuple(sensor, std::get<inTrust>(*found));
                _sensors.push_back(gs);
            }
        }

        /**
         * Says if a sensor belongs to the group.
         *
         * After all sensors have registered, this can be
         * used to say if a TachSensor is in the group.
         *
         * @param[in] sensor - the TachSensor object
         */
         bool inGroup(const monitor::TachSensor& sensor)
         {
             return (std::find_if(
                     _sensors.begin(),
                     _sensors.end(),
                     [&sensor](const auto& s)
                     {
                         return sensor.name() == std::get<0>(s)->name();
                     }) != _sensors.end());
         }

        /**
         * Stops the timers on all sensors in the group.
         *
         * Called when the group just changed to not trusted,
         * so that its sensors' timers can't fire a callback
         * that may cause them to be considered faulted.
         */
        void stopTimers()
        {
            std::for_each(
                    _sensors.begin(),
                    _sensors.end(),
                    [](const auto& s)
                    {
                        std::get<0>(s)->stopTimer();
                    });
        }

        /**
         * Starts the timers on all functional sensors in the group if
         * their target and input values do not match.
         *
         * Called when the group just changed to trusted.
         */
        void startTimers()
        {
            std::for_each(
                    _sensors.begin(),
                    _sensors.end(),
                    [](const auto& s)
                    {
                        //If a sensor isn't functional, then its timer
                        //already expired so don't bother starting it again
                        if (std::get<0>(s)->functional() &&
                            static_cast<uint64_t>(std::get<0>(s)->getInput()) !=
                                    std::get<0>(s)->getTarget())
                        {
                            std::get<0>(s)->startTimer();
                        }
                    });
        }

        /**
         * Determines the trust for this group based on this
         * sensor's latest status.
         *
         * Calls the derived class's checkGroupTrust function
         * and updates the class with the results.
         *
         * If this is called with a sensor not in the group,
         * it will be considered trusted.
         *
         * @param[in] sensor - TachSensor object
         *
         * @return tuple<bool, bool> -
         *   field 0 - the trust value
         *   field 1 - if that trust value changed since last call
         *             to checkTrust
         */
        auto checkTrust(const monitor::TachSensor& sensor)
        {
            if (inGroup(sensor))
            {
                auto trust = checkGroupTrust();

                setTrust(trust);

                return std::tuple<bool, bool>(_trusted, _stateChange);
            }
            return std::tuple<bool, bool>(true, false);
        }

        /**
         * Says if all sensors in the group are currently trusted,
         * as determined by the last call to checkTrust().
         *
         * @return bool - if the group's sensors are trusted or not
         */
        inline auto getTrust() const
        {
            return _trusted;
        }

        /**
         * Says if the trust value changed in the last call to
         * checkTrust()
         *
         * @return bool - if the trust changed or not
         */
        inline auto trustChanged() const
        {
            return _stateChange;
        }

    protected:

        /**
         * The sensor objects and their trust inclusion in the group.
         *
         * Added by registerSensor().
         */
        std::vector<std::tuple<
                std::shared_ptr<monitor::TachSensor>,
                bool>> _sensors;

    private:

        /**
         * Checks if the group's sensors are trusted.
         *
         * The derived class must override this function
         * to provide custom functionality.
         *
         * @return bool - if group is trusted or not
         */
        virtual bool checkGroupTrust() = 0;

        /**
         * Sets the trust value on the object.
         *
         * @param[in] trust - the new trust value
         */
        inline void setTrust(bool trust)
        {
            _stateChange = (trust != _trusted);
            _trusted = trust;
        }

        /**
         * The current trust state of the group
         */
        bool _trusted = true;

        /**
         * If the trust value changed in the last call to checkTrust
         */
        bool _stateChange = false;

        /**
         * The names of the sensors and whether it is included in
         * determining trust for this group
         */
        const std::vector<GroupDefinition> _names;
};

}
}
}
OpenPOWER on IntegriCloud