blob: f28dce686b6ba7da1f6cd19b705247ee75d838ed [file] [log] [blame]
Matt Spinlerf06ab072020-10-14 12:58:22 -05001#pragma once
2
3#include "logging.hpp"
4#include "power_off_action.hpp"
5#include "power_off_cause.hpp"
6
7#include <memory>
8
9namespace phosphor::fan::monitor
10{
11
12/**
13 * @brief Describes when the rule should be checked.
14 * either right at PGOOD, or anytime at runtime.
15 */
16enum class PowerRuleState
17{
18 atPgood, // Only at the moment when PGOOD switches on.
19 runtime // Anytime that power is on.
20};
21
22/**
23 * @class PowerOffRule
24 *
25 * This class implements a power off rule, which has a cause
26 * that is based on fan status, and an action which is the type of
27 * power off that will occur when the cause is satisfied.
28 *
29 * The user of this class calls the 'check()' method when fan
30 * status may have changed, and then the power off action may
31 * be started.
32 */
33class PowerOffRule
34{
35 public:
36 PowerOffRule() = delete;
37 ~PowerOffRule() = default;
38 PowerOffRule(const PowerOffRule&) = delete;
39 PowerOffRule& operator=(const PowerOffRule&) = delete;
40 PowerOffRule(PowerOffRule&&) = delete;
41 PowerOffRule& operator=(PowerOffRule&&) = delete;
42
43 /**
44 * @brief Constructor
45 *
46 * @param[in] validState - What state the rule is valid for
47 * @param[in] cause - The power off cause to use
48 * @param[in] action - The power off action to use
49 */
50 PowerOffRule(PowerRuleState validState,
51 std::unique_ptr<PowerOffCause> cause,
52 std::unique_ptr<PowerOffAction> action) :
53 _validState(validState),
54 _cause(std::move(cause)), _action(std::move(action))
55 {}
56
57 /**
58 * @brief Used to cancel a delay based power off when
59 * there is still time left.
60 */
61 void cancel()
62 {
63 _active = false;
64
65 // force the cancel
66 _action->cancel(true);
67 }
68
69 /**
70 * @brief Checks the cause against the passed in fan health
71 * and starts the power off action if the cause
72 * is satisfied.
73 *
74 * @param[in] state - The state to check the rule at
75 * @param[in] fanHealth - The fan health map
76 */
77 void check(PowerRuleState state, const FanHealth& fanHealth)
78 {
79 if (state == _validState)
80 {
81 auto satisfied = _cause->satisfied(fanHealth);
82
83 if (!_active && satisfied)
84 {
85 // Start the action
86 _active = true;
87 _action->start();
88 getLogger().log(fmt::format(
89 "Starting shutdown action '{}' due to cause '{}'",
90 _action->name(), _cause->name()));
91 }
92 else if (_active && !satisfied)
93 {
94 // Attempt to cancel the action, but don't force it
95 if (_action->cancel(false))
96 {
97 getLogger().log(fmt::format("Stopped shutdown action '{}'",
98 _action->name()));
99 _active = false;
100 }
101 else
102 {
103 getLogger().log(
104 fmt::format("Could not stop shutdown action '{}'",
105 _action->name()));
106 }
107 }
108 }
109 }
110
111 /**
112 * @brief Says if there is an active power off in progress due to
113 * this rule.
114 *
115 * @return bool - If the rule is active or not
116 */
117 bool active() const
118 {
119 return _active;
120 }
121
122 private:
123 /**
124 * @brief The state the rule is valid for.
125 */
126 PowerRuleState _validState;
127
128 /**
129 * @brief If there is an active power off in progress.
130 */
131 bool _active{false};
132
133 /**
134 * @brief Base class pointer to the power off cause class
135 */
136 std::unique_ptr<PowerOffCause> _cause;
137
138 /**
139 * @brief Base class pointer to the power off action class
140 */
141 std::unique_ptr<PowerOffAction> _action;
142};
143
144} // namespace phosphor::fan::monitor