blob: 72aa8f456dea1bf3e6606d70b2d7632cdd62a92d [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 King73eacee2020-10-23 13:58:02 +080019#include "services.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>
25
Shawn McCarneyea7385b2019-11-07 12:19:32 -060026namespace phosphor::power::regulators
Shawn McCarneyc69a2752019-10-30 17:37:30 -050027{
28
Shawn McCarney494ef032019-11-07 15:56:50 -060029// Forward declarations to avoid circular dependencies
30class Device;
31class Rule;
32
Shawn McCarneyc69a2752019-10-30 17:37:30 -050033/**
34 * @class ActionEnvironment
35 *
36 * The current environment when executing actions.
37 *
38 * The ActionEnvironment contains the following information:
39 * - current device ID
40 * - current volts value (if any)
41 * - mapping from device and rule IDs to the corresponding objects
42 * - rule call stack depth (to detect infinite recursion)
43 */
44class ActionEnvironment
45{
46 public:
47 // Specify which compiler-generated methods we want
48 ActionEnvironment() = delete;
49 ActionEnvironment(const ActionEnvironment&) = delete;
50 ActionEnvironment(ActionEnvironment&&) = delete;
51 ActionEnvironment& operator=(const ActionEnvironment&) = delete;
52 ActionEnvironment& operator=(ActionEnvironment&&) = delete;
53 ~ActionEnvironment() = default;
54
55 /**
56 * Maximum rule call stack depth. Used to detect infinite recursion.
57 */
58 static constexpr size_t maxRuleDepth{30};
59
60 /**
61 * Constructor.
62 *
63 * @param idMap mapping from IDs to the associated Device/Rule objects
64 * @param deviceID current device ID
Bob King73eacee2020-10-23 13:58:02 +080065 * @param services system services like error logging and the journal
Shawn McCarneyc69a2752019-10-30 17:37:30 -050066 */
Bob King73eacee2020-10-23 13:58:02 +080067 explicit ActionEnvironment(const IDMap& idMap, const std::string& deviceID,
68 Services& services) :
Shawn McCarneyc69a2752019-10-30 17:37:30 -050069 idMap{idMap},
Bob King73eacee2020-10-23 13:58:02 +080070 deviceID{deviceID}, services{services}
Shawn McCarneyc69a2752019-10-30 17:37:30 -050071 {
72 }
73
74 /**
75 * Decrements the rule call stack depth by one.
76 *
77 * Should be used when a call to a rule returns. Does nothing if depth is
78 * already 0.
79 */
80 void decrementRuleDepth()
81 {
82 if (ruleDepth > 0)
83 {
84 --ruleDepth;
85 }
86 }
87
88 /**
89 * Returns the device with the current device ID.
90 *
91 * Throws invalid_argument if no device is found with current ID.
92 *
93 * @return device with current device ID
94 */
95 Device& getDevice() const
96 {
97 return idMap.getDevice(deviceID);
98 }
99
100 /**
101 * Returns the current device ID.
102 *
103 * @return current device ID
104 */
105 const std::string& getDeviceID() const
106 {
107 return deviceID;
108 }
109
110 /**
111 * Returns the rule with the specified ID.
112 *
113 * Throws invalid_argument if no rule is found with specified ID.
114 *
115 * @param id rule ID
116 * @return rule with specified ID
117 */
118 Rule& getRule(const std::string& id) const
119 {
120 return idMap.getRule(id);
121 }
122
123 /**
124 * Returns the current rule call stack depth.
125 *
126 * The depth is 0 if no rules have been called.
127 *
128 * @return rule call stack depth
129 */
130 size_t getRuleDepth() const
131 {
132 return ruleDepth;
133 }
134
135 /**
Bob King73eacee2020-10-23 13:58:02 +0800136 * Returns the services in this action environment.
137 *
138 * @return system services
139 */
140 Services& getServices() const
141 {
142 return services;
143 }
144
145 /**
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600146 * Returns the current volts value, if set.
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500147 *
148 * @return current volts value
149 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600150 std::optional<double> getVolts() const
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500151 {
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500152 return volts;
153 }
154
155 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500156 * Increments the rule call stack depth by one.
157 *
158 * Should be used when a rule is called.
159 *
160 * Throws runtime_error if the new depth exceeds maxRuleDepth. This
161 * indicates that infinite recursion has probably occurred (rule A -> rule B
162 * -> rule A).
Shawn McCarney2134ca62019-11-11 13:06:18 -0600163 *
164 * @param ruleID ID of the rule that is being called
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500165 */
Shawn McCarney2134ca62019-11-11 13:06:18 -0600166 void incrementRuleDepth(const std::string& ruleID)
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500167 {
168 if (ruleDepth >= maxRuleDepth)
169 {
Shawn McCarney2134ca62019-11-11 13:06:18 -0600170 throw std::runtime_error("Maximum rule depth exceeded by rule " +
171 ruleID + '.');
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500172 }
173 ++ruleDepth;
174 }
175
176 /**
177 * Sets the current device ID.
178 *
179 * @param id device ID
180 */
181 void setDeviceID(const std::string& id)
182 {
183 deviceID = id;
184 }
185
186 /**
187 * Sets the current volts value.
188 *
189 * @param volts new volts value.
190 */
191 void setVolts(double volts)
192 {
193 this->volts = volts;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500194 }
195
196 private:
197 /**
198 * Mapping from string IDs to the associated Device and Rule objects.
199 */
Shawn McCarney494ef032019-11-07 15:56:50 -0600200 const IDMap& idMap;
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500201
202 /**
203 * Current device ID.
204 */
205 std::string deviceID{};
206
207 /**
Bob King73eacee2020-10-23 13:58:02 +0800208 * System services like error logging and the journal.
209 */
210 Services& services;
211
212 /**
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500213 * Current volts value (if set).
214 */
Shawn McCarney0fd07d72020-03-06 17:16:24 -0600215 std::optional<double> volts{};
Shawn McCarneyc69a2752019-10-30 17:37:30 -0500216
217 /**
218 * Rule call stack depth.
219 */
220 size_t ruleDepth{0};
221};
222
Shawn McCarneyea7385b2019-11-07 12:19:32 -0600223} // namespace phosphor::power::regulators