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 "config.h" 17 18 #include "dbus_zone.hpp" 19 20 #include "dbus_paths.hpp" 21 #include "sdbusplus.hpp" 22 #include "zone.hpp" 23 24 #include <cereal/archives/json.hpp> 25 #include <cereal/cereal.hpp> 26 #include <phosphor-logging/log.hpp> 27 28 #include <algorithm> 29 #include <filesystem> 30 #include <format> 31 #include <fstream> 32 33 namespace phosphor::fan::control::json 34 { 35 36 using namespace phosphor::logging; 37 namespace fs = std::filesystem; 38 39 DBusZone::DBusZone(const Zone& zone) : 40 ThermalModeIntf(util::SDBusPlus::getBus(), 41 (fs::path{CONTROL_OBJPATH} /= zone.getName()).c_str(), 42 ThermalModeIntf::action::defer_emit), 43 _zone(zone) 44 {} 45 46 std::string DBusZone::current(std::string value) 47 { 48 auto current = ThermalModeIntf::current(); 49 std::transform(value.begin(), value.end(), value.begin(), toupper); 50 51 auto supported = ThermalModeIntf::supported(); 52 auto isSupported = std::any_of(supported.begin(), supported.end(), 53 [&value](auto& s) { 54 std::transform(s.begin(), s.end(), s.begin(), toupper); 55 return value == s; 56 }); 57 58 if (isSupported && value != current) 59 { 60 current = ThermalModeIntf::current(value); 61 if (_zone.isPersisted(thermalModeIntf, currentProp)) 62 { 63 saveCurrentMode(); 64 } 65 } 66 67 return current; 68 } 69 70 void DBusZone::restoreCurrentMode() 71 { 72 auto current = ThermalModeIntf::current(); 73 fs::path path{CONTROL_PERSIST_ROOT_PATH}; 74 // Append this object's name and property description 75 path /= _zone.getName(); 76 path /= "CurrentMode"; 77 fs::create_directories(path.parent_path()); 78 79 try 80 { 81 if (fs::exists(path)) 82 { 83 std::ifstream ifs(path.c_str(), std::ios::in | std::ios::binary); 84 cereal::JSONInputArchive iArch(ifs); 85 iArch(current); 86 } 87 } 88 catch (const std::exception& e) 89 { 90 // Include possible exception when removing file, otherwise ec = 0 91 std::error_code ec; 92 fs::remove(path, ec); 93 log<level::ERR>( 94 std::format("Unable to restore persisted `Current` thermal mode " 95 "property ({}, ec: {})", 96 e.what(), ec.value()) 97 .c_str()); 98 current = ThermalModeIntf::current(); 99 } 100 101 this->current(current); 102 } 103 104 void DBusZone::saveCurrentMode() 105 { 106 fs::path path{CONTROL_PERSIST_ROOT_PATH}; 107 // Append this object's name and property description 108 path /= _zone.getName(); 109 path /= "CurrentMode"; 110 std::ofstream ofs(path.c_str(), std::ios::binary); 111 cereal::JSONOutputArchive oArch(ofs); 112 oArch(ThermalModeIntf::current()); 113 } 114 115 } // namespace phosphor::fan::control::json 116