Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include "logging.hpp" |
| 4 | #include "power_off_action.hpp" |
| 5 | #include "power_off_cause.hpp" |
| 6 | |
| 7 | #include <memory> |
| 8 | |
| 9 | namespace 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 | */ |
| 16 | enum 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 | */ |
| 33 | class 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 Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame^] | 53 | _validState(validState), _cause(std::move(cause)), |
| 54 | _action(std::move(action)) |
Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 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 | { |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 79 | 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 Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 84 | { |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 85 | // Start the action |
| 86 | getLogger().log( |
Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 87 | std::format("Starting shutdown action '{}' due to cause '{}'", |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 88 | _action->name(), _cause->name())); |
Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 89 | |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 90 | _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 Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 97 | { |
Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 98 | getLogger().log(std::format("Stopped shutdown action '{}'", |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 99 | _action->name())); |
| 100 | _active = false; |
Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 101 | } |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 102 | else |
Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 103 | { |
Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 104 | getLogger().log(std::format( |
Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 105 | "Could not stop shutdown action '{}'", _action->name())); |
Matt Spinler | f06ab07 | 2020-10-14 12:58:22 -0500 | [diff] [blame] | 106 | } |
| 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 |