xref: /openbmc/phosphor-settingsd/settings_manager.mako.hpp (revision c15990a32063192e51c0c3ef5e65e149b2c44d70)
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