blob: 7f6c4027c74e2c9a0b2dee3e7326e38653704c9f [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}
Shawn McCarneyc69a2752019-10-30 17:37:30 -050077 {
78 }
79
80 /**
Shawn McCarney421128e2021-08-25 10:00:59 -050081 * Adds the specified key/value pair to the map of additional error data
82 * that has been captured.
83 *
84 * This data provides more information about an error and will be stored in
85 * the error log.
86 *
87 * @param key key name
88 * @param value value expressed as a string
89 */
90 void addAdditionalErrorData(const std::string& key,
91 const std::string& value)
92 {
93 additionalErrorData.emplace(key, value);
94 }
95
96 /**
97 * Adds the specified phase fault to the set of faults that have been
98 * detected.
99 *
100 * @param type phase fault type
101 */
102 void addPhaseFault(PhaseFaultType type)
103 {
104 phaseFaults.emplace(type);
105 }
106
107 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500108 * Decrements the rule call stack depth by one.
109 *
110 * Should be used when a call to a rule returns. Does nothing if depth is
111 * already 0.
112 */
113 void decrementRuleDepth()
114 {
115 if (ruleDepth > 0)
116 {
117 --ruleDepth;
118 }
119 }
120
121 /**
Shawn McCarney421128e2021-08-25 10:00:59 -0500122 * Returns the additional error data that has been captured (if any).
123 *
124 * @return additional error data
125 */
126 const std::map<std::string, std::string>& getAdditionalErrorData() const
127 {
128 return additionalErrorData;
129 }
130
131 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500132 * Returns the device with the current device ID.
133 *
134 * Throws invalid_argument if no device is found with current ID.
135 *
136 * @return device with current device ID
137 */
138 Device& getDevice() const
139 {
140 return idMap.getDevice(deviceID);
141 }
142
143 /**
144 * Returns the current device ID.
145 *
146 * @return current device ID
147 */
148 const std::string& getDeviceID() const
149 {
150 return deviceID;
151 }
152
153 /**
Shawn McCarney421128e2021-08-25 10:00:59 -0500154 * Returns the set of phase faults that have been detected (if any).
155 *
156 * @return phase faults detected
157 */
158 const std::set<PhaseFaultType>& getPhaseFaults() const
159 {
160 return phaseFaults;
161 }
162
163 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500164 * Returns the rule with the specified ID.
165 *
166 * Throws invalid_argument if no rule is found with specified ID.
167 *
168 * @param id rule ID
169 * @return rule with specified ID
170 */
171 Rule& getRule(const std::string& id) const
172 {
173 return idMap.getRule(id);
174 }
175
176 /**
177 * Returns the current rule call stack depth.
178 *
179 * The depth is 0 if no rules have been called.
180 *
181 * @return rule call stack depth
182 */
183 size_t getRuleDepth() const
184 {
185 return ruleDepth;
186 }
187
188 /**
Bob King73eacee2020-10-23 13:58:02 +0800189 * Returns the services in this action environment.
190 *
191 * @return system services
192 */
193 Services& getServices() const
194 {
195 return services;
196 }
197
198 /**
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600199 * Returns the current volts value, if set.
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500200 *
201 * @return current volts value
202 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600203 std::optional<double> getVolts() const
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500204 {
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500205 return volts;
206 }
207
208 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500209 * Increments the rule call stack depth by one.
210 *
211 * Should be used when a rule is called.
212 *
213 * Throws runtime_error if the new depth exceeds maxRuleDepth. This
214 * indicates that infinite recursion has probably occurred (rule A -> rule B
215 * -> rule A).
Shawn McCarney2134ca62019-11-11 13:06:18 -0600216 *
217 * @param ruleID ID of the rule that is being called
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500218 */
Shawn McCarney2134ca62019-11-11 13:06:18 -0600219 void incrementRuleDepth(const std::string& ruleID)
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500220 {
221 if (ruleDepth >= maxRuleDepth)
222 {
Shawn McCarney2134ca62019-11-11 13:06:18 -0600223 throw std::runtime_error("Maximum rule depth exceeded by rule " +
224 ruleID + '.');
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500225 }
226 ++ruleDepth;
227 }
228
229 /**
230 * Sets the current device ID.
231 *
232 * @param id device ID
233 */
234 void setDeviceID(const std::string& id)
235 {
236 deviceID = id;
237 }
238
239 /**
240 * Sets the current volts value.
241 *
242 * @param volts new volts value.
243 */
244 void setVolts(double volts)
245 {
246 this->volts = volts;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500247 }
248
249 private:
250 /**
251 * Mapping from string IDs to the associated Device and Rule objects.
252 */
Shawn McCarney494ef032019-11-07 15:56:50 -0600253 const IDMap& idMap;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500254
255 /**
256 * Current device ID.
257 */
258 std::string deviceID{};
259
260 /**
Bob King73eacee2020-10-23 13:58:02 +0800261 * System services like error logging and the journal.
262 */
263 Services& services;
264
265 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500266 * Current volts value (if set).
267 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600268 std::optional<double> volts{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500269
270 /**
271 * Rule call stack depth.
272 */
273 size_t ruleDepth{0};
Shawn McCarney421128e2021-08-25 10:00:59 -0500274
275 /**
276 * Redundant phase faults that have been detected.
277 */
278 std::set<PhaseFaultType> phaseFaults{};
279
280 /**
281 * Additional error data that has been captured.
282 */
283 std::map<std::string, std::string> additionalErrorData{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500284};
285
Shawn McCarneyea7385b2019-11-07 12:19:32 -0600286} // namespace phosphor::power::regulators