blob: ce06affa6c512dc2f2b3b5e8d4c79e9c2c5d90a9 [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"
Bob Kingb1ab1cf2020-05-18 18:26:26 +080019#include "pmbus_utils.hpp"
Shawn McCarneyc69a2752019-10-30 17:37:30 -050020
21#include <cstddef> // for size_t
Shawn McCarney0fd07d72020-03-06 17:16:24 -060022#include <optional>
Shawn McCarneyc69a2752019-10-30 17:37:30 -050023#include <stdexcept>
24#include <string>
Bob Kingb1ab1cf2020-05-18 18:26:26 +080025#include <vector>
Shawn McCarneyc69a2752019-10-30 17:37:30 -050026
Shawn McCarneyea7385b2019-11-07 12:19:32 -060027namespace phosphor::power::regulators
Shawn McCarneyc69a2752019-10-30 17:37:30 -050028{
29
Shawn McCarney494ef032019-11-07 15:56:50 -060030// Forward declarations to avoid circular dependencies
31class Device;
32class Rule;
33
Shawn McCarneyc69a2752019-10-30 17:37:30 -050034/**
35 * @class ActionEnvironment
36 *
37 * The current environment when executing actions.
38 *
39 * The ActionEnvironment contains the following information:
40 * - current device ID
41 * - current volts value (if any)
42 * - mapping from device and rule IDs to the corresponding objects
43 * - rule call stack depth (to detect infinite recursion)
Bob Kingb1ab1cf2020-05-18 18:26:26 +080044 * - sensor readings
Shawn McCarneyc69a2752019-10-30 17:37:30 -050045 */
46class ActionEnvironment
47{
48 public:
49 // Specify which compiler-generated methods we want
50 ActionEnvironment() = delete;
51 ActionEnvironment(const ActionEnvironment&) = delete;
52 ActionEnvironment(ActionEnvironment&&) = delete;
53 ActionEnvironment& operator=(const ActionEnvironment&) = delete;
54 ActionEnvironment& operator=(ActionEnvironment&&) = delete;
55 ~ActionEnvironment() = default;
56
57 /**
58 * Maximum rule call stack depth. Used to detect infinite recursion.
59 */
60 static constexpr size_t maxRuleDepth{30};
61
62 /**
63 * Constructor.
64 *
65 * @param idMap mapping from IDs to the associated Device/Rule objects
66 * @param deviceID current device ID
67 */
68 explicit ActionEnvironment(const IDMap& idMap,
69 const std::string& deviceID) :
70 idMap{idMap},
71 deviceID{deviceID}
72 {
73 }
74
75 /**
Bob Kingb1ab1cf2020-05-18 18:26:26 +080076 * Adds the specified sensor reading to this action environment.
77 *
78 * @param reading sensor reading from a regulator rail
79 */
80 void addSensorReading(const pmbus_utils::SensorReading& reading)
81 {
82 sensorReadings.emplace_back(reading);
83 }
84
85 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -050086 * Decrements the rule call stack depth by one.
87 *
88 * Should be used when a call to a rule returns. Does nothing if depth is
89 * already 0.
90 */
91 void decrementRuleDepth()
92 {
93 if (ruleDepth > 0)
94 {
95 --ruleDepth;
96 }
97 }
98
99 /**
100 * Returns the device with the current device ID.
101 *
102 * Throws invalid_argument if no device is found with current ID.
103 *
104 * @return device with current device ID
105 */
106 Device& getDevice() const
107 {
108 return idMap.getDevice(deviceID);
109 }
110
111 /**
112 * Returns the current device ID.
113 *
114 * @return current device ID
115 */
116 const std::string& getDeviceID() const
117 {
118 return deviceID;
119 }
120
121 /**
122 * Returns the rule with the specified ID.
123 *
124 * Throws invalid_argument if no rule is found with specified ID.
125 *
126 * @param id rule ID
127 * @return rule with specified ID
128 */
129 Rule& getRule(const std::string& id) const
130 {
131 return idMap.getRule(id);
132 }
133
134 /**
135 * Returns the current rule call stack depth.
136 *
137 * The depth is 0 if no rules have been called.
138 *
139 * @return rule call stack depth
140 */
141 size_t getRuleDepth() const
142 {
143 return ruleDepth;
144 }
145
146 /**
Bob Kingb1ab1cf2020-05-18 18:26:26 +0800147 * Returns the sensor readings stored in this action environment.
148 *
149 * @return sensor readings
150 */
151 const std::vector<pmbus_utils::SensorReading>& getSensorReadings() const
152 {
153 return sensorReadings;
154 }
155
156 /**
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600157 * Returns the current volts value, if set.
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500158 *
159 * @return current volts value
160 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600161 std::optional<double> getVolts() const
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500162 {
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500163 return volts;
164 }
165
166 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500167 * Increments the rule call stack depth by one.
168 *
169 * Should be used when a rule is called.
170 *
171 * Throws runtime_error if the new depth exceeds maxRuleDepth. This
172 * indicates that infinite recursion has probably occurred (rule A -> rule B
173 * -> rule A).
Shawn McCarney2134ca62019-11-11 13:06:18 -0600174 *
175 * @param ruleID ID of the rule that is being called
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500176 */
Shawn McCarney2134ca62019-11-11 13:06:18 -0600177 void incrementRuleDepth(const std::string& ruleID)
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500178 {
179 if (ruleDepth >= maxRuleDepth)
180 {
Shawn McCarney2134ca62019-11-11 13:06:18 -0600181 throw std::runtime_error("Maximum rule depth exceeded by rule " +
182 ruleID + '.');
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500183 }
184 ++ruleDepth;
185 }
186
187 /**
188 * Sets the current device ID.
189 *
190 * @param id device ID
191 */
192 void setDeviceID(const std::string& id)
193 {
194 deviceID = id;
195 }
196
197 /**
198 * Sets the current volts value.
199 *
200 * @param volts new volts value.
201 */
202 void setVolts(double volts)
203 {
204 this->volts = volts;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500205 }
206
207 private:
208 /**
209 * Mapping from string IDs to the associated Device and Rule objects.
210 */
Shawn McCarney494ef032019-11-07 15:56:50 -0600211 const IDMap& idMap;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500212
213 /**
214 * Current device ID.
215 */
216 std::string deviceID{};
217
218 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500219 * Current volts value (if set).
220 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600221 std::optional<double> volts{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500222
223 /**
224 * Rule call stack depth.
225 */
226 size_t ruleDepth{0};
Bob Kingb1ab1cf2020-05-18 18:26:26 +0800227
228 /**
229 * Sensor readings for a single regulator rail.
230 */
231 std::vector<pmbus_utils::SensorReading> sensorReadings{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500232};
233
Shawn McCarneyea7385b2019-11-07 12:19:32 -0600234} // namespace phosphor::power::regulators