1 /**
2 * Copyright © 2021 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 #include "net_target_decrease.hpp"
17
18 #include "../manager.hpp"
19 #include "../zone.hpp"
20 #include "action.hpp"
21 #include "group.hpp"
22
23 #include <nlohmann/json.hpp>
24 #include <phosphor-logging/lg2.hpp>
25
26 #include <algorithm>
27 #include <variant>
28
29 namespace phosphor::fan::control::json
30 {
31
32 using json = nlohmann::json;
33
NetTargetDecrease(const json & jsonObj,const std::vector<Group> & groups)34 NetTargetDecrease::NetTargetDecrease(const json& jsonObj,
35 const std::vector<Group>& groups) :
36 ActionBase(jsonObj, groups)
37 {
38 setState(jsonObj);
39 setDelta(jsonObj);
40 }
41
run(Zone & zone)42 void NetTargetDecrease::run(Zone& zone)
43 {
44 if (!_stateParameter.empty())
45 {
46 auto s = Manager::getParameter(_stateParameter);
47 if (!s)
48 {
49 return;
50 }
51 _state = *s;
52 }
53
54 auto netDelta = zone.getDecDelta();
55 for (const auto& group : _groups)
56 {
57 for (const auto& member : group.getMembers())
58 {
59 try
60 {
61 auto value = Manager::getObjValueVariant(
62 member, group.getInterface(), group.getProperty());
63 if (std::holds_alternative<int64_t>(value) ||
64 std::holds_alternative<double>(value))
65 {
66 if (value >= _state)
67 {
68 // No decrease allowed for this group
69 netDelta = 0;
70 break;
71 }
72 else
73 {
74 // Decrease factor is the difference in configured state
75 // to the current value's state
76 uint64_t deltaFactor = 0;
77 if (auto dblPtr = std::get_if<double>(&value))
78 {
79 deltaFactor = static_cast<uint64_t>(
80 std::get<double>(_state) - *dblPtr);
81 }
82 else
83 {
84 deltaFactor = static_cast<uint64_t>(
85 std::get<int64_t>(_state) -
86 std::get<int64_t>(value));
87 }
88
89 // Multiply the decrease factor by the configured delta
90 // to get the net decrease delta for the given group
91 // member. The lowest net decrease delta of the entire
92 // group is the decrease requested.
93 if (netDelta == 0)
94 {
95 netDelta = deltaFactor * _delta;
96 }
97 else
98 {
99 netDelta = std::min(netDelta, deltaFactor * _delta);
100 }
101 }
102 }
103 else if (std::holds_alternative<bool>(value) ||
104 std::holds_alternative<std::string>(value))
105 {
106 // Where a group of booleans or strings equal the state
107 // provided, request a decrease of the configured delta
108 if (_state == value)
109 {
110 if (netDelta == 0)
111 {
112 netDelta = _delta;
113 }
114 else
115 {
116 netDelta = std::min(netDelta, _delta);
117 }
118 }
119 }
120 else
121 {
122 // Unsupported group member type for this action
123 lg2::error(
124 "Action {ACTION_NAME}: Unsupported group member type "
125 "given. [object = {MEMBER} : {GROUP_INTERFACE} : {GROUP_PROPERTY}]",
126 "ACTION_NAME", ActionBase::getName(), "MEMBER", member,
127 "GROUP_INTERFACE", group.getInterface(),
128 "GROUP_PROPERTY", group.getProperty());
129 }
130 }
131 catch (const std::out_of_range& oore)
132 {
133 // Property value not found, netDelta unchanged
134 }
135 }
136 // Update group's decrease allowed state
137 zone.setDecreaseAllow(group.getName(), !(netDelta == 0));
138 }
139 // Request target decrease to occur on decrease interval
140 zone.requestDecrease(netDelta);
141 }
142
setState(const json & jsonObj)143 void NetTargetDecrease::setState(const json& jsonObj)
144 {
145 if (jsonObj.contains("state"))
146 {
147 _state = getJsonValue(jsonObj["state"]);
148 }
149 else if (jsonObj.contains("state_parameter_name"))
150 {
151 _stateParameter = jsonObj["state_parameter_name"].get<std::string>();
152 }
153 else
154 {
155 throw ActionParseError{
156 ActionBase::getName(),
157 "Missing required state or state_parameter_name value"};
158 }
159 }
160
setDelta(const json & jsonObj)161 void NetTargetDecrease::setDelta(const json& jsonObj)
162 {
163 if (!jsonObj.contains("delta"))
164 {
165 throw ActionParseError{ActionBase::getName(),
166 "Missing required delta value"};
167 }
168 _delta = jsonObj["delta"].get<uint64_t>();
169 }
170
171 } // namespace phosphor::fan::control::json
172