1a227a16dSMatthew Barth /** 2a227a16dSMatthew Barth * Copyright © 2020 IBM Corporation 3a227a16dSMatthew Barth * 4a227a16dSMatthew Barth * Licensed under the Apache License, Version 2.0 (the "License"); 5a227a16dSMatthew Barth * you may not use this file except in compliance with the License. 6a227a16dSMatthew Barth * You may obtain a copy of the License at 7a227a16dSMatthew Barth * 8a227a16dSMatthew Barth * http://www.apache.org/licenses/LICENSE-2.0 9a227a16dSMatthew Barth * 10a227a16dSMatthew Barth * Unless required by applicable law or agreed to in writing, software 11a227a16dSMatthew Barth * distributed under the License is distributed on an "AS IS" BASIS, 12a227a16dSMatthew Barth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a227a16dSMatthew Barth * See the License for the specific language governing permissions and 14a227a16dSMatthew Barth * limitations under the License. 15a227a16dSMatthew Barth */ 16b584d818SMatthew Barth #include "config.h" 17b584d818SMatthew Barth 18a227a16dSMatthew Barth #include "manager.hpp" 19a227a16dSMatthew Barth 20d9cb63b6SMatthew Barth #include "action.hpp" 2144ab7693SMatthew Barth #include "event.hpp" 22de90fb4dSMatthew Barth #include "fan.hpp" 23d9cb63b6SMatthew Barth #include "group.hpp" 24a227a16dSMatthew Barth #include "json_config.hpp" 2548f44daaSMatthew Barth #include "power_state.hpp" 2606764946SMatthew Barth #include "profile.hpp" 279403a217SMatthew Barth #include "sdbusplus.hpp" 28acd737cdSMatthew Barth #include "zone.hpp" 29a227a16dSMatthew Barth 30acd737cdSMatthew Barth #include <nlohmann/json.hpp> 31a227a16dSMatthew Barth #include <sdbusplus/bus.hpp> 321542fb5aSMatthew Barth #include <sdbusplus/server/manager.hpp> 33acd737cdSMatthew Barth #include <sdeventplus/event.hpp> 34d9cb63b6SMatthew Barth #include <sdeventplus/utility/timer.hpp> 35a227a16dSMatthew Barth 36de90fb4dSMatthew Barth #include <algorithm> 37d9cb63b6SMatthew Barth #include <chrono> 38a227a16dSMatthew Barth #include <filesystem> 39d9cb63b6SMatthew Barth #include <functional> 40d9cb63b6SMatthew Barth #include <map> 41d9cb63b6SMatthew Barth #include <memory> 42d9cb63b6SMatthew Barth #include <tuple> 43d9cb63b6SMatthew Barth #include <utility> 4406764946SMatthew Barth #include <vector> 45a227a16dSMatthew Barth 46a227a16dSMatthew Barth namespace phosphor::fan::control::json 47a227a16dSMatthew Barth { 48a227a16dSMatthew Barth 49acd737cdSMatthew Barth using json = nlohmann::json; 50acd737cdSMatthew Barth 51acd737cdSMatthew Barth std::vector<std::string> Manager::_activeProfiles; 5212cb125aSMatthew Barth std::map<std::string, 534ca87faeSMatthew Barth std::map<std::string, std::pair<bool, std::vector<std::string>>>> 5412cb125aSMatthew Barth Manager::_servTree; 5507fecfc6SMatthew Barth std::map<std::string, 5607fecfc6SMatthew Barth std::map<std::string, std::map<std::string, PropertyVariantType>>> 5707fecfc6SMatthew Barth Manager::_objects; 58*d76351bdSMatt Spinler std::unordered_map<std::string, PropertyVariantType> Manager::_parameters; 59acd737cdSMatthew Barth 609403a217SMatthew Barth Manager::Manager(const sdeventplus::Event& event) : 6148f44daaSMatthew Barth _bus(util::SDBusPlus::getBus()), _event(event), 623770a1daSMatthew Barth _mgr(util::SDBusPlus::getBus(), CONTROL_OBJPATH), _loadAllowed(true), 6348f44daaSMatthew Barth _powerState(std::make_unique<PGoodState>( 6448f44daaSMatthew Barth util::SDBusPlus::getBus(), 6548f44daaSMatthew Barth std::bind(std::mem_fn(&Manager::powerStateChanged), this, 6648f44daaSMatthew Barth std::placeholders::_1))) 673770a1daSMatthew Barth {} 68e91ac864SMatthew Barth 69e91ac864SMatthew Barth void Manager::sighupHandler(sdeventplus::source::Signal&, 70e91ac864SMatthew Barth const struct signalfd_siginfo*) 71e91ac864SMatthew Barth { 72e91ac864SMatthew Barth // Save current set of available and active profiles 73e91ac864SMatthew Barth std::map<configKey, std::unique_ptr<Profile>> profiles; 74e91ac864SMatthew Barth profiles.swap(_profiles); 75e91ac864SMatthew Barth std::vector<std::string> activeProfiles; 76e91ac864SMatthew Barth activeProfiles.swap(_activeProfiles); 77e91ac864SMatthew Barth 78e91ac864SMatthew Barth try 79e91ac864SMatthew Barth { 803770a1daSMatthew Barth _loadAllowed = true; 81e91ac864SMatthew Barth load(); 82e91ac864SMatthew Barth } 83e91ac864SMatthew Barth catch (std::runtime_error& re) 84e91ac864SMatthew Barth { 85e91ac864SMatthew Barth // Restore saved available and active profiles 863770a1daSMatthew Barth _loadAllowed = false; 87e91ac864SMatthew Barth _profiles.swap(profiles); 88e91ac864SMatthew Barth _activeProfiles.swap(activeProfiles); 89e91ac864SMatthew Barth log<level::ERR>("Error reloading configs, no changes made", 90e91ac864SMatthew Barth entry("LOAD_ERROR=%s", re.what())); 91e91ac864SMatthew Barth } 92e91ac864SMatthew Barth } 93e91ac864SMatthew Barth 94e91ac864SMatthew Barth void Manager::load() 95e91ac864SMatthew Barth { 963770a1daSMatthew Barth if (_loadAllowed) 973770a1daSMatthew Barth { 98e91ac864SMatthew Barth // Load the available profiles and which are active 99acd737cdSMatthew Barth setProfiles(); 100acd737cdSMatthew Barth 101acd737cdSMatthew Barth // Load the zone configurations 102e91ac864SMatthew Barth auto zones = getConfig<Zone>(false, _event, this); 103de90fb4dSMatthew Barth // Load the fan configurations and move each fan into its zone 1049403a217SMatthew Barth auto fans = getConfig<Fan>(false); 105de90fb4dSMatthew Barth for (auto& fan : fans) 106de90fb4dSMatthew Barth { 1070206c728SMatthew Barth configKey fanProfile = 1080206c728SMatthew Barth std::make_pair(fan.second->getZone(), fan.first.second); 1090206c728SMatthew Barth auto itZone = std::find_if( 110e91ac864SMatthew Barth zones.begin(), zones.end(), [&fanProfile](const auto& zone) { 1110206c728SMatthew Barth return Manager::inConfig(fanProfile, zone.first); 112de90fb4dSMatthew Barth }); 113e91ac864SMatthew Barth if (itZone != zones.end()) 114de90fb4dSMatthew Barth { 1156f787309SMatthew Barth if (itZone->second->getTarget() != fan.second->getTarget() && 1166f787309SMatthew Barth fan.second->getTarget() != 0) 1176f787309SMatthew Barth { 118e91ac864SMatthew Barth // Update zone target to current target of the fan in the 119e91ac864SMatthew Barth // zone 1206f787309SMatthew Barth itZone->second->setTarget(fan.second->getTarget()); 1216f787309SMatthew Barth } 122de90fb4dSMatthew Barth itZone->second->addFan(std::move(fan.second)); 123de90fb4dSMatthew Barth } 124de90fb4dSMatthew Barth } 125e91ac864SMatthew Barth 126e91ac864SMatthew Barth // Load any events configured 127e91ac864SMatthew Barth auto events = getConfig<Event>(true, this, zones); 128e91ac864SMatthew Barth 12914303a45SMatthew Barth // Enable zones 130e91ac864SMatthew Barth _zones = std::move(zones); 13114303a45SMatthew Barth std::for_each(_zones.begin(), _zones.end(), 13214303a45SMatthew Barth [](const auto& entry) { entry.second->enable(); }); 133b584d818SMatthew Barth 134e91ac864SMatthew Barth // Clear current timers and signal subscriptions before enabling events 1353770a1daSMatthew Barth // To save reloading services and/or objects into cache, do not clear 1363770a1daSMatthew Barth // cache 137e91ac864SMatthew Barth _timers.clear(); 138e91ac864SMatthew Barth _signals.clear(); 139e91ac864SMatthew Barth 140e91ac864SMatthew Barth // Enable events 141e91ac864SMatthew Barth _events = std::move(events); 14254b5a24fSMatthew Barth std::for_each(_events.begin(), _events.end(), 14354b5a24fSMatthew Barth [](const auto& entry) { entry.second->enable(); }); 1443770a1daSMatthew Barth 1453770a1daSMatthew Barth _loadAllowed = false; 1463770a1daSMatthew Barth } 14706764946SMatthew Barth } 148acd737cdSMatthew Barth 14948f44daaSMatthew Barth void Manager::powerStateChanged(bool powerStateOn) 15048f44daaSMatthew Barth { 15148f44daaSMatthew Barth if (powerStateOn) 15248f44daaSMatthew Barth { 15348f44daaSMatthew Barth std::for_each(_zones.begin(), _zones.end(), [](const auto& entry) { 15448f44daaSMatthew Barth entry.second->setTarget(entry.second->getPoweronTarget()); 15548f44daaSMatthew Barth }); 15648f44daaSMatthew Barth } 15748f44daaSMatthew Barth } 15848f44daaSMatthew Barth 159acd737cdSMatthew Barth const std::vector<std::string>& Manager::getActiveProfiles() 160acd737cdSMatthew Barth { 161acd737cdSMatthew Barth return _activeProfiles; 162a227a16dSMatthew Barth } 163a227a16dSMatthew Barth 1640206c728SMatthew Barth bool Manager::inConfig(const configKey& input, const configKey& comp) 1650206c728SMatthew Barth { 1660206c728SMatthew Barth // Config names dont match, do not include in config 1670206c728SMatthew Barth if (input.first != comp.first) 1680206c728SMatthew Barth { 1690206c728SMatthew Barth return false; 1700206c728SMatthew Barth } 1710206c728SMatthew Barth // No profiles specified by input config, can be used in any config 1720206c728SMatthew Barth if (input.second.empty()) 1730206c728SMatthew Barth { 1740206c728SMatthew Barth return true; 1750206c728SMatthew Barth } 1760206c728SMatthew Barth else 1770206c728SMatthew Barth { 1780206c728SMatthew Barth // Profiles must have one match in the other's profiles(and they must be 1790206c728SMatthew Barth // an active profile) to be used in the config 1800206c728SMatthew Barth return std::any_of( 1810206c728SMatthew Barth input.second.begin(), input.second.end(), 1820206c728SMatthew Barth [&comp](const auto& lProfile) { 1830206c728SMatthew Barth return std::any_of( 1840206c728SMatthew Barth comp.second.begin(), comp.second.end(), 1850206c728SMatthew Barth [&lProfile](const auto& rProfile) { 1860206c728SMatthew Barth if (lProfile != rProfile) 1870206c728SMatthew Barth { 1880206c728SMatthew Barth return false; 1890206c728SMatthew Barth } 1900206c728SMatthew Barth auto activeProfs = getActiveProfiles(); 1910206c728SMatthew Barth return std::find(activeProfs.begin(), activeProfs.end(), 1920206c728SMatthew Barth lProfile) != activeProfs.end(); 1930206c728SMatthew Barth }); 1940206c728SMatthew Barth }); 1950206c728SMatthew Barth } 1960206c728SMatthew Barth } 1970206c728SMatthew Barth 19812cb125aSMatthew Barth bool Manager::hasOwner(const std::string& path, const std::string& intf) 19912cb125aSMatthew Barth { 20012cb125aSMatthew Barth auto itServ = _servTree.find(path); 20112cb125aSMatthew Barth if (itServ == _servTree.end()) 20212cb125aSMatthew Barth { 20312cb125aSMatthew Barth // Path not found in cache, therefore owner missing 20412cb125aSMatthew Barth return false; 20512cb125aSMatthew Barth } 2064ca87faeSMatthew Barth for (const auto& service : itServ->second) 20712cb125aSMatthew Barth { 20812cb125aSMatthew Barth auto itIntf = std::find_if( 2094ca87faeSMatthew Barth service.second.second.begin(), service.second.second.end(), 21012cb125aSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 2114ca87faeSMatthew Barth if (itIntf != std::end(service.second.second)) 21212cb125aSMatthew Barth { 21312cb125aSMatthew Barth // Service found, return owner state 2144ca87faeSMatthew Barth return service.second.first; 21512cb125aSMatthew Barth } 21612cb125aSMatthew Barth } 21712cb125aSMatthew Barth // Interface not found in cache, therefore owner missing 21812cb125aSMatthew Barth return false; 21912cb125aSMatthew Barth } 22012cb125aSMatthew Barth 2214ca87faeSMatthew Barth void Manager::setOwner(const std::string& path, const std::string& serv, 2224ca87faeSMatthew Barth const std::string& intf, bool isOwned) 2234ca87faeSMatthew Barth { 2242a9e7b2eSMatthew Barth // Set owner state for specific object given 2252a9e7b2eSMatthew Barth auto& ownIntf = _servTree[path][serv]; 2262a9e7b2eSMatthew Barth ownIntf.first = isOwned; 2274ca87faeSMatthew Barth auto itIntf = std::find_if( 2282a9e7b2eSMatthew Barth ownIntf.second.begin(), ownIntf.second.end(), 2294ca87faeSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 2302a9e7b2eSMatthew Barth if (itIntf == std::end(ownIntf.second)) 2314ca87faeSMatthew Barth { 2322a9e7b2eSMatthew Barth ownIntf.second.emplace_back(intf); 2332a9e7b2eSMatthew Barth } 2342a9e7b2eSMatthew Barth 2352a9e7b2eSMatthew Barth // Update owner state on all entries of the same `serv` & `intf` 2362a9e7b2eSMatthew Barth for (auto& itPath : _servTree) 2374ca87faeSMatthew Barth { 2382a9e7b2eSMatthew Barth if (itPath.first == path) 2392a9e7b2eSMatthew Barth { 2402a9e7b2eSMatthew Barth // Already set/updated owner on this path for `serv` & `intf` 2412a9e7b2eSMatthew Barth continue; 2422a9e7b2eSMatthew Barth } 2432a9e7b2eSMatthew Barth for (auto& itServ : itPath.second) 2442a9e7b2eSMatthew Barth { 2452a9e7b2eSMatthew Barth if (itServ.first != serv) 2462a9e7b2eSMatthew Barth { 2472a9e7b2eSMatthew Barth continue; 2482a9e7b2eSMatthew Barth } 2492a9e7b2eSMatthew Barth auto itIntf = std::find_if( 2502a9e7b2eSMatthew Barth itServ.second.second.begin(), itServ.second.second.end(), 2512a9e7b2eSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 2522a9e7b2eSMatthew Barth if (itIntf != std::end(itServ.second.second)) 2532a9e7b2eSMatthew Barth { 2542a9e7b2eSMatthew Barth itServ.second.first = isOwned; 2554ca87faeSMatthew Barth } 2564ca87faeSMatthew Barth } 2574ca87faeSMatthew Barth } 2584ca87faeSMatthew Barth } 2594ca87faeSMatthew Barth 2604ca87faeSMatthew Barth const std::string& Manager::findService(const std::string& path, 2614ca87faeSMatthew Barth const std::string& intf) 2624ca87faeSMatthew Barth { 2634ca87faeSMatthew Barth static const std::string empty = ""; 2644ca87faeSMatthew Barth 2654ca87faeSMatthew Barth auto itServ = _servTree.find(path); 2664ca87faeSMatthew Barth if (itServ != _servTree.end()) 2674ca87faeSMatthew Barth { 2684ca87faeSMatthew Barth for (const auto& service : itServ->second) 2694ca87faeSMatthew Barth { 2704ca87faeSMatthew Barth auto itIntf = std::find_if( 2714ca87faeSMatthew Barth service.second.second.begin(), service.second.second.end(), 2724ca87faeSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 2734ca87faeSMatthew Barth if (itIntf != std::end(service.second.second)) 2744ca87faeSMatthew Barth { 2754ca87faeSMatthew Barth // Service found, return service name 2764ca87faeSMatthew Barth return service.first; 2774ca87faeSMatthew Barth } 2784ca87faeSMatthew Barth } 2794ca87faeSMatthew Barth } 2804ca87faeSMatthew Barth 2814ca87faeSMatthew Barth return empty; 2824ca87faeSMatthew Barth } 2834ca87faeSMatthew Barth 28498f6fc17SMatthew Barth void Manager::addServices(const std::string& intf, int32_t depth) 2854ca87faeSMatthew Barth { 2864ca87faeSMatthew Barth // Get all subtree objects for the given interface 28734835150SMatt Spinler auto objects = util::SDBusPlus::getSubTreeRaw(util::SDBusPlus::getBus(), 28834835150SMatt Spinler "/", intf, depth); 2894ca87faeSMatthew Barth // Add what's returned to the cache of path->services 2904ca87faeSMatthew Barth for (auto& itPath : objects) 2914ca87faeSMatthew Barth { 2924ca87faeSMatthew Barth auto pathIter = _servTree.find(itPath.first); 2934ca87faeSMatthew Barth if (pathIter != _servTree.end()) 2944ca87faeSMatthew Barth { 2954ca87faeSMatthew Barth // Path found in cache 2964ca87faeSMatthew Barth for (auto& itServ : itPath.second) 2974ca87faeSMatthew Barth { 2984ca87faeSMatthew Barth auto servIter = pathIter->second.find(itServ.first); 2994ca87faeSMatthew Barth if (servIter != pathIter->second.end()) 3004ca87faeSMatthew Barth { 3014ca87faeSMatthew Barth // Service found in cache 3024ca87faeSMatthew Barth for (auto& itIntf : itServ.second) 3034ca87faeSMatthew Barth { 3044ca87faeSMatthew Barth if (std::find(servIter->second.second.begin(), 3054ca87faeSMatthew Barth servIter->second.second.end(), 3064ca87faeSMatthew Barth itIntf) == servIter->second.second.end()) 3074ca87faeSMatthew Barth { 3084ca87faeSMatthew Barth // Add interface to cache 3094ca87faeSMatthew Barth servIter->second.second.emplace_back(itIntf); 3104ca87faeSMatthew Barth } 3114ca87faeSMatthew Barth } 3124ca87faeSMatthew Barth } 3134ca87faeSMatthew Barth else 3144ca87faeSMatthew Barth { 3154ca87faeSMatthew Barth // Service not found in cache 3164ca87faeSMatthew Barth auto intfs = {intf}; 3174ca87faeSMatthew Barth pathIter->second[itServ.first] = 3184ca87faeSMatthew Barth std::make_pair(true, intfs); 3194ca87faeSMatthew Barth } 3204ca87faeSMatthew Barth } 3214ca87faeSMatthew Barth } 3224ca87faeSMatthew Barth else 3234ca87faeSMatthew Barth { 3244ca87faeSMatthew Barth // Path not found in cache 3254ca87faeSMatthew Barth auto intfs = {intf}; 3264ca87faeSMatthew Barth _servTree[itPath.first] = { 3274ca87faeSMatthew Barth {itPath.second.begin()->first, std::make_pair(true, intfs)}}; 3284ca87faeSMatthew Barth } 3294ca87faeSMatthew Barth } 3304ca87faeSMatthew Barth } 3314ca87faeSMatthew Barth 3324ca87faeSMatthew Barth const std::string& Manager::getService(const std::string& path, 3334ca87faeSMatthew Barth const std::string& intf) 3344ca87faeSMatthew Barth { 3354ca87faeSMatthew Barth // Retrieve service from cache 3364ca87faeSMatthew Barth const auto& serviceName = findService(path, intf); 3374ca87faeSMatthew Barth if (serviceName.empty()) 3384ca87faeSMatthew Barth { 33998f6fc17SMatthew Barth addServices(intf, 0); 3404ca87faeSMatthew Barth return findService(path, intf); 3414ca87faeSMatthew Barth } 3424ca87faeSMatthew Barth 3434ca87faeSMatthew Barth return serviceName; 3444ca87faeSMatthew Barth } 3454ca87faeSMatthew Barth 346f41e947bSMatthew Barth std::vector<std::string> Manager::findPaths(const std::string& serv, 347f41e947bSMatthew Barth const std::string& intf) 348f41e947bSMatthew Barth { 349f41e947bSMatthew Barth std::vector<std::string> paths; 350f41e947bSMatthew Barth 351f41e947bSMatthew Barth for (const auto& path : _servTree) 352f41e947bSMatthew Barth { 353f41e947bSMatthew Barth auto itServ = path.second.find(serv); 354f41e947bSMatthew Barth if (itServ != path.second.end()) 355f41e947bSMatthew Barth { 356f41e947bSMatthew Barth if (std::find(itServ->second.second.begin(), 357f41e947bSMatthew Barth itServ->second.second.end(), 358f41e947bSMatthew Barth intf) != itServ->second.second.end()) 359f41e947bSMatthew Barth { 360f41e947bSMatthew Barth if (std::find(paths.begin(), paths.end(), path.first) == 361f41e947bSMatthew Barth paths.end()) 362f41e947bSMatthew Barth { 363f41e947bSMatthew Barth paths.push_back(path.first); 364f41e947bSMatthew Barth } 365f41e947bSMatthew Barth } 366f41e947bSMatthew Barth } 367f41e947bSMatthew Barth } 368f41e947bSMatthew Barth 369f41e947bSMatthew Barth return paths; 370f41e947bSMatthew Barth } 371f41e947bSMatthew Barth 372f41e947bSMatthew Barth std::vector<std::string> Manager::getPaths(const std::string& serv, 373f41e947bSMatthew Barth const std::string& intf) 374f41e947bSMatthew Barth { 375f41e947bSMatthew Barth auto paths = findPaths(serv, intf); 376f41e947bSMatthew Barth if (paths.empty()) 377f41e947bSMatthew Barth { 378f41e947bSMatthew Barth addServices(intf, 0); 379f41e947bSMatthew Barth return findPaths(serv, intf); 380f41e947bSMatthew Barth } 381f41e947bSMatthew Barth 382f41e947bSMatthew Barth return paths; 383f41e947bSMatthew Barth } 384f41e947bSMatthew Barth 385f41e947bSMatthew Barth void Manager::addObjects(const std::string& path, const std::string& intf, 386f41e947bSMatthew Barth const std::string& prop) 387f41e947bSMatthew Barth { 388f41e947bSMatthew Barth auto service = getService(path, intf); 389f41e947bSMatthew Barth if (service.empty()) 390f41e947bSMatthew Barth { 391f41e947bSMatthew Barth // Log service not found for object 39234835150SMatt Spinler log<level::DEBUG>( 393f41e947bSMatthew Barth fmt::format("Unable to get service name for path {}, interface {}", 394f41e947bSMatthew Barth path, intf) 395f41e947bSMatthew Barth .c_str()); 396f41e947bSMatthew Barth return; 397f41e947bSMatthew Barth } 398f41e947bSMatthew Barth 399f41e947bSMatthew Barth auto objMgrPaths = getPaths(service, "org.freedesktop.DBus.ObjectManager"); 400f41e947bSMatthew Barth if (objMgrPaths.empty()) 401f41e947bSMatthew Barth { 402f41e947bSMatthew Barth // No object manager interface provided by service? 403f41e947bSMatthew Barth // Attempt to retrieve property directly 404f41e947bSMatthew Barth auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>( 405f41e947bSMatthew Barth _bus, service, path, intf, prop); 406f41e947bSMatthew Barth _objects[path][intf][prop] = variant; 407f41e947bSMatthew Barth return; 408f41e947bSMatthew Barth } 409f41e947bSMatthew Barth 410f41e947bSMatthew Barth for (const auto& objMgrPath : objMgrPaths) 411f41e947bSMatthew Barth { 412f41e947bSMatthew Barth // Get all managed objects of service 413f41e947bSMatthew Barth auto objects = util::SDBusPlus::getManagedObjects<PropertyVariantType>( 414f41e947bSMatthew Barth _bus, service, objMgrPath); 415f41e947bSMatthew Barth 416f41e947bSMatthew Barth // Add what's returned to the cache of objects 417f41e947bSMatthew Barth for (auto& object : objects) 418f41e947bSMatthew Barth { 419f41e947bSMatthew Barth auto itPath = _objects.find(object.first); 420f41e947bSMatthew Barth if (itPath != _objects.end()) 421f41e947bSMatthew Barth { 422f41e947bSMatthew Barth // Path found in cache 423f41e947bSMatthew Barth for (auto& interface : itPath->second) 424f41e947bSMatthew Barth { 425f41e947bSMatthew Barth auto itIntf = itPath->second.find(interface.first); 426f41e947bSMatthew Barth if (itIntf != itPath->second.end()) 427f41e947bSMatthew Barth { 428f41e947bSMatthew Barth // Interface found in cache 429f41e947bSMatthew Barth for (auto& property : itIntf->second) 430f41e947bSMatthew Barth { 431f41e947bSMatthew Barth auto itProp = itIntf->second.find(property.first); 432f41e947bSMatthew Barth if (itProp != itIntf->second.end()) 433f41e947bSMatthew Barth { 434f41e947bSMatthew Barth // Property found, update value 435f41e947bSMatthew Barth itProp->second = property.second; 436f41e947bSMatthew Barth } 437f41e947bSMatthew Barth else 438f41e947bSMatthew Barth { 439f41e947bSMatthew Barth itIntf->second.insert(property); 440f41e947bSMatthew Barth } 441f41e947bSMatthew Barth } 442f41e947bSMatthew Barth } 443f41e947bSMatthew Barth else 444f41e947bSMatthew Barth { 445f41e947bSMatthew Barth // Interface not found in cache 446f41e947bSMatthew Barth itPath->second.insert(interface); 447f41e947bSMatthew Barth } 448f41e947bSMatthew Barth } 449f41e947bSMatthew Barth } 450f41e947bSMatthew Barth else 451f41e947bSMatthew Barth { 452f41e947bSMatthew Barth // Path not found in cache 453f41e947bSMatthew Barth _objects.insert(object); 454f41e947bSMatthew Barth } 455f41e947bSMatthew Barth } 456f41e947bSMatthew Barth } 457f41e947bSMatthew Barth } 458f41e947bSMatthew Barth 459f41e947bSMatthew Barth const std::optional<PropertyVariantType> 460f41e947bSMatthew Barth Manager::getProperty(const std::string& path, const std::string& intf, 461f41e947bSMatthew Barth const std::string& prop) 462f41e947bSMatthew Barth { 463f41e947bSMatthew Barth // TODO Objects hosted by fan control (i.e. ThermalMode) are required to 464f41e947bSMatthew Barth // update the cache upon being set/updated 465f41e947bSMatthew Barth auto itPath = _objects.find(path); 466f41e947bSMatthew Barth if (itPath != _objects.end()) 467f41e947bSMatthew Barth { 468f41e947bSMatthew Barth auto itIntf = itPath->second.find(intf); 469f41e947bSMatthew Barth if (itIntf != itPath->second.end()) 470f41e947bSMatthew Barth { 471f41e947bSMatthew Barth auto itProp = itIntf->second.find(prop); 472f41e947bSMatthew Barth if (itProp != itIntf->second.end()) 473f41e947bSMatthew Barth { 474f41e947bSMatthew Barth return itProp->second; 475f41e947bSMatthew Barth } 476f41e947bSMatthew Barth } 477f41e947bSMatthew Barth } 478f41e947bSMatthew Barth 479f41e947bSMatthew Barth return std::nullopt; 480f41e947bSMatthew Barth } 481f41e947bSMatthew Barth 482d9cb63b6SMatthew Barth void Manager::addTimer(const TimerType type, 483d9cb63b6SMatthew Barth const std::chrono::microseconds interval, 484d9cb63b6SMatthew Barth std::unique_ptr<TimerPkg> pkg) 485d9cb63b6SMatthew Barth { 486d9cb63b6SMatthew Barth auto dataPtr = 487d9cb63b6SMatthew Barth std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg))); 488d9cb63b6SMatthew Barth Timer timer(_event, 489d9cb63b6SMatthew Barth std::bind(&Manager::timerExpired, this, std::ref(*dataPtr))); 490d9cb63b6SMatthew Barth if (type == TimerType::repeating) 491d9cb63b6SMatthew Barth { 492d9cb63b6SMatthew Barth timer.restart(interval); 493d9cb63b6SMatthew Barth } 494d9cb63b6SMatthew Barth else if (type == TimerType::oneshot) 495d9cb63b6SMatthew Barth { 496d9cb63b6SMatthew Barth timer.restartOnce(interval); 497d9cb63b6SMatthew Barth } 498d9cb63b6SMatthew Barth else 499d9cb63b6SMatthew Barth { 500d9cb63b6SMatthew Barth throw std::invalid_argument("Invalid Timer Type"); 501d9cb63b6SMatthew Barth } 502d9cb63b6SMatthew Barth _timers.emplace_back(std::move(dataPtr), std::move(timer)); 503d9cb63b6SMatthew Barth } 504d9cb63b6SMatthew Barth 505d9cb63b6SMatthew Barth void Manager::timerExpired(TimerData& data) 506d9cb63b6SMatthew Barth { 507d9cb63b6SMatthew Barth auto& actions = 508d9cb63b6SMatthew Barth std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second); 509d9cb63b6SMatthew Barth // Perform the actions in the timer data 510d9cb63b6SMatthew Barth std::for_each(actions.begin(), actions.end(), 51100f6aa09SMatthew Barth [](auto& action) { action->run(); }); 512d9cb63b6SMatthew Barth 513d9cb63b6SMatthew Barth // Remove oneshot timers after they expired 514d9cb63b6SMatthew Barth if (data.first == TimerType::oneshot) 515d9cb63b6SMatthew Barth { 516d9cb63b6SMatthew Barth auto itTimer = std::find_if( 517d9cb63b6SMatthew Barth _timers.begin(), _timers.end(), [&data](const auto& timer) { 518d9cb63b6SMatthew Barth return (data.first == timer.first->first && 519d9cb63b6SMatthew Barth (std::get<std::string>(data.second) == 520d9cb63b6SMatthew Barth std::get<std::string>(timer.first->second))); 521d9cb63b6SMatthew Barth }); 522d9cb63b6SMatthew Barth if (itTimer != std::end(_timers)) 523d9cb63b6SMatthew Barth { 524d9cb63b6SMatthew Barth _timers.erase(itTimer); 525d9cb63b6SMatthew Barth } 526d9cb63b6SMatthew Barth } 527d9cb63b6SMatthew Barth } 528d9cb63b6SMatthew Barth 529ebabc040SMatthew Barth void Manager::handleSignal(sdbusplus::message::message& msg, 530fac8a2feSMatthew Barth const std::vector<SignalPkg>& pkgs) 531ebabc040SMatthew Barth { 532fac8a2feSMatthew Barth for (auto& pkg : pkgs) 533ebabc040SMatthew Barth { 534ebabc040SMatthew Barth // Handle the signal callback and only run the actions if the handler 535ebabc040SMatthew Barth // updated the cache for the given SignalObject 536ebabc040SMatthew Barth if (std::get<SignalHandler>(pkg)(msg, std::get<SignalObject>(pkg), 537ebabc040SMatthew Barth *this)) 538ebabc040SMatthew Barth { 539ebabc040SMatthew Barth // Perform the actions in the handler package 540ebabc040SMatthew Barth auto& actions = std::get<SignalActions>(pkg); 541ebabc040SMatthew Barth std::for_each(actions.begin(), actions.end(), 542ebabc040SMatthew Barth [](auto& action) { action.get()->run(); }); 543ebabc040SMatthew Barth } 544ebabc040SMatthew Barth } 545ebabc040SMatthew Barth } 546ebabc040SMatthew Barth 547acd737cdSMatthew Barth void Manager::setProfiles() 548acd737cdSMatthew Barth { 549acd737cdSMatthew Barth // Profiles JSON config file is optional 550acd737cdSMatthew Barth auto confFile = fan::JsonConfig::getConfFile(_bus, confAppName, 551acd737cdSMatthew Barth Profile::confFileName, true); 552e91ac864SMatthew Barth 553e91ac864SMatthew Barth _profiles.clear(); 554acd737cdSMatthew Barth if (!confFile.empty()) 555acd737cdSMatthew Barth { 556acd737cdSMatthew Barth for (const auto& entry : fan::JsonConfig::load(confFile)) 557acd737cdSMatthew Barth { 558acd737cdSMatthew Barth auto obj = std::make_unique<Profile>(entry); 559acd737cdSMatthew Barth _profiles.emplace( 560acd737cdSMatthew Barth std::make_pair(obj->getName(), obj->getProfiles()), 561acd737cdSMatthew Barth std::move(obj)); 562acd737cdSMatthew Barth } 563acd737cdSMatthew Barth } 564e91ac864SMatthew Barth 565acd737cdSMatthew Barth // Ensure all configurations use the same set of active profiles 566acd737cdSMatthew Barth // (In case a profile's active state changes during configuration) 567e91ac864SMatthew Barth _activeProfiles.clear(); 568acd737cdSMatthew Barth for (const auto& profile : _profiles) 569acd737cdSMatthew Barth { 570acd737cdSMatthew Barth if (profile.second->isActive()) 571acd737cdSMatthew Barth { 572acd737cdSMatthew Barth _activeProfiles.emplace_back(profile.first.first); 573acd737cdSMatthew Barth } 574acd737cdSMatthew Barth } 575acd737cdSMatthew Barth } 576acd737cdSMatthew Barth 577a227a16dSMatthew Barth } // namespace phosphor::fan::control::json 578