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