| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 1 | /** | 
| Mike Capps | b2e9a4f | 2022-06-13 10:15:42 -0400 | [diff] [blame] | 2 |  * Copyright © 2022 IBM Corporation | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 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 |  */ | 
| Matthew Barth | b584d81 | 2021-03-11 15:55:04 -0600 | [diff] [blame] | 16 | #include "config.h" | 
 | 17 |  | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 18 | #include "manager.hpp" | 
 | 19 |  | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 20 | #include "action.hpp" | 
| Mike Capps | bf8e56f | 2022-06-29 14:23:07 -0400 | [diff] [blame] | 21 | #include "dbus_paths.hpp" | 
| Matthew Barth | 44ab769 | 2021-03-26 11:40:10 -0500 | [diff] [blame] | 22 | #include "event.hpp" | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 23 | #include "fan.hpp" | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 24 | #include "group.hpp" | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 25 | #include "json_config.hpp" | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 26 | #include "power_state.hpp" | 
| Matthew Barth | 0676494 | 2021-03-04 09:28:40 -0600 | [diff] [blame] | 27 | #include "profile.hpp" | 
| Matthew Barth | 9403a21 | 2021-05-17 09:31:50 -0500 | [diff] [blame] | 28 | #include "sdbusplus.hpp" | 
| Matthew Barth | bd52ed0 | 2022-02-07 15:15:10 -0600 | [diff] [blame] | 29 | #include "utils/flight_recorder.hpp" | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 30 | #include "zone.hpp" | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 31 |  | 
| Matthew Barth | c024d78 | 2021-11-09 16:15:49 -0600 | [diff] [blame] | 32 | #include <systemd/sd-bus.h> | 
 | 33 |  | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 34 | #include <nlohmann/json.hpp> | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 35 | #include <sdbusplus/bus.hpp> | 
| Matthew Barth | 1542fb5 | 2021-06-10 14:09:09 -0500 | [diff] [blame] | 36 | #include <sdbusplus/server/manager.hpp> | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 37 | #include <sdeventplus/event.hpp> | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 38 | #include <sdeventplus/utility/timer.hpp> | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 39 |  | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 40 | #include <algorithm> | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 41 | #include <chrono> | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 42 | #include <filesystem> | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 43 | #include <functional> | 
 | 44 | #include <map> | 
 | 45 | #include <memory> | 
 | 46 | #include <tuple> | 
 | 47 | #include <utility> | 
| Matthew Barth | 0676494 | 2021-03-04 09:28:40 -0600 | [diff] [blame] | 48 | #include <vector> | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 49 |  | 
 | 50 | namespace phosphor::fan::control::json | 
 | 51 | { | 
 | 52 |  | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 53 | using json = nlohmann::json; | 
 | 54 |  | 
 | 55 | std::vector<std::string> Manager::_activeProfiles; | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 56 | std::map<std::string, | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 57 |          std::map<std::string, std::pair<bool, std::vector<std::string>>>> | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 58 |     Manager::_servTree; | 
| Matthew Barth | 07fecfc | 2021-01-29 09:04:43 -0600 | [diff] [blame] | 59 | std::map<std::string, | 
 | 60 |          std::map<std::string, std::map<std::string, PropertyVariantType>>> | 
 | 61 |     Manager::_objects; | 
| Matt Spinler | d76351b | 2021-08-05 16:23:09 -0500 | [diff] [blame] | 62 | std::unordered_map<std::string, PropertyVariantType> Manager::_parameters; | 
| Matt Spinler | d0ba86a | 2021-11-09 10:09:13 -0600 | [diff] [blame] | 63 | std::unordered_map<std::string, TriggerActions> Manager::_parameterTriggers; | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 64 |  | 
| Matt Spinler | 7787def | 2021-10-14 16:33:16 -0500 | [diff] [blame] | 65 | const std::string Manager::dumpFile = "/tmp/fan_control_dump.json"; | 
 | 66 |  | 
| Matthew Barth | 9403a21 | 2021-05-17 09:31:50 -0500 | [diff] [blame] | 67 | Manager::Manager(const sdeventplus::Event& event) : | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 68 |     _bus(util::SDBusPlus::getBus()), _event(event), | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 69 |     _mgr(util::SDBusPlus::getBus(), CONTROL_OBJPATH), _loadAllowed(true), | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 70 |     _powerState(std::make_unique<PGoodState>( | 
 | 71 |         util::SDBusPlus::getBus(), | 
 | 72 |         std::bind(std::mem_fn(&Manager::powerStateChanged), this, | 
 | 73 |                   std::placeholders::_1))) | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 74 | {} | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 75 |  | 
 | 76 | void Manager::sighupHandler(sdeventplus::source::Signal&, | 
 | 77 |                             const struct signalfd_siginfo*) | 
 | 78 | { | 
| Matthew Barth | bd52ed0 | 2022-02-07 15:15:10 -0600 | [diff] [blame] | 79 |     FlightRecorder::instance().log("main", "SIGHUP received"); | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 80 |     // Save current set of available and active profiles | 
 | 81 |     std::map<configKey, std::unique_ptr<Profile>> profiles; | 
 | 82 |     profiles.swap(_profiles); | 
 | 83 |     std::vector<std::string> activeProfiles; | 
 | 84 |     activeProfiles.swap(_activeProfiles); | 
 | 85 |  | 
 | 86 |     try | 
 | 87 |     { | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 88 |         _loadAllowed = true; | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 89 |         load(); | 
 | 90 |     } | 
| Patrick Williams | ddb773b | 2021-10-06 11:24:49 -0500 | [diff] [blame] | 91 |     catch (const std::runtime_error& re) | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 92 |     { | 
 | 93 |         // Restore saved available and active profiles | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 94 |         _loadAllowed = false; | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 95 |         _profiles.swap(profiles); | 
 | 96 |         _activeProfiles.swap(activeProfiles); | 
| Anwaar Hadi | 64b5ac2 | 2025-04-04 23:54:53 +0000 | [diff] [blame] | 97 |         lg2::error("Error reloading configs, no changes made: {LOAD_ERROR}", | 
 | 98 |                    "LOAD_ERROR", re); | 
| Matthew Barth | bd52ed0 | 2022-02-07 15:15:10 -0600 | [diff] [blame] | 99 |         FlightRecorder::instance().log( | 
| Patrick Williams | fbf4703 | 2023-07-17 12:27:34 -0500 | [diff] [blame] | 100 |             "main", std::format("Error reloading configs, no changes made: {}", | 
| Matthew Barth | bd52ed0 | 2022-02-07 15:15:10 -0600 | [diff] [blame] | 101 |                                 re.what())); | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 102 |     } | 
 | 103 | } | 
 | 104 |  | 
| Matt Spinler | 27f5f4e | 2022-09-01 14:57:39 -0500 | [diff] [blame] | 105 | void Manager::dumpDebugData(sdeventplus::source::Signal&, | 
 | 106 |                             const struct signalfd_siginfo*) | 
| Matt Spinler | 2fc0a35 | 2021-10-04 15:10:57 -0500 | [diff] [blame] | 107 | { | 
| Matt Spinler | 7787def | 2021-10-14 16:33:16 -0500 | [diff] [blame] | 108 |     json data; | 
 | 109 |     FlightRecorder::instance().dump(data); | 
| Matt Spinler | b5c21a2 | 2021-10-14 16:52:12 -0500 | [diff] [blame] | 110 |     dumpCache(data); | 
| Matt Spinler | 7787def | 2021-10-14 16:33:16 -0500 | [diff] [blame] | 111 |  | 
| Matt Spinler | 9db6dd1 | 2021-10-29 16:10:08 -0500 | [diff] [blame] | 112 |     std::for_each(_zones.begin(), _zones.end(), [&data](const auto& zone) { | 
 | 113 |         data["zones"][zone.second->getName()] = zone.second->dump(); | 
 | 114 |     }); | 
 | 115 |  | 
| Matt Spinler | 7787def | 2021-10-14 16:33:16 -0500 | [diff] [blame] | 116 |     std::ofstream file{Manager::dumpFile}; | 
 | 117 |     if (!file) | 
 | 118 |     { | 
| Anwaar Hadi | 64b5ac2 | 2025-04-04 23:54:53 +0000 | [diff] [blame] | 119 |         lg2::error("Could not open file for fan dump"); | 
| Matt Spinler | 7787def | 2021-10-14 16:33:16 -0500 | [diff] [blame] | 120 |         return; | 
 | 121 |     } | 
 | 122 |  | 
 | 123 |     file << std::setw(4) << data; | 
| Matt Spinler | 2fc0a35 | 2021-10-04 15:10:57 -0500 | [diff] [blame] | 124 | } | 
 | 125 |  | 
| Matt Spinler | b5c21a2 | 2021-10-14 16:52:12 -0500 | [diff] [blame] | 126 | void Manager::dumpCache(json& data) | 
 | 127 | { | 
 | 128 |     auto& objects = data["objects"]; | 
 | 129 |     for (const auto& [path, interfaces] : _objects) | 
 | 130 |     { | 
 | 131 |         auto& interfaceJSON = objects[path]; | 
 | 132 |  | 
 | 133 |         for (const auto& [interface, properties] : interfaces) | 
 | 134 |         { | 
 | 135 |             auto& propertyJSON = interfaceJSON[interface]; | 
 | 136 |             for (const auto& [propName, propValue] : properties) | 
 | 137 |             { | 
 | 138 |                 std::visit( | 
 | 139 |                     [&obj = propertyJSON[propName]](auto&& val) { obj = val; }, | 
 | 140 |                     propValue); | 
 | 141 |             } | 
 | 142 |         } | 
 | 143 |     } | 
 | 144 |  | 
 | 145 |     auto& parameters = data["parameters"]; | 
 | 146 |     for (const auto& [name, value] : _parameters) | 
 | 147 |     { | 
| Matt Spinler | 29088e7 | 2021-11-08 16:23:27 -0600 | [diff] [blame] | 148 |         std::visit([&obj = parameters[name]](auto&& val) { obj = val; }, value); | 
| Matt Spinler | b5c21a2 | 2021-10-14 16:52:12 -0500 | [diff] [blame] | 149 |     } | 
 | 150 |  | 
| Matt Spinler | c3eb7b3 | 2022-04-25 15:44:16 -0500 | [diff] [blame] | 151 |     std::for_each(_events.begin(), _events.end(), [&data](const auto& event) { | 
 | 152 |         data["events"][event.second->getName()] = event.second->dump(); | 
 | 153 |     }); | 
 | 154 |  | 
| Matt Spinler | b5c21a2 | 2021-10-14 16:52:12 -0500 | [diff] [blame] | 155 |     data["services"] = _servTree; | 
 | 156 | } | 
 | 157 |  | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 158 | void Manager::load() | 
 | 159 | { | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 160 |     if (_loadAllowed) | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 161 |     { | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 162 |         // Load the available profiles and which are active | 
 | 163 |         setProfiles(); | 
 | 164 |  | 
 | 165 |         // Load the zone configurations | 
 | 166 |         auto zones = getConfig<Zone>(false, _event, this); | 
 | 167 |         // Load the fan configurations and move each fan into its zone | 
 | 168 |         auto fans = getConfig<Fan>(false); | 
 | 169 |         for (auto& fan : fans) | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 170 |         { | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 171 |             configKey fanProfile = | 
 | 172 |                 std::make_pair(fan.second->getZone(), fan.first.second); | 
 | 173 |             auto itZone = std::find_if( | 
 | 174 |                 zones.begin(), zones.end(), [&fanProfile](const auto& zone) { | 
 | 175 |                     return Manager::inConfig(fanProfile, zone.first); | 
 | 176 |                 }); | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 177 |             if (itZone != zones.end()) | 
| Matthew Barth | 6f78730 | 2021-03-25 15:01:01 -0500 | [diff] [blame] | 178 |             { | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 179 |                 if (itZone->second->getTarget() != fan.second->getTarget() && | 
 | 180 |                     fan.second->getTarget() != 0) | 
 | 181 |                 { | 
 | 182 |                     // Update zone target to current target of the fan in the | 
 | 183 |                     // zone | 
 | 184 |                     itZone->second->setTarget(fan.second->getTarget()); | 
 | 185 |                 } | 
 | 186 |                 itZone->second->addFan(std::move(fan.second)); | 
| Matthew Barth | 6f78730 | 2021-03-25 15:01:01 -0500 | [diff] [blame] | 187 |             } | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 188 |         } | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 189 |  | 
| Matthew Barth | 3695ac3 | 2021-10-06 14:55:30 -0500 | [diff] [blame] | 190 |         // Save all currently available groups, if any, then clear for reloading | 
 | 191 |         auto groups = std::move(Event::getAllGroups(false)); | 
 | 192 |         Event::clearAllGroups(); | 
 | 193 |  | 
 | 194 |         std::map<configKey, std::unique_ptr<Event>> events; | 
 | 195 |         try | 
 | 196 |         { | 
 | 197 |             // Load any events configured, including all the groups | 
 | 198 |             events = getConfig<Event>(true, this, zones); | 
 | 199 |         } | 
 | 200 |         catch (const std::runtime_error& re) | 
 | 201 |         { | 
 | 202 |             // Restore saved set of all available groups for current events | 
 | 203 |             Event::setAllGroups(std::move(groups)); | 
 | 204 |             throw re; | 
 | 205 |         } | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 206 |  | 
 | 207 |         // Enable zones | 
 | 208 |         _zones = std::move(zones); | 
 | 209 |         std::for_each(_zones.begin(), _zones.end(), | 
 | 210 |                       [](const auto& entry) { entry.second->enable(); }); | 
 | 211 |  | 
 | 212 |         // Clear current timers and signal subscriptions before enabling events | 
 | 213 |         // To save reloading services and/or objects into cache, do not clear | 
 | 214 |         // cache | 
 | 215 |         _timers.clear(); | 
 | 216 |         _signals.clear(); | 
 | 217 |  | 
 | 218 |         // Enable events | 
 | 219 |         _events = std::move(events); | 
| Matt Spinler | e56672d | 2023-01-10 16:05:11 -0600 | [diff] [blame] | 220 |         FlightRecorder::instance().log("main", "Enabling events"); | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 221 |         std::for_each(_events.begin(), _events.end(), | 
 | 222 |                       [](const auto& entry) { entry.second->enable(); }); | 
| Matt Spinler | e56672d | 2023-01-10 16:05:11 -0600 | [diff] [blame] | 223 |         FlightRecorder::instance().log("main", "Done enabling events"); | 
| Matthew Barth | 3770a1d | 2021-06-10 15:09:37 -0500 | [diff] [blame] | 224 |  | 
 | 225 |         _loadAllowed = false; | 
| Matthew Barth | de90fb4 | 2021-03-04 16:34:28 -0600 | [diff] [blame] | 226 |     } | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 227 | } | 
 | 228 |  | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 229 | void Manager::powerStateChanged(bool powerStateOn) | 
 | 230 | { | 
 | 231 |     if (powerStateOn) | 
 | 232 |     { | 
| Matt Spinler | 8d9c391 | 2023-11-08 12:41:47 -0600 | [diff] [blame] | 233 |         FlightRecorder::instance().log("power", "Power on"); | 
| Matthew Barth | 6a2418a | 2021-09-01 09:10:09 -0500 | [diff] [blame] | 234 |         if (_zones.empty()) | 
 | 235 |         { | 
 | 236 |             throw std::runtime_error("No configured zones found at poweron"); | 
 | 237 |         } | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 238 |         std::for_each(_zones.begin(), _zones.end(), [](const auto& entry) { | 
 | 239 |             entry.second->setTarget(entry.second->getPoweronTarget()); | 
 | 240 |         }); | 
| Matt Spinler | d1f97f4 | 2021-10-29 16:19:24 -0500 | [diff] [blame] | 241 |  | 
 | 242 |         // Tell events to run their power on triggers | 
 | 243 |         std::for_each(_events.begin(), _events.end(), | 
 | 244 |                       [](const auto& entry) { entry.second->powerOn(); }); | 
 | 245 |     } | 
 | 246 |     else | 
 | 247 |     { | 
| Matt Spinler | 8d9c391 | 2023-11-08 12:41:47 -0600 | [diff] [blame] | 248 |         FlightRecorder::instance().log("power", "Power off"); | 
| Matt Spinler | d1f97f4 | 2021-10-29 16:19:24 -0500 | [diff] [blame] | 249 |         // Tell events to run their power off triggers | 
 | 250 |         std::for_each(_events.begin(), _events.end(), | 
 | 251 |                       [](const auto& entry) { entry.second->powerOff(); }); | 
| Matthew Barth | 48f44da | 2021-05-27 15:43:34 -0500 | [diff] [blame] | 252 |     } | 
 | 253 | } | 
 | 254 |  | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 255 | const std::vector<std::string>& Manager::getActiveProfiles() | 
 | 256 | { | 
 | 257 |     return _activeProfiles; | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 258 | } | 
 | 259 |  | 
| Matthew Barth | 0206c72 | 2021-03-30 15:20:05 -0500 | [diff] [blame] | 260 | bool Manager::inConfig(const configKey& input, const configKey& comp) | 
 | 261 | { | 
 | 262 |     // Config names dont match, do not include in config | 
 | 263 |     if (input.first != comp.first) | 
 | 264 |     { | 
 | 265 |         return false; | 
 | 266 |     } | 
 | 267 |     // No profiles specified by input config, can be used in any config | 
 | 268 |     if (input.second.empty()) | 
 | 269 |     { | 
 | 270 |         return true; | 
 | 271 |     } | 
 | 272 |     else | 
 | 273 |     { | 
 | 274 |         // Profiles must have one match in the other's profiles(and they must be | 
 | 275 |         // an active profile) to be used in the config | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 276 |         return std::any_of( | 
 | 277 |             input.second.begin(), input.second.end(), | 
 | 278 |             [&comp](const auto& lProfile) { | 
 | 279 |                 return std::any_of( | 
 | 280 |                     comp.second.begin(), comp.second.end(), | 
 | 281 |                     [&lProfile](const auto& rProfile) { | 
 | 282 |                         if (lProfile != rProfile) | 
 | 283 |                         { | 
 | 284 |                             return false; | 
 | 285 |                         } | 
 | 286 |                         auto activeProfs = getActiveProfiles(); | 
 | 287 |                         return std::find(activeProfs.begin(), activeProfs.end(), | 
 | 288 |                                          lProfile) != activeProfs.end(); | 
 | 289 |                     }); | 
| Matthew Barth | 0206c72 | 2021-03-30 15:20:05 -0500 | [diff] [blame] | 290 |             }); | 
 | 291 |     } | 
 | 292 | } | 
 | 293 |  | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 294 | bool Manager::hasOwner(const std::string& path, const std::string& intf) | 
 | 295 | { | 
 | 296 |     auto itServ = _servTree.find(path); | 
 | 297 |     if (itServ == _servTree.end()) | 
 | 298 |     { | 
 | 299 |         // Path not found in cache, therefore owner missing | 
 | 300 |         return false; | 
 | 301 |     } | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 302 |     for (const auto& service : itServ->second) | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 303 |     { | 
 | 304 |         auto itIntf = std::find_if( | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 305 |             service.second.second.begin(), service.second.second.end(), | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 306 |             [&intf](const auto& interface) { return intf == interface; }); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 307 |         if (itIntf != std::end(service.second.second)) | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 308 |         { | 
 | 309 |             // Service found, return owner state | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 310 |             return service.second.first; | 
| Matthew Barth | 12cb125 | 2021-03-08 16:47:30 -0600 | [diff] [blame] | 311 |         } | 
 | 312 |     } | 
 | 313 |     // Interface not found in cache, therefore owner missing | 
 | 314 |     return false; | 
 | 315 | } | 
 | 316 |  | 
| Matthew Barth | 6d8e2d3 | 2022-02-01 16:47:08 -0600 | [diff] [blame] | 317 | void Manager::setOwner(const std::string& serv, bool hasOwner) | 
 | 318 | { | 
 | 319 |     // Update owner state on all entries of `serv` | 
 | 320 |     for (auto& itPath : _servTree) | 
 | 321 |     { | 
 | 322 |         auto itServ = itPath.second.find(serv); | 
 | 323 |         if (itServ != itPath.second.end()) | 
 | 324 |         { | 
 | 325 |             itServ->second.first = hasOwner; | 
 | 326 |  | 
 | 327 |             // Remove associated interfaces from object cache when service no | 
 | 328 |             // longer has an owner | 
 | 329 |             if (!hasOwner && _objects.find(itPath.first) != _objects.end()) | 
 | 330 |             { | 
 | 331 |                 for (auto& intf : itServ->second.second) | 
 | 332 |                 { | 
 | 333 |                     _objects[itPath.first].erase(intf); | 
 | 334 |                 } | 
 | 335 |             } | 
 | 336 |         } | 
 | 337 |     } | 
 | 338 | } | 
 | 339 |  | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 340 | void Manager::setOwner(const std::string& path, const std::string& serv, | 
 | 341 |                        const std::string& intf, bool isOwned) | 
 | 342 | { | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 343 |     // Set owner state for specific object given | 
 | 344 |     auto& ownIntf = _servTree[path][serv]; | 
 | 345 |     ownIntf.first = isOwned; | 
| Patrick Williams | 5e15c3b | 2023-10-20 11:18:11 -0500 | [diff] [blame] | 346 |     auto itIntf = std::find_if( | 
 | 347 |         ownIntf.second.begin(), ownIntf.second.end(), | 
 | 348 |         [&intf](const auto& interface) { return intf == interface; }); | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 349 |     if (itIntf == std::end(ownIntf.second)) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 350 |     { | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 351 |         ownIntf.second.emplace_back(intf); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 352 |     } | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 353 |  | 
 | 354 |     // Update owner state on all entries of the same `serv` & `intf` | 
 | 355 |     for (auto& itPath : _servTree) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 356 |     { | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 357 |         if (itPath.first == path) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 358 |         { | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 359 |             // Already set/updated owner on this path for `serv` & `intf` | 
 | 360 |             continue; | 
 | 361 |         } | 
 | 362 |         for (auto& itServ : itPath.second) | 
 | 363 |         { | 
 | 364 |             if (itServ.first != serv) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 365 |             { | 
| Matthew Barth | 2a9e7b2 | 2021-05-17 11:54:54 -0500 | [diff] [blame] | 366 |                 continue; | 
 | 367 |             } | 
 | 368 |             auto itIntf = std::find_if( | 
 | 369 |                 itServ.second.second.begin(), itServ.second.second.end(), | 
 | 370 |                 [&intf](const auto& interface) { return intf == interface; }); | 
 | 371 |             if (itIntf != std::end(itServ.second.second)) | 
 | 372 |             { | 
 | 373 |                 itServ.second.first = isOwned; | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 374 |             } | 
 | 375 |         } | 
 | 376 |     } | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 377 | } | 
 | 378 |  | 
 | 379 | const std::string& Manager::findService(const std::string& path, | 
 | 380 |                                         const std::string& intf) | 
 | 381 | { | 
 | 382 |     static const std::string empty = ""; | 
 | 383 |  | 
 | 384 |     auto itServ = _servTree.find(path); | 
 | 385 |     if (itServ != _servTree.end()) | 
 | 386 |     { | 
 | 387 |         for (const auto& service : itServ->second) | 
 | 388 |         { | 
 | 389 |             auto itIntf = std::find_if( | 
 | 390 |                 service.second.second.begin(), service.second.second.end(), | 
 | 391 |                 [&intf](const auto& interface) { return intf == interface; }); | 
 | 392 |             if (itIntf != std::end(service.second.second)) | 
 | 393 |             { | 
 | 394 |                 // Service found, return service name | 
 | 395 |                 return service.first; | 
 | 396 |             } | 
 | 397 |         } | 
 | 398 |     } | 
 | 399 |  | 
 | 400 |     return empty; | 
 | 401 | } | 
 | 402 |  | 
| Matthew Barth | 98f6fc1 | 2021-04-16 10:48:37 -0500 | [diff] [blame] | 403 | void Manager::addServices(const std::string& intf, int32_t depth) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 404 | { | 
 | 405 |     // Get all subtree objects for the given interface | 
| Matt Spinler | 3483515 | 2021-07-01 12:28:58 -0600 | [diff] [blame] | 406 |     auto objects = util::SDBusPlus::getSubTreeRaw(util::SDBusPlus::getBus(), | 
 | 407 |                                                   "/", intf, depth); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 408 |     // Add what's returned to the cache of path->services | 
 | 409 |     for (auto& itPath : objects) | 
 | 410 |     { | 
 | 411 |         auto pathIter = _servTree.find(itPath.first); | 
 | 412 |         if (pathIter != _servTree.end()) | 
 | 413 |         { | 
 | 414 |             // Path found in cache | 
 | 415 |             for (auto& itServ : itPath.second) | 
 | 416 |             { | 
 | 417 |                 auto servIter = pathIter->second.find(itServ.first); | 
 | 418 |                 if (servIter != pathIter->second.end()) | 
 | 419 |                 { | 
| Matt Spinler | d9f85c9 | 2022-04-07 12:55:48 -0500 | [diff] [blame] | 420 |                     if (std::find(servIter->second.second.begin(), | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 421 |                                   servIter->second.second.end(), intf) == | 
 | 422 |                         servIter->second.second.end()) | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 423 |                     { | 
| Matt Spinler | d9f85c9 | 2022-04-07 12:55:48 -0500 | [diff] [blame] | 424 |                         // Add interface to cache | 
 | 425 |                         servIter->second.second.emplace_back(intf); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 426 |                     } | 
 | 427 |                 } | 
 | 428 |                 else | 
 | 429 |                 { | 
 | 430 |                     // Service not found in cache | 
 | 431 |                     auto intfs = {intf}; | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 432 |                     pathIter->second[itServ.first] = | 
 | 433 |                         std::make_pair(true, intfs); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 434 |                 } | 
 | 435 |             } | 
 | 436 |         } | 
 | 437 |         else | 
 | 438 |         { | 
 | 439 |             // Path not found in cache | 
 | 440 |             auto intfs = {intf}; | 
| Matt Spinler | a0b8a68 | 2021-10-14 15:38:48 -0500 | [diff] [blame] | 441 |             for (const auto& [servName, servIntfs] : itPath.second) | 
 | 442 |             { | 
 | 443 |                 _servTree[itPath.first][servName] = std::make_pair(true, intfs); | 
 | 444 |             } | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 445 |         } | 
 | 446 |     } | 
 | 447 | } | 
 | 448 |  | 
 | 449 | const std::string& Manager::getService(const std::string& path, | 
 | 450 |                                        const std::string& intf) | 
 | 451 | { | 
 | 452 |     // Retrieve service from cache | 
 | 453 |     const auto& serviceName = findService(path, intf); | 
 | 454 |     if (serviceName.empty()) | 
 | 455 |     { | 
| Matthew Barth | 98f6fc1 | 2021-04-16 10:48:37 -0500 | [diff] [blame] | 456 |         addServices(intf, 0); | 
| Matthew Barth | 4ca87fa | 2021-04-14 11:31:13 -0500 | [diff] [blame] | 457 |         return findService(path, intf); | 
 | 458 |     } | 
 | 459 |  | 
 | 460 |     return serviceName; | 
 | 461 | } | 
 | 462 |  | 
| Patrick Williams | 4fa67aa | 2025-02-03 14:28:47 -0500 | [diff] [blame] | 463 | std::vector<std::string> Manager::findPaths(const std::string& serv, | 
 | 464 |                                             const std::string& intf) | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 465 | { | 
 | 466 |     std::vector<std::string> paths; | 
 | 467 |  | 
 | 468 |     for (const auto& path : _servTree) | 
 | 469 |     { | 
 | 470 |         auto itServ = path.second.find(serv); | 
 | 471 |         if (itServ != path.second.end()) | 
 | 472 |         { | 
 | 473 |             if (std::find(itServ->second.second.begin(), | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 474 |                           itServ->second.second.end(), intf) != | 
 | 475 |                 itServ->second.second.end()) | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 476 |             { | 
 | 477 |                 if (std::find(paths.begin(), paths.end(), path.first) == | 
 | 478 |                     paths.end()) | 
 | 479 |                 { | 
 | 480 |                     paths.push_back(path.first); | 
 | 481 |                 } | 
 | 482 |             } | 
 | 483 |         } | 
 | 484 |     } | 
 | 485 |  | 
 | 486 |     return paths; | 
 | 487 | } | 
 | 488 |  | 
 | 489 | std::vector<std::string> Manager::getPaths(const std::string& serv, | 
 | 490 |                                            const std::string& intf) | 
 | 491 | { | 
 | 492 |     auto paths = findPaths(serv, intf); | 
 | 493 |     if (paths.empty()) | 
 | 494 |     { | 
 | 495 |         addServices(intf, 0); | 
 | 496 |         return findPaths(serv, intf); | 
 | 497 |     } | 
 | 498 |  | 
 | 499 |     return paths; | 
 | 500 | } | 
 | 501 |  | 
| Mike Capps | 1a19ead | 2021-10-22 09:15:14 -0400 | [diff] [blame] | 502 | void Manager::insertFilteredObjects(ManagedObjects& ref) | 
 | 503 | { | 
| Matt Spinler | c2c2db7 | 2022-04-07 13:59:37 -0500 | [diff] [blame] | 504 |     // Filter out objects that aren't part of a group | 
 | 505 |     const auto& allGroupMembers = Group::getAllMembers(); | 
 | 506 |     auto it = ref.begin(); | 
 | 507 |  | 
 | 508 |     while (it != ref.end()) | 
 | 509 |     { | 
 | 510 |         if (allGroupMembers.find(it->first) == allGroupMembers.end()) | 
 | 511 |         { | 
 | 512 |             it = ref.erase(it); | 
 | 513 |         } | 
 | 514 |         else | 
 | 515 |         { | 
 | 516 |             it++; | 
 | 517 |         } | 
 | 518 |     } | 
 | 519 |  | 
| Mike Capps | 1a19ead | 2021-10-22 09:15:14 -0400 | [diff] [blame] | 520 |     for (auto& [path, pathMap] : ref) | 
 | 521 |     { | 
 | 522 |         for (auto& [intf, intfMap] : pathMap) | 
 | 523 |         { | 
 | 524 |             // for each property on this path+interface | 
 | 525 |             for (auto& [prop, value] : intfMap) | 
 | 526 |             { | 
 | 527 |                 setProperty(path, intf, prop, value); | 
 | 528 |             } | 
 | 529 |         } | 
 | 530 |     } | 
 | 531 | } | 
 | 532 |  | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 533 | void Manager::addObjects(const std::string& path, const std::string& intf, | 
| Matt Spinler | 9ac325c | 2022-04-25 14:13:49 -0500 | [diff] [blame] | 534 |                          const std::string& prop, | 
 | 535 |                          const std::string& serviceName) | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 536 | { | 
| Matt Spinler | 9ac325c | 2022-04-25 14:13:49 -0500 | [diff] [blame] | 537 |     auto service = serviceName; | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 538 |     if (service.empty()) | 
 | 539 |     { | 
| Matt Spinler | 9ac325c | 2022-04-25 14:13:49 -0500 | [diff] [blame] | 540 |         service = getService(path, intf); | 
 | 541 |         if (service.empty()) | 
 | 542 |         { | 
 | 543 |             // Log service not found for object | 
| Anwaar Hadi | 64b5ac2 | 2025-04-04 23:54:53 +0000 | [diff] [blame] | 544 |             lg2::debug( | 
 | 545 |                 "Unable to get service name for path {PATH}, interface {INTERFACE}", | 
 | 546 |                 "PATH", path, "INTERFACE", intf); | 
| Matt Spinler | 9ac325c | 2022-04-25 14:13:49 -0500 | [diff] [blame] | 547 |             return; | 
 | 548 |         } | 
 | 549 |     } | 
 | 550 |     else | 
 | 551 |     { | 
 | 552 |         // The service is known, so the service cache can be | 
 | 553 |         // populated even if the path itself isn't present. | 
 | 554 |         const auto& s = findService(path, intf); | 
 | 555 |         if (s.empty()) | 
 | 556 |         { | 
 | 557 |             addServices(intf, 0); | 
 | 558 |         } | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 559 |     } | 
 | 560 |  | 
 | 561 |     auto objMgrPaths = getPaths(service, "org.freedesktop.DBus.ObjectManager"); | 
| Chau Ly | 078c0a8 | 2024-06-11 09:45:28 +0000 | [diff] [blame] | 562 |  | 
 | 563 |     bool useManagedObj = false; | 
 | 564 |  | 
 | 565 |     if (!objMgrPaths.empty()) | 
 | 566 |     { | 
 | 567 |         for (const auto& objMgrPath : objMgrPaths) | 
 | 568 |         { | 
 | 569 |             // Get all managed objects of service | 
 | 570 |             auto objects = | 
 | 571 |                 util::SDBusPlus::getManagedObjects<PropertyVariantType>( | 
 | 572 |                     _bus, service, objMgrPath); | 
 | 573 |             if (objects.size() > 0) | 
 | 574 |             { | 
 | 575 |                 useManagedObj = true; | 
 | 576 |             } | 
 | 577 |             // insert all objects that are in groups but remove any NaN values | 
 | 578 |             insertFilteredObjects(objects); | 
 | 579 |         } | 
 | 580 |     } | 
 | 581 |  | 
 | 582 |     if (!useManagedObj) | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 583 |     { | 
 | 584 |         // No object manager interface provided by service? | 
| Chau Ly | 078c0a8 | 2024-06-11 09:45:28 +0000 | [diff] [blame] | 585 |         // Or no object is managed? | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 586 |         // Attempt to retrieve property directly | 
| Matt Spinler | f16f063 | 2022-05-09 14:27:46 -0500 | [diff] [blame] | 587 |         try | 
 | 588 |         { | 
 | 589 |             auto value = | 
 | 590 |                 util::SDBusPlus::getPropertyVariant<PropertyVariantType>( | 
 | 591 |                     _bus, service, path, intf, prop); | 
| Mike Capps | 1a19ead | 2021-10-22 09:15:14 -0400 | [diff] [blame] | 592 |  | 
| Matt Spinler | f16f063 | 2022-05-09 14:27:46 -0500 | [diff] [blame] | 593 |             setProperty(path, intf, prop, value); | 
 | 594 |         } | 
 | 595 |         catch (const std::exception& e) | 
 | 596 |         {} | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 597 |         return; | 
 | 598 |     } | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 599 | } | 
 | 600 |  | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 601 | const std::optional<PropertyVariantType> Manager::getProperty( | 
 | 602 |     const std::string& path, const std::string& intf, const std::string& prop) | 
| Matthew Barth | f41e947 | 2021-05-13 16:38:06 -0500 | [diff] [blame] | 603 | { | 
 | 604 |     // TODO Objects hosted by fan control (i.e. ThermalMode) are required to | 
 | 605 |     // update the cache upon being set/updated | 
 | 606 |     auto itPath = _objects.find(path); | 
 | 607 |     if (itPath != _objects.end()) | 
 | 608 |     { | 
 | 609 |         auto itIntf = itPath->second.find(intf); | 
 | 610 |         if (itIntf != itPath->second.end()) | 
 | 611 |         { | 
 | 612 |             auto itProp = itIntf->second.find(prop); | 
 | 613 |             if (itProp != itIntf->second.end()) | 
 | 614 |             { | 
 | 615 |                 return itProp->second; | 
 | 616 |             } | 
 | 617 |         } | 
 | 618 |     } | 
 | 619 |  | 
 | 620 |     return std::nullopt; | 
 | 621 | } | 
 | 622 |  | 
| Mike Capps | 1a19ead | 2021-10-22 09:15:14 -0400 | [diff] [blame] | 623 | void Manager::setProperty(const std::string& path, const std::string& intf, | 
 | 624 |                           const std::string& prop, PropertyVariantType value) | 
 | 625 | { | 
 | 626 |     // filter NaNs out of the cache | 
 | 627 |     if (PropertyContainsNan(value)) | 
 | 628 |     { | 
 | 629 |         // dont use operator [] if paths dont exist | 
 | 630 |         if (_objects.find(path) != _objects.end() && | 
 | 631 |             _objects[path].find(intf) != _objects[path].end()) | 
 | 632 |         { | 
 | 633 |             _objects[path][intf].erase(prop); | 
 | 634 |         } | 
 | 635 |     } | 
 | 636 |     else | 
 | 637 |     { | 
 | 638 |         _objects[path][intf][prop] = std::move(value); | 
 | 639 |     } | 
 | 640 | } | 
 | 641 |  | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 642 | void Manager::addTimer(const TimerType type, | 
 | 643 |                        const std::chrono::microseconds interval, | 
 | 644 |                        std::unique_ptr<TimerPkg> pkg) | 
 | 645 | { | 
 | 646 |     auto dataPtr = | 
 | 647 |         std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg))); | 
 | 648 |     Timer timer(_event, | 
 | 649 |                 std::bind(&Manager::timerExpired, this, std::ref(*dataPtr))); | 
 | 650 |     if (type == TimerType::repeating) | 
 | 651 |     { | 
 | 652 |         timer.restart(interval); | 
 | 653 |     } | 
 | 654 |     else if (type == TimerType::oneshot) | 
 | 655 |     { | 
 | 656 |         timer.restartOnce(interval); | 
 | 657 |     } | 
 | 658 |     else | 
 | 659 |     { | 
 | 660 |         throw std::invalid_argument("Invalid Timer Type"); | 
 | 661 |     } | 
 | 662 |     _timers.emplace_back(std::move(dataPtr), std::move(timer)); | 
 | 663 | } | 
 | 664 |  | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 665 | void Manager::addGroups(const std::vector<Group>& groups) | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 666 | { | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 667 |     std::string lastServ; | 
 | 668 |     std::vector<std::string> objMgrPaths; | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 669 |     std::set<std::string> services; | 
 | 670 |     for (const auto& group : groups) | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 671 |     { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 672 |         for (const auto& member : group.getMembers()) | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 673 |         { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 674 |             try | 
| Matthew Barth | 95d7349 | 2022-02-09 11:30:35 -0600 | [diff] [blame] | 675 |             { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 676 |                 auto service = group.getService(); | 
 | 677 |                 if (service.empty()) | 
| Matthew Barth | 55627ad | 2021-12-02 22:28:29 -0600 | [diff] [blame] | 678 |                 { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 679 |                     service = getService(member, group.getInterface()); | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 680 |                 } | 
| Matthew Barth | 55627ad | 2021-12-02 22:28:29 -0600 | [diff] [blame] | 681 |  | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 682 |                 if (!service.empty()) | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 683 |                 { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 684 |                     if (lastServ != service) | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 685 |                     { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 686 |                         objMgrPaths = getPaths( | 
 | 687 |                             service, "org.freedesktop.DBus.ObjectManager"); | 
 | 688 |                         lastServ = service; | 
 | 689 |                     } | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 690 |  | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 691 |                     // Look for the ObjectManager as an ancestor from the | 
 | 692 |                     // member. | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 693 |                     auto hasObjMgr = std::any_of( | 
 | 694 |                         objMgrPaths.begin(), objMgrPaths.end(), | 
 | 695 |                         [&member](const auto& path) { | 
 | 696 |                             return member.find(path) != std::string::npos; | 
 | 697 |                         }); | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 698 |  | 
 | 699 |                     if (!hasObjMgr) | 
 | 700 |                     { | 
 | 701 |                         // No object manager interface provided for group member | 
 | 702 |                         // Attempt to retrieve group member property directly | 
| Matt Spinler | f16f063 | 2022-05-09 14:27:46 -0500 | [diff] [blame] | 703 |                         try | 
 | 704 |                         { | 
 | 705 |                             auto value = util::SDBusPlus::getPropertyVariant< | 
 | 706 |                                 PropertyVariantType>(_bus, service, member, | 
 | 707 |                                                      group.getInterface(), | 
 | 708 |                                                      group.getProperty()); | 
 | 709 |                             setProperty(member, group.getInterface(), | 
 | 710 |                                         group.getProperty(), value); | 
 | 711 |                         } | 
 | 712 |                         catch (const std::exception& e) | 
 | 713 |                         {} | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 714 |                         continue; | 
 | 715 |                     } | 
 | 716 |  | 
 | 717 |                     if (services.find(service) == services.end()) | 
 | 718 |                     { | 
 | 719 |                         services.insert(service); | 
 | 720 |                         for (const auto& objMgrPath : objMgrPaths) | 
 | 721 |                         { | 
 | 722 |                             // Get all managed objects from the service | 
 | 723 |                             auto objects = util::SDBusPlus::getManagedObjects< | 
 | 724 |                                 PropertyVariantType>(_bus, service, objMgrPath); | 
 | 725 |  | 
 | 726 |                             // Insert objects into cache | 
 | 727 |                             insertFilteredObjects(objects); | 
 | 728 |                         } | 
| Matthew Barth | 1a5c623 | 2022-02-14 14:28:41 -0600 | [diff] [blame] | 729 |                     } | 
| Matthew Barth | 55627ad | 2021-12-02 22:28:29 -0600 | [diff] [blame] | 730 |                 } | 
 | 731 |             } | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 732 |             catch (const util::DBusError&) | 
 | 733 |             { | 
 | 734 |                 // No service or property found for group member with the | 
 | 735 |                 // group's configured interface | 
 | 736 |                 continue; | 
 | 737 |             } | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 738 |         } | 
 | 739 |     } | 
 | 740 | } | 
 | 741 |  | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 742 | void Manager::timerExpired(TimerData& data) | 
 | 743 | { | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 744 |     if (std::get<bool>(data.second)) | 
 | 745 |     { | 
| Matthew Barth | 2f359f7 | 2022-02-15 10:00:26 -0600 | [diff] [blame] | 746 |         addGroups(std::get<const std::vector<Group>&>(data.second)); | 
| Matt Spinler | ade0c37 | 2021-10-28 16:09:44 -0500 | [diff] [blame] | 747 |     } | 
 | 748 |  | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 749 |     auto& actions = | 
 | 750 |         std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second); | 
 | 751 |     // Perform the actions in the timer data | 
 | 752 |     std::for_each(actions.begin(), actions.end(), | 
| Matthew Barth | 00f6aa0 | 2021-04-09 10:49:47 -0500 | [diff] [blame] | 753 |                   [](auto& action) { action->run(); }); | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 754 |  | 
 | 755 |     // Remove oneshot timers after they expired | 
 | 756 |     if (data.first == TimerType::oneshot) | 
 | 757 |     { | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 758 |         auto itTimer = std::find_if( | 
 | 759 |             _timers.begin(), _timers.end(), [&data](const auto& timer) { | 
 | 760 |                 return (data.first == timer.first->first && | 
 | 761 |                         (std::get<std::string>(data.second) == | 
 | 762 |                          std::get<std::string>(timer.first->second))); | 
 | 763 |             }); | 
| Matthew Barth | d9cb63b | 2021-03-24 14:36:49 -0500 | [diff] [blame] | 764 |         if (itTimer != std::end(_timers)) | 
 | 765 |         { | 
 | 766 |             _timers.erase(itTimer); | 
 | 767 |         } | 
 | 768 |     } | 
 | 769 | } | 
 | 770 |  | 
| Patrick Williams | cb356d4 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 771 | void Manager::handleSignal(sdbusplus::message_t& msg, | 
| Matthew Barth | c024d78 | 2021-11-09 16:15:49 -0600 | [diff] [blame] | 772 |                            const std::vector<SignalPkg>* pkgs) | 
| Matthew Barth | ebabc04 | 2021-05-13 15:38:58 -0500 | [diff] [blame] | 773 | { | 
| Matthew Barth | c024d78 | 2021-11-09 16:15:49 -0600 | [diff] [blame] | 774 |     for (auto& pkg : *pkgs) | 
| Matthew Barth | ebabc04 | 2021-05-13 15:38:58 -0500 | [diff] [blame] | 775 |     { | 
 | 776 |         // Handle the signal callback and only run the actions if the handler | 
 | 777 |         // updated the cache for the given SignalObject | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 778 |         if (std::get<SignalHandler>( | 
 | 779 |                 pkg)(msg, std::get<SignalObject>(pkg), *this)) | 
| Matthew Barth | ebabc04 | 2021-05-13 15:38:58 -0500 | [diff] [blame] | 780 |         { | 
 | 781 |             // Perform the actions in the handler package | 
| Matt Spinler | d0ba86a | 2021-11-09 10:09:13 -0600 | [diff] [blame] | 782 |             auto& actions = std::get<TriggerActions>(pkg); | 
| Matthew Barth | c3a6908 | 2021-11-15 14:32:48 -0600 | [diff] [blame] | 783 |             std::for_each(actions.begin(), actions.end(), [](auto& action) { | 
 | 784 |                 if (action.get()) | 
 | 785 |                 { | 
 | 786 |                     action.get()->run(); | 
 | 787 |                 } | 
 | 788 |             }); | 
| Matthew Barth | ebabc04 | 2021-05-13 15:38:58 -0500 | [diff] [blame] | 789 |         } | 
| Matthew Barth | c024d78 | 2021-11-09 16:15:49 -0600 | [diff] [blame] | 790 |         // Only rewind message when not last package | 
 | 791 |         if (&pkg != &pkgs->back()) | 
 | 792 |         { | 
 | 793 |             sd_bus_message_rewind(msg.get(), true); | 
 | 794 |         } | 
| Matthew Barth | ebabc04 | 2021-05-13 15:38:58 -0500 | [diff] [blame] | 795 |     } | 
 | 796 | } | 
 | 797 |  | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 798 | void Manager::setProfiles() | 
 | 799 | { | 
 | 800 |     // Profiles JSON config file is optional | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 801 |     auto confFile = | 
 | 802 |         fan::JsonConfig::getConfFile(confAppName, Profile::confFileName, true); | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 803 |  | 
 | 804 |     _profiles.clear(); | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 805 |     if (!confFile.empty()) | 
 | 806 |     { | 
 | 807 |         for (const auto& entry : fan::JsonConfig::load(confFile)) | 
 | 808 |         { | 
 | 809 |             auto obj = std::make_unique<Profile>(entry); | 
 | 810 |             _profiles.emplace( | 
 | 811 |                 std::make_pair(obj->getName(), obj->getProfiles()), | 
 | 812 |                 std::move(obj)); | 
 | 813 |         } | 
 | 814 |     } | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 815 |  | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 816 |     // Ensure all configurations use the same set of active profiles | 
 | 817 |     // (In case a profile's active state changes during configuration) | 
| Matthew Barth | e91ac86 | 2021-05-25 16:22:17 -0500 | [diff] [blame] | 818 |     _activeProfiles.clear(); | 
| Matthew Barth | acd737c | 2021-03-04 11:04:01 -0600 | [diff] [blame] | 819 |     for (const auto& profile : _profiles) | 
 | 820 |     { | 
 | 821 |         if (profile.second->isActive()) | 
 | 822 |         { | 
 | 823 |             _activeProfiles.emplace_back(profile.first.first); | 
 | 824 |         } | 
 | 825 |     } | 
 | 826 | } | 
 | 827 |  | 
| Matt Spinler | d0ba86a | 2021-11-09 10:09:13 -0600 | [diff] [blame] | 828 | void Manager::addParameterTrigger( | 
 | 829 |     const std::string& name, std::vector<std::unique_ptr<ActionBase>>& actions) | 
 | 830 | { | 
 | 831 |     auto it = _parameterTriggers.find(name); | 
 | 832 |     if (it != _parameterTriggers.end()) | 
 | 833 |     { | 
 | 834 |         std::for_each(actions.begin(), actions.end(), | 
 | 835 |                       [&actList = it->second](auto& action) { | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 836 |                           actList.emplace_back(std::ref(action)); | 
 | 837 |                       }); | 
| Matt Spinler | d0ba86a | 2021-11-09 10:09:13 -0600 | [diff] [blame] | 838 |     } | 
 | 839 |     else | 
 | 840 |     { | 
 | 841 |         TriggerActions triggerActions; | 
 | 842 |         std::for_each(actions.begin(), actions.end(), | 
 | 843 |                       [&triggerActions](auto& action) { | 
| Patrick Williams | dfddd64 | 2024-08-16 15:21:51 -0400 | [diff] [blame] | 844 |                           triggerActions.emplace_back(std::ref(action)); | 
 | 845 |                       }); | 
| Matt Spinler | d0ba86a | 2021-11-09 10:09:13 -0600 | [diff] [blame] | 846 |         _parameterTriggers[name] = std::move(triggerActions); | 
 | 847 |     } | 
 | 848 | } | 
 | 849 |  | 
 | 850 | void Manager::runParameterActions(const std::string& name) | 
 | 851 | { | 
 | 852 |     auto it = _parameterTriggers.find(name); | 
 | 853 |     if (it != _parameterTriggers.end()) | 
 | 854 |     { | 
 | 855 |         std::for_each(it->second.begin(), it->second.end(), | 
 | 856 |                       [](auto& action) { action.get()->run(); }); | 
 | 857 |     } | 
 | 858 | } | 
 | 859 |  | 
| Matthew Barth | a227a16 | 2020-08-05 10:51:45 -0500 | [diff] [blame] | 860 | } // namespace phosphor::fan::control::json |