| /** |
| * Copyright © 2019 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include "id_map.hpp" |
| #include "phase_fault.hpp" |
| #include "services.hpp" |
| |
| #include <cstddef> // for size_t |
| #include <map> |
| #include <optional> |
| #include <set> |
| #include <stdexcept> |
| #include <string> |
| |
| namespace phosphor::power::regulators |
| { |
| |
| // Forward declarations to avoid circular dependencies |
| class Device; |
| class Rule; |
| |
| /** |
| * @class ActionEnvironment |
| * |
| * The current environment when executing actions. |
| * |
| * The ActionEnvironment contains the following information: |
| * - current device ID |
| * - current volts value (if any) |
| * - mapping from device and rule IDs to the corresponding objects |
| * - rule call stack depth (to detect infinite recursion) |
| * - reference to system services |
| * - faults detected by actions (if any) |
| * - additional error data captured by actions (if any) |
| */ |
| class ActionEnvironment |
| { |
| public: |
| // Specify which compiler-generated methods we want |
| ActionEnvironment() = delete; |
| ActionEnvironment(const ActionEnvironment&) = delete; |
| ActionEnvironment(ActionEnvironment&&) = delete; |
| ActionEnvironment& operator=(const ActionEnvironment&) = delete; |
| ActionEnvironment& operator=(ActionEnvironment&&) = delete; |
| ~ActionEnvironment() = default; |
| |
| /** |
| * Maximum rule call stack depth. Used to detect infinite recursion. |
| */ |
| static constexpr size_t maxRuleDepth{30}; |
| |
| /** |
| * Constructor. |
| * |
| * @param idMap mapping from IDs to the associated Device/Rule objects |
| * @param deviceID current device ID |
| * @param services system services like error logging and the journal |
| */ |
| explicit ActionEnvironment(const IDMap& idMap, const std::string& deviceID, |
| Services& services) : |
| idMap{idMap}, |
| deviceID{deviceID}, services{services} |
| {} |
| |
| /** |
| * Adds the specified key/value pair to the map of additional error data |
| * that has been captured. |
| * |
| * This data provides more information about an error and will be stored in |
| * the error log. |
| * |
| * @param key key name |
| * @param value value expressed as a string |
| */ |
| void addAdditionalErrorData(const std::string& key, |
| const std::string& value) |
| { |
| additionalErrorData.emplace(key, value); |
| } |
| |
| /** |
| * Adds the specified phase fault to the set of faults that have been |
| * detected. |
| * |
| * @param type phase fault type |
| */ |
| void addPhaseFault(PhaseFaultType type) |
| { |
| phaseFaults.emplace(type); |
| } |
| |
| /** |
| * Decrements the rule call stack depth by one. |
| * |
| * Should be used when a call to a rule returns. Does nothing if depth is |
| * already 0. |
| */ |
| void decrementRuleDepth() |
| { |
| if (ruleDepth > 0) |
| { |
| --ruleDepth; |
| } |
| } |
| |
| /** |
| * Returns the additional error data that has been captured (if any). |
| * |
| * @return additional error data |
| */ |
| const std::map<std::string, std::string>& getAdditionalErrorData() const |
| { |
| return additionalErrorData; |
| } |
| |
| /** |
| * Returns the device with the current device ID. |
| * |
| * Throws invalid_argument if no device is found with current ID. |
| * |
| * @return device with current device ID |
| */ |
| Device& getDevice() const |
| { |
| return idMap.getDevice(deviceID); |
| } |
| |
| /** |
| * Returns the current device ID. |
| * |
| * @return current device ID |
| */ |
| const std::string& getDeviceID() const |
| { |
| return deviceID; |
| } |
| |
| /** |
| * Returns the set of phase faults that have been detected (if any). |
| * |
| * @return phase faults detected |
| */ |
| const std::set<PhaseFaultType>& getPhaseFaults() const |
| { |
| return phaseFaults; |
| } |
| |
| /** |
| * Returns the rule with the specified ID. |
| * |
| * Throws invalid_argument if no rule is found with specified ID. |
| * |
| * @param id rule ID |
| * @return rule with specified ID |
| */ |
| Rule& getRule(const std::string& id) const |
| { |
| return idMap.getRule(id); |
| } |
| |
| /** |
| * Returns the current rule call stack depth. |
| * |
| * The depth is 0 if no rules have been called. |
| * |
| * @return rule call stack depth |
| */ |
| size_t getRuleDepth() const |
| { |
| return ruleDepth; |
| } |
| |
| /** |
| * Returns the services in this action environment. |
| * |
| * @return system services |
| */ |
| Services& getServices() const |
| { |
| return services; |
| } |
| |
| /** |
| * Returns the current volts value, if set. |
| * |
| * @return current volts value |
| */ |
| std::optional<double> getVolts() const |
| { |
| return volts; |
| } |
| |
| /** |
| * Increments the rule call stack depth by one. |
| * |
| * Should be used when a rule is called. |
| * |
| * Throws runtime_error if the new depth exceeds maxRuleDepth. This |
| * indicates that infinite recursion has probably occurred (rule A -> rule B |
| * -> rule A). |
| * |
| * @param ruleID ID of the rule that is being called |
| */ |
| void incrementRuleDepth(const std::string& ruleID) |
| { |
| if (ruleDepth >= maxRuleDepth) |
| { |
| throw std::runtime_error("Maximum rule depth exceeded by rule " + |
| ruleID + '.'); |
| } |
| ++ruleDepth; |
| } |
| |
| /** |
| * Sets the current device ID. |
| * |
| * @param id device ID |
| */ |
| void setDeviceID(const std::string& id) |
| { |
| deviceID = id; |
| } |
| |
| /** |
| * Sets the current volts value. |
| * |
| * @param volts new volts value. |
| */ |
| void setVolts(double volts) |
| { |
| this->volts = volts; |
| } |
| |
| private: |
| /** |
| * Mapping from string IDs to the associated Device and Rule objects. |
| */ |
| const IDMap& idMap; |
| |
| /** |
| * Current device ID. |
| */ |
| std::string deviceID{}; |
| |
| /** |
| * System services like error logging and the journal. |
| */ |
| Services& services; |
| |
| /** |
| * Current volts value (if set). |
| */ |
| std::optional<double> volts{}; |
| |
| /** |
| * Rule call stack depth. |
| */ |
| size_t ruleDepth{0}; |
| |
| /** |
| * Redundant phase faults that have been detected. |
| */ |
| std::set<PhaseFaultType> phaseFaults{}; |
| |
| /** |
| * Additional error data that has been captured. |
| */ |
| std::map<std::string, std::string> additionalErrorData{}; |
| }; |
| |
| } // namespace phosphor::power::regulators |