| 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 |