1 ## This file is a template. The comment below is emitted 2 ## into the rendered file; feel free to edit this file. 3 // WARNING: Generated header. Do not edit! 4 <% 5 from collections import defaultdict 6 objects = list(settingsDict.viewkeys()) 7 sdbusplus_namespaces = [] 8 sdbusplus_includes = [] 9 interfaces = [] 10 props = defaultdict(list) 11 12 def get_setting_sdbusplus_type(setting_intf): 13 setting = "sdbusplus::" + setting_intf.replace('.', '::') 14 i = setting.rfind('::') 15 setting = setting[:i] + '::server::' + setting[i+2:] 16 return setting 17 18 def get_setting_type(setting_intf): 19 setting = setting_intf.replace('.', '::') 20 return setting 21 %>\ 22 #pragma once 23 24 % for object in objects: 25 <% 26 include = settingsDict[object]['Interface'] 27 include = include.replace('.', '/') 28 include = include + "/server.hpp" 29 sdbusplus_includes.append(include) 30 %>\ 31 % endfor 32 #include <cereal/archives/json.hpp> 33 #include <fstream> 34 #include <utility> 35 #include <experimental/filesystem> 36 #include "config.h" 37 38 % for i in set(sdbusplus_includes): 39 #include "${i}" 40 % endfor 41 42 % for object in objects: 43 <% 44 ns = get_setting_sdbusplus_type(settingsDict[object]['Interface']) 45 i = ns.rfind('::') 46 ns = ns[:i] 47 sdbusplus_namespaces.append(ns) 48 %>\ 49 % endfor 50 51 namespace phosphor 52 { 53 namespace settings 54 { 55 56 namespace fs = std::experimental::filesystem; 57 58 % for n in set(sdbusplus_namespaces): 59 using namespace ${n}; 60 % endfor 61 62 % for object in objects: 63 <% 64 intf = settingsDict[object]['Interface'] 65 interfaces.append(intf) 66 if intf not in props: 67 for property, value in settingsDict[object]['Defaults'].items(): 68 props[intf].append(property) 69 %>\ 70 % endfor 71 % for intf in set(interfaces): 72 <% 73 ns = intf.split(".") 74 sdbusplus_type = get_setting_sdbusplus_type(intf) 75 %>\ 76 % for n in ns: 77 namespace ${n} 78 { 79 % endfor 80 81 using Base = ${sdbusplus_type}; 82 <% parent = "sdbusplus::server::object::object" + "<" + sdbusplus_type + ">" %>\ 83 using Parent = ${parent}; 84 85 class Impl : public Parent 86 { 87 public: 88 Impl(sdbusplus::bus::bus& bus, const char* path): 89 Parent(bus, path, true), 90 path(path) 91 { 92 } 93 virtual ~Impl() = default; 94 95 % for arg in props[intf]: 96 <% t = arg[:1].lower() + arg[1:] %>\ 97 decltype(std::declval<Base>().${t}()) ${t}(decltype(std::declval<Base>().${t}()) value) override 98 { 99 auto result = Base::${t}(); 100 if (value != result) 101 { 102 fs::path p(SETTINGS_PERSIST_PATH); 103 p /= path; 104 fs::create_directories(p.parent_path()); 105 std::ofstream os(p.c_str(), std::ios::binary); 106 cereal::JSONOutputArchive oarchive(os); 107 result = Base::${t}(value); 108 oarchive(*this); 109 } 110 return result; 111 } 112 using Base::${t}; 113 114 % endfor 115 private: 116 fs::path path; 117 }; 118 119 template<class Archive> 120 void save(Archive& a, 121 const Impl& setting) 122 { 123 <% 124 args = ["setting." + p[:1].lower() + p[1:] + "()" for p in props[intf]] 125 args = ','.join(args) 126 %>\ 127 a(${args}); 128 } 129 130 template<class Archive> 131 void load(Archive& a, 132 Impl& setting) 133 { 134 % for arg in props[intf]: 135 <% t = "setting." + arg[:1].lower() + arg[1:] + "()" %>\ 136 decltype(${t}) ${arg}{}; 137 % endfor 138 <% 139 args = ','.join(props[intf]) 140 %>\ 141 a(${args}); 142 % for arg in props[intf]: 143 <% t = "setting." + arg[:1].lower() + arg[1:] + "(" + arg + ")" %>\ 144 ${t}; 145 % endfor 146 } 147 148 % for n in reversed(ns): 149 } // namespace ${n} 150 % endfor 151 % endfor 152 153 /** @class Manager 154 * 155 * @brief Compose settings objects and put them on the bus. 156 */ 157 class Manager 158 { 159 public: 160 Manager() = delete; 161 Manager(const Manager&) = delete; 162 Manager& operator=(const Manager&) = delete; 163 Manager(Manager&&) = delete; 164 Manager& operator=(Manager&&) = delete; 165 virtual ~Manager() = default; 166 167 /** @brief Constructor to put settings objects on to the bus. 168 * @param[in] bus - Bus to attach to. 169 */ 170 Manager(sdbusplus::bus::bus& bus) 171 { 172 fs::path path{}; 173 settings = 174 std::make_tuple( 175 % for index, object in enumerate(objects): 176 <% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\ 177 std::make_unique<${type}>( 178 bus, 179 % if index < len(settingsDict) - 1: 180 "${object}"), 181 % else: 182 "${object}")); 183 % endif 184 % endfor 185 186 % for index, object in enumerate(objects): 187 % for property, value in settingsDict[object]['Defaults'].items(): 188 <% p = property[:1].lower() + property[1:] %>\ 189 path = fs::path(SETTINGS_PERSIST_PATH) / "${object}"; 190 if (fs::exists(path)) 191 { 192 std::ifstream is(path.c_str(), std::ios::in); 193 cereal::JSONInputArchive iarchive(is); 194 iarchive(*std::get<${index}>(settings)); 195 } 196 else 197 { 198 std::get<${index}>(settings)-> 199 ${get_setting_sdbusplus_type(settingsDict[object]['Interface'])}::${p}(${value}); 200 } 201 % endfor 202 std::get<${index}>(settings)->emit_object_added(); 203 204 % endfor 205 } 206 207 private: 208 /* @brief Composition of settings objects. */ 209 std::tuple< 210 % for index, object in enumerate(objects): 211 <% type = get_setting_type(settingsDict[object]['Interface']) + "::Impl" %>\ 212 % if index < len(settingsDict) - 1: 213 std::unique_ptr<${type}>, 214 % else: 215 std::unique_ptr<${type}>> settings; 216 % endif 217 % endfor 218 }; 219 220 } // namespace settings 221 } // namespace phosphor 222