1279183feSMatthew Barth /**
2279183feSMatthew Barth  * Copyright © 2021 IBM Corporation
3279183feSMatthew Barth  *
4279183feSMatthew Barth  * Licensed under the Apache License, Version 2.0 (the "License");
5279183feSMatthew Barth  * you may not use this file except in compliance with the License.
6279183feSMatthew Barth  * You may obtain a copy of the License at
7279183feSMatthew Barth  *
8279183feSMatthew Barth  *     http://www.apache.org/licenses/LICENSE-2.0
9279183feSMatthew Barth  *
10279183feSMatthew Barth  * Unless required by applicable law or agreed to in writing, software
11279183feSMatthew Barth  * distributed under the License is distributed on an "AS IS" BASIS,
12279183feSMatthew Barth  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13279183feSMatthew Barth  * See the License for the specific language governing permissions and
14279183feSMatthew Barth  * limitations under the License.
15279183feSMatthew Barth  */
16279183feSMatthew Barth #include "config.h"
17279183feSMatthew Barth 
18279183feSMatthew Barth #include "dbus_zone.hpp"
19279183feSMatthew Barth 
20bf8e56f6SMike Capps #include "dbus_paths.hpp"
21279183feSMatthew Barth #include "sdbusplus.hpp"
22279183feSMatthew Barth #include "zone.hpp"
23279183feSMatthew Barth 
24279183feSMatthew Barth #include <cereal/archives/json.hpp>
25279183feSMatthew Barth #include <cereal/cereal.hpp>
26279183feSMatthew Barth #include <phosphor-logging/log.hpp>
27279183feSMatthew Barth 
28279183feSMatthew Barth #include <algorithm>
29279183feSMatthew Barth #include <filesystem>
30*fbf4703fSPatrick Williams #include <format>
31279183feSMatthew Barth #include <fstream>
32279183feSMatthew Barth 
33279183feSMatthew Barth namespace phosphor::fan::control::json
34279183feSMatthew Barth {
35279183feSMatthew Barth 
36279183feSMatthew Barth using namespace phosphor::logging;
37279183feSMatthew Barth namespace fs = std::filesystem;
38279183feSMatthew Barth 
DBusZone(const Zone & zone)39279183feSMatthew Barth DBusZone::DBusZone(const Zone& zone) :
40279183feSMatthew Barth     ThermalModeIntf(util::SDBusPlus::getBus(),
41279183feSMatthew Barth                     (fs::path{CONTROL_OBJPATH} /= zone.getName()).c_str(),
42a3ed9b09SPatrick Williams                     ThermalModeIntf::action::defer_emit),
43279183feSMatthew Barth     _zone(zone)
44279183feSMatthew Barth {}
45279183feSMatthew Barth 
current(std::string value)46279183feSMatthew Barth std::string DBusZone::current(std::string value)
47279183feSMatthew Barth {
48279183feSMatthew Barth     auto current = ThermalModeIntf::current();
49279183feSMatthew Barth     std::transform(value.begin(), value.end(), value.begin(), toupper);
50279183feSMatthew Barth 
51279183feSMatthew Barth     auto supported = ThermalModeIntf::supported();
5261b73296SPatrick Williams     auto isSupported = std::any_of(supported.begin(), supported.end(),
5361b73296SPatrick Williams                                    [&value](auto& s) {
54279183feSMatthew Barth         std::transform(s.begin(), s.end(), s.begin(), toupper);
55279183feSMatthew Barth         return value == s;
56279183feSMatthew Barth     });
57279183feSMatthew Barth 
58279183feSMatthew Barth     if (isSupported && value != current)
59279183feSMatthew Barth     {
60279183feSMatthew Barth         current = ThermalModeIntf::current(value);
61279183feSMatthew Barth         if (_zone.isPersisted(thermalModeIntf, currentProp))
62279183feSMatthew Barth         {
63279183feSMatthew Barth             saveCurrentMode();
64279183feSMatthew Barth         }
65279183feSMatthew Barth     }
66279183feSMatthew Barth 
67279183feSMatthew Barth     return current;
68279183feSMatthew Barth }
69279183feSMatthew Barth 
restoreCurrentMode()70279183feSMatthew Barth void DBusZone::restoreCurrentMode()
71279183feSMatthew Barth {
72279183feSMatthew Barth     auto current = ThermalModeIntf::current();
73279183feSMatthew Barth     fs::path path{CONTROL_PERSIST_ROOT_PATH};
74279183feSMatthew Barth     // Append this object's name and property description
75279183feSMatthew Barth     path /= _zone.getName();
76279183feSMatthew Barth     path /= "CurrentMode";
77279183feSMatthew Barth     fs::create_directories(path.parent_path());
78279183feSMatthew Barth 
79279183feSMatthew Barth     try
80279183feSMatthew Barth     {
81279183feSMatthew Barth         if (fs::exists(path))
82279183feSMatthew Barth         {
83279183feSMatthew Barth             std::ifstream ifs(path.c_str(), std::ios::in | std::ios::binary);
84279183feSMatthew Barth             cereal::JSONInputArchive iArch(ifs);
85279183feSMatthew Barth             iArch(current);
86279183feSMatthew Barth         }
87279183feSMatthew Barth     }
88ddb773b2SPatrick Williams     catch (const std::exception& e)
89279183feSMatthew Barth     {
907072237bSMatthew Barth         // Include possible exception when removing file, otherwise ec = 0
917072237bSMatthew Barth         std::error_code ec;
927072237bSMatthew Barth         fs::remove(path, ec);
937072237bSMatthew Barth         log<level::ERR>(
94*fbf4703fSPatrick Williams             std::format("Unable to restore persisted `Current` thermal mode "
957072237bSMatthew Barth                         "property ({}, ec: {})",
967072237bSMatthew Barth                         e.what(), ec.value())
977072237bSMatthew Barth                 .c_str());
98279183feSMatthew Barth         current = ThermalModeIntf::current();
99279183feSMatthew Barth     }
100279183feSMatthew Barth 
101279183feSMatthew Barth     this->current(current);
102279183feSMatthew Barth }
103279183feSMatthew Barth 
saveCurrentMode()104279183feSMatthew Barth void DBusZone::saveCurrentMode()
105279183feSMatthew Barth {
106279183feSMatthew Barth     fs::path path{CONTROL_PERSIST_ROOT_PATH};
107279183feSMatthew Barth     // Append this object's name and property description
108279183feSMatthew Barth     path /= _zone.getName();
109279183feSMatthew Barth     path /= "CurrentMode";
110279183feSMatthew Barth     std::ofstream ofs(path.c_str(), std::ios::binary);
111279183feSMatthew Barth     cereal::JSONOutputArchive oArch(ofs);
112279183feSMatthew Barth     oArch(ThermalModeIntf::current());
113279183feSMatthew Barth }
114279183feSMatthew Barth 
115279183feSMatthew Barth } // namespace phosphor::fan::control::json
116