blob: 22e8469915ae890e862ab942bbd401f4936df680 [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) :
Patrick Williamsdfddd642024-08-16 15:21:51 -040053 _validState(validState), _cause(std::move(cause)),
54 _action(std::move(action))
Matt Spinlerf06ab072020-10-14 12:58:22 -050055 {}
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 {
Matt Spinler7d135642021-02-04 12:44:17 -060079 auto satisfied = _cause->satisfied(fanHealth);
80
81 // Only start an action if it matches on the current state,
82 // but be able to stop it no matter what the state is.
83 if (!_active && satisfied && (state == _validState))
Matt Spinlerf06ab072020-10-14 12:58:22 -050084 {
Matt Spinler7d135642021-02-04 12:44:17 -060085 // Start the action
86 getLogger().log(
Patrick Williamsfbf47032023-07-17 12:27:34 -050087 std::format("Starting shutdown action '{}' due to cause '{}'",
Matt Spinler7d135642021-02-04 12:44:17 -060088 _action->name(), _cause->name()));
Matt Spinlerf06ab072020-10-14 12:58:22 -050089
Matt Spinler7d135642021-02-04 12:44:17 -060090 _active = true;
91 _action->start();
92 }
93 else if (_active && !satisfied)
94 {
95 // Attempt to cancel the action, but don't force it
96 if (_action->cancel(false))
Matt Spinlerf06ab072020-10-14 12:58:22 -050097 {
Patrick Williamsfbf47032023-07-17 12:27:34 -050098 getLogger().log(std::format("Stopped shutdown action '{}'",
Matt Spinler7d135642021-02-04 12:44:17 -060099 _action->name()));
100 _active = false;
Matt Spinlerf06ab072020-10-14 12:58:22 -0500101 }
Matt Spinler7d135642021-02-04 12:44:17 -0600102 else
Matt Spinlerf06ab072020-10-14 12:58:22 -0500103 {
Patrick Williamsfbf47032023-07-17 12:27:34 -0500104 getLogger().log(std::format(
Matt Spinler7d135642021-02-04 12:44:17 -0600105 "Could not stop shutdown action '{}'", _action->name()));
Matt Spinlerf06ab072020-10-14 12:58:22 -0500106 }
107 }
108 }
109
110 /**
111 * @brief Says if there is an active power off in progress due to
112 * this rule.
113 *
114 * @return bool - If the rule is active or not
115 */
116 bool active() const
117 {
118 return _active;
119 }
120
121 private:
122 /**
123 * @brief The state the rule is valid for.
124 */
125 PowerRuleState _validState;
126
127 /**
128 * @brief If there is an active power off in progress.
129 */
130 bool _active{false};
131
132 /**
133 * @brief Base class pointer to the power off cause class
134 */
135 std::unique_ptr<PowerOffCause> _cause;
136
137 /**
138 * @brief Base class pointer to the power off action class
139 */
140 std::unique_ptr<PowerOffAction> _action;
141};
142
143} // namespace phosphor::fan::monitor