blob: 265a7bf33fdad42b15965592a85e5438aea404f0 [file] [log] [blame]
Shawn McCarneyc69a2752019-10-30 17:37:30 -05001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
Shawn McCarneyc69a2752019-10-30 17:37:30 -050018#include "id_map.hpp"
Shawn McCarney421128e2021-08-25 10:00:59 -050019#include "phase_fault.hpp"
Bob King73eacee2020-10-23 13:58:02 +080020#include "services.hpp"
Shawn McCarneyc69a2752019-10-30 17:37:30 -050021
22#include <cstddef> // for size_t
Shawn McCarney421128e2021-08-25 10:00:59 -050023#include <map>
Shawn McCarney0fd07d72020-03-06 17:16:24 -060024#include <optional>
Shawn McCarney421128e2021-08-25 10:00:59 -050025#include <set>
Shawn McCarneyc69a2752019-10-30 17:37:30 -050026#include <stdexcept>
27#include <string>
28
Shawn McCarneyea7385b2019-11-07 12:19:32 -060029namespace phosphor::power::regulators
Shawn McCarneyc69a2752019-10-30 17:37:30 -050030{
31
Shawn McCarney494ef032019-11-07 15:56:50 -060032// Forward declarations to avoid circular dependencies
33class Device;
34class Rule;
35
Shawn McCarneyc69a2752019-10-30 17:37:30 -050036/**
37 * @class ActionEnvironment
38 *
39 * The current environment when executing actions.
40 *
41 * The ActionEnvironment contains the following information:
42 * - current device ID
43 * - current volts value (if any)
44 * - mapping from device and rule IDs to the corresponding objects
45 * - rule call stack depth (to detect infinite recursion)
Shawn McCarney421128e2021-08-25 10:00:59 -050046 * - reference to system services
47 * - faults detected by actions (if any)
48 * - additional error data captured by actions (if any)
Shawn McCarneyc69a2752019-10-30 17:37:30 -050049 */
50class ActionEnvironment
51{
52 public:
53 // Specify which compiler-generated methods we want
54 ActionEnvironment() = delete;
55 ActionEnvironment(const ActionEnvironment&) = delete;
56 ActionEnvironment(ActionEnvironment&&) = delete;
57 ActionEnvironment& operator=(const ActionEnvironment&) = delete;
58 ActionEnvironment& operator=(ActionEnvironment&&) = delete;
59 ~ActionEnvironment() = default;
60
61 /**
62 * Maximum rule call stack depth. Used to detect infinite recursion.
63 */
64 static constexpr size_t maxRuleDepth{30};
65
66 /**
67 * Constructor.
68 *
69 * @param idMap mapping from IDs to the associated Device/Rule objects
70 * @param deviceID current device ID
Bob King73eacee2020-10-23 13:58:02 +080071 * @param services system services like error logging and the journal
Shawn McCarneyc69a2752019-10-30 17:37:30 -050072 */
Bob King73eacee2020-10-23 13:58:02 +080073 explicit ActionEnvironment(const IDMap& idMap, const std::string& deviceID,
74 Services& services) :
Shawn McCarneyc69a2752019-10-30 17:37:30 -050075 idMap{idMap},
Bob King73eacee2020-10-23 13:58:02 +080076 deviceID{deviceID}, services{services}
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +000077 {}
Shawn McCarneyc69a2752019-10-30 17:37:30 -050078
79 /**
Shawn McCarney421128e2021-08-25 10:00:59 -050080 * Adds the specified key/value pair to the map of additional error data
81 * that has been captured.
82 *
83 * This data provides more information about an error and will be stored in
84 * the error log.
85 *
86 * @param key key name
87 * @param value value expressed as a string
88 */
89 void addAdditionalErrorData(const std::string& key,
90 const std::string& value)
91 {
92 additionalErrorData.emplace(key, value);
93 }
94
95 /**
96 * Adds the specified phase fault to the set of faults that have been
97 * detected.
98 *
99 * @param type phase fault type
100 */
101 void addPhaseFault(PhaseFaultType type)
102 {
103 phaseFaults.emplace(type);
104 }
105
106 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500107 * Decrements the rule call stack depth by one.
108 *
109 * Should be used when a call to a rule returns. Does nothing if depth is
110 * already 0.
111 */
112 void decrementRuleDepth()
113 {
114 if (ruleDepth > 0)
115 {
116 --ruleDepth;
117 }
118 }
119
120 /**
Shawn McCarney421128e2021-08-25 10:00:59 -0500121 * Returns the additional error data that has been captured (if any).
122 *
123 * @return additional error data
124 */
125 const std::map<std::string, std::string>& getAdditionalErrorData() const
126 {
127 return additionalErrorData;
128 }
129
130 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500131 * Returns the device with the current device ID.
132 *
133 * Throws invalid_argument if no device is found with current ID.
134 *
135 * @return device with current device ID
136 */
137 Device& getDevice() const
138 {
139 return idMap.getDevice(deviceID);
140 }
141
142 /**
143 * Returns the current device ID.
144 *
145 * @return current device ID
146 */
147 const std::string& getDeviceID() const
148 {
149 return deviceID;
150 }
151
152 /**
Shawn McCarney421128e2021-08-25 10:00:59 -0500153 * Returns the set of phase faults that have been detected (if any).
154 *
155 * @return phase faults detected
156 */
157 const std::set<PhaseFaultType>& getPhaseFaults() const
158 {
159 return phaseFaults;
160 }
161
162 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500163 * Returns the rule with the specified ID.
164 *
165 * Throws invalid_argument if no rule is found with specified ID.
166 *
167 * @param id rule ID
168 * @return rule with specified ID
169 */
170 Rule& getRule(const std::string& id) const
171 {
172 return idMap.getRule(id);
173 }
174
175 /**
176 * Returns the current rule call stack depth.
177 *
178 * The depth is 0 if no rules have been called.
179 *
180 * @return rule call stack depth
181 */
182 size_t getRuleDepth() const
183 {
184 return ruleDepth;
185 }
186
187 /**
Bob King73eacee2020-10-23 13:58:02 +0800188 * Returns the services in this action environment.
189 *
190 * @return system services
191 */
192 Services& getServices() const
193 {
194 return services;
195 }
196
197 /**
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600198 * Returns the current volts value, if set.
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500199 *
200 * @return current volts value
201 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600202 std::optional<double> getVolts() const
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500203 {
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500204 return volts;
205 }
206
207 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500208 * Increments the rule call stack depth by one.
209 *
210 * Should be used when a rule is called.
211 *
212 * Throws runtime_error if the new depth exceeds maxRuleDepth. This
213 * indicates that infinite recursion has probably occurred (rule A -> rule B
214 * -> rule A).
Shawn McCarney2134ca62019-11-11 13:06:18 -0600215 *
216 * @param ruleID ID of the rule that is being called
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500217 */
Shawn McCarney2134ca62019-11-11 13:06:18 -0600218 void incrementRuleDepth(const std::string& ruleID)
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500219 {
220 if (ruleDepth >= maxRuleDepth)
221 {
Shawn McCarney2134ca62019-11-11 13:06:18 -0600222 throw std::runtime_error("Maximum rule depth exceeded by rule " +
223 ruleID + '.');
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500224 }
225 ++ruleDepth;
226 }
227
228 /**
229 * Sets the current device ID.
230 *
231 * @param id device ID
232 */
233 void setDeviceID(const std::string& id)
234 {
235 deviceID = id;
236 }
237
238 /**
239 * Sets the current volts value.
240 *
241 * @param volts new volts value.
242 */
243 void setVolts(double volts)
244 {
245 this->volts = volts;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500246 }
247
248 private:
249 /**
250 * Mapping from string IDs to the associated Device and Rule objects.
251 */
Shawn McCarney494ef032019-11-07 15:56:50 -0600252 const IDMap& idMap;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500253
254 /**
255 * Current device ID.
256 */
257 std::string deviceID{};
258
259 /**
Bob King73eacee2020-10-23 13:58:02 +0800260 * System services like error logging and the journal.
261 */
262 Services& services;
263
264 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500265 * Current volts value (if set).
266 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600267 std::optional<double> volts{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500268
269 /**
270 * Rule call stack depth.
271 */
272 size_t ruleDepth{0};
Shawn McCarney421128e2021-08-25 10:00:59 -0500273
274 /**
275 * Redundant phase faults that have been detected.
276 */
277 std::set<PhaseFaultType> phaseFaults{};
278
279 /**
280 * Additional error data that has been captured.
281 */
282 std::map<std::string, std::string> additionalErrorData{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500283};
284
Shawn McCarneyea7385b2019-11-07 12:19:32 -0600285} // namespace phosphor::power::regulators