xref: /openbmc/phosphor-settingsd/settings_manager.mako.hpp (revision e568fcad2ca4c41487d6cd2f8ff5969aac32a2b0)
15de0957cSDeepak Kodihalli ## This file is a template.  The comment below is emitted
25de0957cSDeepak Kodihalli ## into the rendered file; feel free to edit this file.
35de0957cSDeepak Kodihalli // WARNING: Generated header. Do not edit!
45de0957cSDeepak Kodihalli <%
561d3b6a1SDhruvaraj Subhashchandran import re
67a6f2526SDeepak Kodihalli from collections import defaultdict
7bcf95781SPatrick Williams from sdbusplus.namedelement import NamedElement
82b7152fbSPatrick Williams objects = settingsDict.keys()
97a6f2526SDeepak Kodihalli sdbusplus_includes = []
107a6f2526SDeepak Kodihalli props = defaultdict(list)
1161d3b6a1SDhruvaraj Subhashchandran validators = defaultdict(tuple)
125de0957cSDeepak Kodihalli 
137a6f2526SDeepak Kodihalli def get_setting_sdbusplus_type(setting_intf):
145de0957cSDeepak Kodihalli     setting = "sdbusplus::" + setting_intf.replace('.', '::')
155de0957cSDeepak Kodihalli     i = setting.rfind('::')
165de0957cSDeepak Kodihalli     setting = setting[:i] + '::server::' + setting[i+2:]
175de0957cSDeepak Kodihalli     return setting
187a6f2526SDeepak Kodihalli 
19db838626SDeepak Kodihalli def get_setting_type(path):
20db838626SDeepak Kodihalli     path = path[1:]
21db838626SDeepak Kodihalli     path = path.replace('/', '::')
22db838626SDeepak Kodihalli     return path
23ffdf8658SMatt Spinler 
24ffdf8658SMatt Spinler def get_default_value(object, interface, prop):
25ffdf8658SMatt Spinler     default_value = None
26ffdf8658SMatt Spinler     for item in settingsDict[object]:
27ffdf8658SMatt Spinler         if item['Interface'] == interface:
28ffdf8658SMatt Spinler             default_value = item['Properties'][prop]['Default']
29ffdf8658SMatt Spinler             break
30ffdf8658SMatt Spinler 
31ffdf8658SMatt Spinler     if isinstance(default_value, str) and  not \
32ffdf8658SMatt Spinler         default_value.startswith('"') and '::' in default_value:
33ffdf8658SMatt Spinler             ns = get_setting_sdbusplus_type(interface)
34ffdf8658SMatt Spinler             i = ns.rfind('::')
35ffdf8658SMatt Spinler             default_value = "{}::{}".format(ns[:i], default_value)
36ffdf8658SMatt Spinler 
37ffdf8658SMatt Spinler     return default_value
385de0957cSDeepak Kodihalli %>\
395de0957cSDeepak Kodihalli #pragma once
405de0957cSDeepak Kodihalli 
415de0957cSDeepak Kodihalli % for object in objects:
42db838626SDeepak Kodihalli     % for item in settingsDict[object]:
435de0957cSDeepak Kodihalli <%
44db838626SDeepak Kodihalli     include = item['Interface']
455de0957cSDeepak Kodihalli     include = include.replace('.', '/')
465de0957cSDeepak Kodihalli     include = include + "/server.hpp"
477a6f2526SDeepak Kodihalli     sdbusplus_includes.append(include)
485de0957cSDeepak Kodihalli %>\
495de0957cSDeepak Kodihalli     % endfor
50db838626SDeepak Kodihalli % endfor
517a6f2526SDeepak Kodihalli #include <cereal/archives/json.hpp>
5274e3be7dSJames Feist #include <cereal/types/vector.hpp>
537a6f2526SDeepak Kodihalli #include <fstream>
547a6f2526SDeepak Kodihalli #include <utility>
556306e5e4SPatrick Williams #include <filesystem>
5661d3b6a1SDhruvaraj Subhashchandran #include <regex>
5761d3b6a1SDhruvaraj Subhashchandran #include <phosphor-logging/elog.hpp>
5861d3b6a1SDhruvaraj Subhashchandran #include <phosphor-logging/elog-errors.hpp>
59c2f84c7bSMatt Spinler #include <phosphor-logging/lg2.hpp>
6061d3b6a1SDhruvaraj Subhashchandran #include <xyz/openbmc_project/Common/error.hpp>
617a6f2526SDeepak Kodihalli 
624d28bcd3SJagpal Singh Gill /* The DBus busname to own */
634d28bcd3SJagpal Singh Gill #define SETTINGS_BUSNAME "xyz.openbmc_project.Settings"
644d28bcd3SJagpal Singh Gill /* Path of directory housing persisted settings */
654d28bcd3SJagpal Singh Gill #define SETTINGS_PERSIST_PATH "/var/lib/phosphor-settings-manager/settings"
664d28bcd3SJagpal Singh Gill 
674d28bcd3SJagpal Singh Gill /* Class version to register with Cereal */
68c2f84c7bSMatt Spinler static constexpr size_t CLASS_VERSION = 2;
69c2f84c7bSMatt Spinler static constexpr size_t CLASS_VERSION_WITH_NVP = 2;
704d28bcd3SJagpal Singh Gill 
717a6f2526SDeepak Kodihalli % for i in set(sdbusplus_includes):
725de0957cSDeepak Kodihalli #include "${i}"
735de0957cSDeepak Kodihalli % endfor
745de0957cSDeepak Kodihalli 
755de0957cSDeepak Kodihalli namespace phosphor
765de0957cSDeepak Kodihalli {
775de0957cSDeepak Kodihalli namespace settings
785de0957cSDeepak Kodihalli {
795de0957cSDeepak Kodihalli 
806306e5e4SPatrick Williams namespace fs = std::filesystem;
817a6f2526SDeepak Kodihalli 
82242bc77cSDeepak Kodihalli namespace persistent
83242bc77cSDeepak Kodihalli {
84242bc77cSDeepak Kodihalli 
85242bc77cSDeepak Kodihalli // A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
86242bc77cSDeepak Kodihalli // same path. This eases re-construction of settings objects when we restore
87242bc77cSDeepak Kodihalli // from the filesystem. This can be a problem though when you have two objects
88242bc77cSDeepak Kodihalli // such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
89242bc77cSDeepak Kodihalli // a file in the first case, and a subdir in the second. To solve this, suffix
90242bc77cSDeepak Kodihalli // files with a trailing __. The __ is a safe character sequence to use, because
91242bc77cSDeepak Kodihalli // we won't have d-bus object paths ending with this.
92242bc77cSDeepak Kodihalli // With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
93242bc77cSDeepak Kodihalli constexpr auto fileSuffix = "__";
94242bc77cSDeepak Kodihalli 
95242bc77cSDeepak Kodihalli }
96242bc77cSDeepak Kodihalli 
97fb1ad7ccSMatt Spinler static fs::path getFilePath(const fs::path& objectPath)
98fb1ad7ccSMatt Spinler {
99fb1ad7ccSMatt Spinler     fs::path p(SETTINGS_PERSIST_PATH);
100fb1ad7ccSMatt Spinler     p /= objectPath.relative_path();
101fb1ad7ccSMatt Spinler     p += persistent::fileSuffix;
102fb1ad7ccSMatt Spinler     return p;
103fb1ad7ccSMatt Spinler }
104fb1ad7ccSMatt Spinler 
1057a6f2526SDeepak Kodihalli % for object in objects:
1067a6f2526SDeepak Kodihalli <%
107db838626SDeepak Kodihalli    ns = object.split('/')
108db838626SDeepak Kodihalli    ns.pop(0)
1097a6f2526SDeepak Kodihalli %>\
1107a6f2526SDeepak Kodihalli % for n in ns:
1117a6f2526SDeepak Kodihalli namespace ${n}
1127a6f2526SDeepak Kodihalli {
1137a6f2526SDeepak Kodihalli % endfor
114db838626SDeepak Kodihalli <%
115db838626SDeepak Kodihalli     interfaces = []
116db838626SDeepak Kodihalli     aliases = []
117db838626SDeepak Kodihalli     for item in settingsDict[object]:
118db838626SDeepak Kodihalli         interfaces.append(item['Interface'])
119db838626SDeepak Kodihalli         for name, meta in item['Properties'].items():
120db838626SDeepak Kodihalli             if 'Validation' in meta:
121db838626SDeepak Kodihalli                 dict = meta['Validation']
122db838626SDeepak Kodihalli                 if dict['Type'] == "range":
123db838626SDeepak Kodihalli                     validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
124db838626SDeepak Kodihalli                 else:
125db838626SDeepak Kodihalli                     validators[name] = (dict['Type'], dict['Validator'])
126db838626SDeepak Kodihalli %>
127db838626SDeepak Kodihalli % for index, intf in enumerate(interfaces):
128db838626SDeepak Kodihalli using Iface${index} = ${get_setting_sdbusplus_type(intf)};
129db838626SDeepak Kodihalli <% aliases.append("Iface" + str(index)) %>\
130db838626SDeepak Kodihalli % endfor
131db838626SDeepak Kodihalli <%
1327c4181cfSPatrick Williams     parent = "sdbusplus::server::object_t" + "<" + ", ".join(aliases) + ">"
133db838626SDeepak Kodihalli %>\
1347a6f2526SDeepak Kodihalli using Parent = ${parent};
1357a6f2526SDeepak Kodihalli 
1367a6f2526SDeepak Kodihalli class Impl : public Parent
1377a6f2526SDeepak Kodihalli {
1387a6f2526SDeepak Kodihalli     public:
1397c4181cfSPatrick Williams         Impl(sdbusplus::bus_t& bus, const char* path):
14074c4f3b1SPatrick Williams             Parent(bus, path, Parent::action::defer_emit),
1417a6f2526SDeepak Kodihalli             path(path)
1427a6f2526SDeepak Kodihalli         {
1437a6f2526SDeepak Kodihalli         }
1447a6f2526SDeepak Kodihalli         virtual ~Impl() = default;
1457a6f2526SDeepak Kodihalli 
146fb1ad7ccSMatt Spinler         void setInitialVersion(std::uint32_t v)
147fb1ad7ccSMatt Spinler         {
148fb1ad7ccSMatt Spinler             initialVersion = v;
149fb1ad7ccSMatt Spinler         }
150fb1ad7ccSMatt Spinler 
151fb1ad7ccSMatt Spinler         std::uint32_t getInitialVersion() const
152fb1ad7ccSMatt Spinler         {
153fb1ad7ccSMatt Spinler             return initialVersion;
154fb1ad7ccSMatt Spinler         }
155fb1ad7ccSMatt Spinler 
156fb1ad7ccSMatt Spinler         bool deserialize()
157fb1ad7ccSMatt Spinler         {
158fb1ad7ccSMatt Spinler             auto p = getFilePath(path);
159fb1ad7ccSMatt Spinler             if (fs::exists(p))
160fb1ad7ccSMatt Spinler             {
161fb1ad7ccSMatt Spinler                 std::ifstream is(p.c_str(), std::ios::in);
162fb1ad7ccSMatt Spinler                 cereal::JSONInputArchive iarchive(is);
163fb1ad7ccSMatt Spinler                 iarchive(*this);
164fb1ad7ccSMatt Spinler                 return true;
165fb1ad7ccSMatt Spinler             }
166fb1ad7ccSMatt Spinler             return false;
167fb1ad7ccSMatt Spinler         }
168fb1ad7ccSMatt Spinler 
169fb1ad7ccSMatt Spinler         void serialize()
170fb1ad7ccSMatt Spinler         {
171fb1ad7ccSMatt Spinler             auto p = getFilePath(path);
172fb1ad7ccSMatt Spinler             if (!fs::exists(p.parent_path()))
173fb1ad7ccSMatt Spinler             {
174fb1ad7ccSMatt Spinler                 fs::create_directories(p.parent_path());
175fb1ad7ccSMatt Spinler             }
176fb1ad7ccSMatt Spinler             std::ofstream os(p.c_str(), std::ios::binary);
177fb1ad7ccSMatt Spinler             cereal::JSONOutputArchive oarchive(os);
178fb1ad7ccSMatt Spinler             oarchive(*this);
179fb1ad7ccSMatt Spinler         }
180fb1ad7ccSMatt Spinler 
181fb1ad7ccSMatt Spinler         void removeFile() const
182fb1ad7ccSMatt Spinler         {
183fb1ad7ccSMatt Spinler             std::error_code ec;
184fb1ad7ccSMatt Spinler             fs::remove(getFilePath(path), ec);
185fb1ad7ccSMatt Spinler         }
186fb1ad7ccSMatt Spinler 
187db838626SDeepak Kodihalli % for index, item in enumerate(settingsDict[object]):
188db838626SDeepak Kodihalli     % for propName, metaDict in item['Properties'].items():
189bcf95781SPatrick Williams <% t = NamedElement(name=propName).camelCase %>\
190db838626SDeepak Kodihalli <% fname = "validate" + propName %>\
191db838626SDeepak Kodihalli         decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
1927a6f2526SDeepak Kodihalli         {
193db838626SDeepak Kodihalli             auto result = Iface${index}::${t}();
1947a6f2526SDeepak Kodihalli             if (value != result)
1957a6f2526SDeepak Kodihalli             {
196db838626SDeepak Kodihalli             % if propName in validators:
19761d3b6a1SDhruvaraj Subhashchandran                 if (!${fname}(value))
19861d3b6a1SDhruvaraj Subhashchandran                 {
19961d3b6a1SDhruvaraj Subhashchandran                     namespace error =
20061d3b6a1SDhruvaraj Subhashchandran                         sdbusplus::xyz::openbmc_project::Common::Error;
20161d3b6a1SDhruvaraj Subhashchandran                     namespace metadata =
20261d3b6a1SDhruvaraj Subhashchandran                         phosphor::logging::xyz::openbmc_project::Common;
20361d3b6a1SDhruvaraj Subhashchandran                     phosphor::logging::report<error::InvalidArgument>(
20461d3b6a1SDhruvaraj Subhashchandran                         metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
205db838626SDeepak Kodihalli                     % if validators[propName][0] != "regex":
20661d3b6a1SDhruvaraj Subhashchandran                         metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
20761d3b6a1SDhruvaraj Subhashchandran                     % else:
20861d3b6a1SDhruvaraj Subhashchandran                         metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
20961d3b6a1SDhruvaraj Subhashchandran                     % endif
21061d3b6a1SDhruvaraj Subhashchandran                     return result;
21161d3b6a1SDhruvaraj Subhashchandran                 }
21261d3b6a1SDhruvaraj Subhashchandran              % endif
213db838626SDeepak Kodihalli                 result = Iface${index}::${t}(value);
214fb1ad7ccSMatt Spinler                 serialize();
2157a6f2526SDeepak Kodihalli             }
2167a6f2526SDeepak Kodihalli             return result;
2177a6f2526SDeepak Kodihalli         }
218db838626SDeepak Kodihalli         using Iface${index}::${t};
2197a6f2526SDeepak Kodihalli 
220c15990a3SAndrew Geissler     % endfor
221db838626SDeepak Kodihalli % endfor
2227a6f2526SDeepak Kodihalli     private:
2237a6f2526SDeepak Kodihalli         fs::path path;
224fb1ad7ccSMatt Spinler         std::uint32_t initialVersion = 0;
225db838626SDeepak Kodihalli % for index, item in enumerate(settingsDict[object]):
226db838626SDeepak Kodihalli   % for propName, metaDict in item['Properties'].items():
227bcf95781SPatrick Williams <% t = NamedElement(name=propName).camelCase %>\
228db838626SDeepak Kodihalli <% fname = "validate" + propName %>\
229db838626SDeepak Kodihalli     % if propName in validators:
23061d3b6a1SDhruvaraj Subhashchandran 
231db838626SDeepak Kodihalli         bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
23261d3b6a1SDhruvaraj Subhashchandran         {
23361d3b6a1SDhruvaraj Subhashchandran             bool matched = false;
234db838626SDeepak Kodihalli         % if (validators[propName][0] == 'regex'):
235db838626SDeepak Kodihalli             std::regex regexToCheck("${validators[propName][1]}");
23661d3b6a1SDhruvaraj Subhashchandran             matched = std::regex_search(value, regexToCheck);
23761d3b6a1SDhruvaraj Subhashchandran             if (!matched)
23861d3b6a1SDhruvaraj Subhashchandran             {
239*e568fcadSMatt Spinler                 lg2::error("Input parameter for ${propName} is invalid. "
240*e568fcadSMatt Spinler                            "Input '{VALUE}' not in the format of this regex: "
241*e568fcadSMatt Spinler                            "${validators[propName][1]}", "VALUE", value);
24261d3b6a1SDhruvaraj Subhashchandran             }
243db838626SDeepak Kodihalli         % elif (validators[propName][0] == 'range'):
244db838626SDeepak Kodihalli <% lowhigh = re.split('\.\.', validators[propName][1]) %>\
245cfd49eb8SJagpal Singh Gill         % if lowhigh[0] == '0':
246cfd49eb8SJagpal Singh Gill             if (value <= ${lowhigh[1]})
247cfd49eb8SJagpal Singh Gill         % else:
24861d3b6a1SDhruvaraj Subhashchandran             if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
249cfd49eb8SJagpal Singh Gill         % endif
25061d3b6a1SDhruvaraj Subhashchandran             {
25161d3b6a1SDhruvaraj Subhashchandran                 matched = true;
25261d3b6a1SDhruvaraj Subhashchandran             }
25361d3b6a1SDhruvaraj Subhashchandran             else
25461d3b6a1SDhruvaraj Subhashchandran             {
255*e568fcadSMatt Spinler                 lg2::error("Input parameter for ${propName} is invalid. "
256*e568fcadSMatt Spinler                            "Input '{VALUE}' with unit '${validators[propName][2]}' "
257*e568fcadSMatt Spinler                            "is not in range ${validators[propName][1]}",
258*e568fcadSMatt Spinler                            "VALUE", std::to_string(value));
25961d3b6a1SDhruvaraj Subhashchandran             }
260db838626SDeepak Kodihalli         % else:
261db838626SDeepak Kodihalli             <% assert("Unknown validation type: propName") %>\
26261d3b6a1SDhruvaraj Subhashchandran         % endif
26361d3b6a1SDhruvaraj Subhashchandran             return matched;
26461d3b6a1SDhruvaraj Subhashchandran         }
26561d3b6a1SDhruvaraj Subhashchandran     % endif
26661d3b6a1SDhruvaraj Subhashchandran   % endfor
267db838626SDeepak Kodihalli % endfor
2687a6f2526SDeepak Kodihalli };
2697a6f2526SDeepak Kodihalli 
2707a6f2526SDeepak Kodihalli template<class Archive>
2717a6f2526SDeepak Kodihalli void save(Archive& a,
272a29a3eb7SVishwanatha Subbanna           const Impl& setting,
273cfd49eb8SJagpal Singh Gill           [[maybe_unused]] const std::uint32_t version)
2747a6f2526SDeepak Kodihalli {
2757a6f2526SDeepak Kodihalli <%
276db838626SDeepak Kodihalli props = []
277db838626SDeepak Kodihalli for index, item in enumerate(settingsDict[object]):
278c2f84c7bSMatt Spinler     props.extend(item['Properties'].keys())
2797a6f2526SDeepak Kodihalli %>\
280c2f84c7bSMatt Spinler ## Since the iface isn't saved, property names need to be unique on
281c2f84c7bSMatt Spinler ## the object path.  This could be supported by providing unique
282c2f84c7bSMatt Spinler ## field names to make_nvp() if ever necessary.
283c2f84c7bSMatt Spinler % if len(set(props)) != len(props):
284c2f84c7bSMatt Spinler #error Duplicate property names on object path ${object}
285c0ce992fSLei YU %endif
286c2f84c7bSMatt Spinler <%
287c2f84c7bSMatt Spinler args = []
288c2f84c7bSMatt Spinler for prop in props:
289c2f84c7bSMatt Spinler     t = "setting." + NamedElement(name=prop).camelCase + "()"
290c2f84c7bSMatt Spinler     args.append(f"cereal::make_nvp(\"{prop}\", {t})")
291c2f84c7bSMatt Spinler args = ", ".join(args)
292c2f84c7bSMatt Spinler %>\
293c2f84c7bSMatt Spinler     a(${args});
2947a6f2526SDeepak Kodihalli }
2957a6f2526SDeepak Kodihalli 
2967a6f2526SDeepak Kodihalli template<class Archive>
2977a6f2526SDeepak Kodihalli void load(Archive& a,
298a29a3eb7SVishwanatha Subbanna           Impl& setting,
299c2f84c7bSMatt Spinler           const std::uint32_t version)
3007a6f2526SDeepak Kodihalli {
301fb1ad7ccSMatt Spinler     setting.setInitialVersion(version);
3027a6f2526SDeepak Kodihalli <%
303c2f84c7bSMatt Spinler props = []
304c2f84c7bSMatt Spinler for index, item in enumerate(settingsDict[object]):
305c2f84c7bSMatt Spinler     for prop in item['Properties'].keys():
306bcf95781SPatrick Williams         t = "setting." + NamedElement(name=prop).camelCase + "()"
307c2f84c7bSMatt Spinler         props.append({'prop' : prop, 'iface': item['Interface'], 'func': t})
3087a6f2526SDeepak Kodihalli %>\
309c2f84c7bSMatt Spinler % for p in props:
310c2f84c7bSMatt Spinler     decltype(${p['func']}) ${p['prop']}{};
311db838626SDeepak Kodihalli % endfor
312c2f84c7bSMatt Spinler <% propList = ', '.join([p['prop'] for p in props]) %>
313c2f84c7bSMatt Spinler % if propList:
314c2f84c7bSMatt Spinler     if (version < CLASS_VERSION_WITH_NVP)
315c2f84c7bSMatt Spinler     {
316c2f84c7bSMatt Spinler         a(${propList});
317c2f84c7bSMatt Spinler     }
318c2f84c7bSMatt Spinler     else
319c2f84c7bSMatt Spinler     {
320c2f84c7bSMatt Spinler     % for p in props:
321c2f84c7bSMatt Spinler         try
322c2f84c7bSMatt Spinler         {
323c2f84c7bSMatt Spinler             a(CEREAL_NVP(${p['prop']}));
324c2f84c7bSMatt Spinler         }
325c2f84c7bSMatt Spinler         catch (const cereal::Exception& e)
326c2f84c7bSMatt Spinler         {
327c2f84c7bSMatt Spinler             lg2::info("Could not restore property ${p['prop']} on ${object}, setting to default value");
328c2f84c7bSMatt Spinler             ${p['prop']} = ${get_default_value(object, p['iface'], p['prop'])};
329c2f84c7bSMatt Spinler         }
330db838626SDeepak Kodihalli     % endfor
331c2f84c7bSMatt Spinler     }
332c0ce992fSLei YU % endif
333db838626SDeepak Kodihalli <% props = [] %>
334db838626SDeepak Kodihalli % for index, item in enumerate(settingsDict[object]):
335db838626SDeepak Kodihalli   % for  prop, metaDict in item['Properties'].items():
336db838626SDeepak Kodihalli <%
337bcf95781SPatrick Williams     t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
338db838626SDeepak Kodihalli %>\
3397a6f2526SDeepak Kodihalli     ${t};
3407a6f2526SDeepak Kodihalli   % endfor
341db838626SDeepak Kodihalli % endfor
3427a6f2526SDeepak Kodihalli }
3437a6f2526SDeepak Kodihalli 
3447a6f2526SDeepak Kodihalli % for n in reversed(ns):
3457a6f2526SDeepak Kodihalli } // namespace ${n}
3467a6f2526SDeepak Kodihalli % endfor
347db838626SDeepak Kodihalli 
3487a6f2526SDeepak Kodihalli % endfor
3497a6f2526SDeepak Kodihalli 
3505de0957cSDeepak Kodihalli /** @class Manager
3515de0957cSDeepak Kodihalli  *
3525de0957cSDeepak Kodihalli  *  @brief Compose settings objects and put them on the bus.
3535de0957cSDeepak Kodihalli  */
3545de0957cSDeepak Kodihalli class Manager
3555de0957cSDeepak Kodihalli {
3565de0957cSDeepak Kodihalli     public:
3575de0957cSDeepak Kodihalli         Manager() = delete;
3585de0957cSDeepak Kodihalli         Manager(const Manager&) = delete;
3595de0957cSDeepak Kodihalli         Manager& operator=(const Manager&) = delete;
3605de0957cSDeepak Kodihalli         Manager(Manager&&) = delete;
3615de0957cSDeepak Kodihalli         Manager& operator=(Manager&&) = delete;
3625de0957cSDeepak Kodihalli         virtual ~Manager() = default;
3635de0957cSDeepak Kodihalli 
3645de0957cSDeepak Kodihalli         /** @brief Constructor to put settings objects on to the bus.
3655de0957cSDeepak Kodihalli          *  @param[in] bus - Bus to attach to.
3665de0957cSDeepak Kodihalli          */
3677c4181cfSPatrick Williams         explicit Manager(sdbusplus::bus_t& bus) :
3680f6903dbSPatrick Williams             settings(
3695de0957cSDeepak Kodihalli                 std::make_tuple(
370db838626SDeepak Kodihalli % for index, path in enumerate(objects):
371db838626SDeepak Kodihalli <% type = get_setting_type(path) + "::Impl" %>\
3725de0957cSDeepak Kodihalli                     std::make_unique<${type}>(
3735de0957cSDeepak Kodihalli                         bus,
3745de0957cSDeepak Kodihalli   % if index < len(settingsDict) - 1:
375db838626SDeepak Kodihalli                         "${path}"),
3765de0957cSDeepak Kodihalli   % else:
3770f6903dbSPatrick Williams                         "${path}")
3785de0957cSDeepak Kodihalli   % endif
3795de0957cSDeepak Kodihalli % endfor
3800f6903dbSPatrick Williams                 )
3810f6903dbSPatrick Williams             )
3820f6903dbSPatrick Williams         {
383db838626SDeepak Kodihalli % for index, path in enumerate(objects):
3844636e07cSTom Joseph             auto initSetting${index} = [&]()
3857a6f2526SDeepak Kodihalli             {
386db838626SDeepak Kodihalli   % for item in settingsDict[path]:
387db838626SDeepak Kodihalli     % for propName, metaDict in item['Properties'].items():
388bcf95781SPatrick Williams <% p = NamedElement(name=propName).camelCase %>\
389ffdf8658SMatt Spinler <% defaultValue = get_default_value(path, item['Interface'], propName) %>\
3905de0957cSDeepak Kodihalli                 std::get<${index}>(settings)->
391db838626SDeepak Kodihalli                   ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
3925de0957cSDeepak Kodihalli   % endfor
393db838626SDeepak Kodihalli % endfor
3944636e07cSTom Joseph             };
3954636e07cSTom Joseph 
3964636e07cSTom Joseph             try
3974636e07cSTom Joseph             {
398fb1ad7ccSMatt Spinler                 if (std::get<${index}>(settings)->deserialize())
3994636e07cSTom Joseph                 {
400fb1ad7ccSMatt Spinler                     /* Update the archive to use name/value pairs if it isn't. */
401fb1ad7ccSMatt Spinler                     if (std::get<${index}>(settings)->getInitialVersion() < CLASS_VERSION_WITH_NVP)
402fb1ad7ccSMatt Spinler                     {
403fb1ad7ccSMatt Spinler                         std::get<${index}>(settings)->serialize();
404fb1ad7ccSMatt Spinler                     }
4054636e07cSTom Joseph                 }
4064636e07cSTom Joseph                 else
4074636e07cSTom Joseph                 {
4084636e07cSTom Joseph                     initSetting${index}();
4094636e07cSTom Joseph                 }
4104636e07cSTom Joseph             }
411b6fa9bb1SPatrick Williams             catch (const cereal::Exception& e)
4124636e07cSTom Joseph             {
413*e568fcadSMatt Spinler                 lg2::error("Cereal exception on ${path}: {ERROR}", "ERROR", e);
414fb1ad7ccSMatt Spinler                 std::get<${index}>(settings)->removeFile();
4154636e07cSTom Joseph                 initSetting${index}();
416db838626SDeepak Kodihalli             }
4177a6f2526SDeepak Kodihalli             std::get<${index}>(settings)->emit_object_added();
4185de0957cSDeepak Kodihalli 
4195de0957cSDeepak Kodihalli % endfor
4205de0957cSDeepak Kodihalli         }
4215de0957cSDeepak Kodihalli 
4225de0957cSDeepak Kodihalli     private:
4235de0957cSDeepak Kodihalli         /* @brief Composition of settings objects. */
4245de0957cSDeepak Kodihalli         std::tuple<
425db838626SDeepak Kodihalli % for index, path in enumerate(objects):
426db838626SDeepak Kodihalli <% type = get_setting_type(path) + "::Impl" %>\
4275de0957cSDeepak Kodihalli   % if index < len(settingsDict) - 1:
4285de0957cSDeepak Kodihalli             std::unique_ptr<${type}>,
4295de0957cSDeepak Kodihalli   % else:
4305de0957cSDeepak Kodihalli             std::unique_ptr<${type}>> settings;
4315de0957cSDeepak Kodihalli   % endif
4325de0957cSDeepak Kodihalli % endfor
4335de0957cSDeepak Kodihalli };
4345de0957cSDeepak Kodihalli 
4355de0957cSDeepak Kodihalli } // namespace settings
4365de0957cSDeepak Kodihalli } // namespace phosphor
437a29a3eb7SVishwanatha Subbanna 
438a29a3eb7SVishwanatha Subbanna // Now register the class version with Cereal
439a29a3eb7SVishwanatha Subbanna % for object in objects:
440a29a3eb7SVishwanatha Subbanna <%
441a29a3eb7SVishwanatha Subbanna    classname = "phosphor::settings"
442a29a3eb7SVishwanatha Subbanna    ns = object.split('/')
443a29a3eb7SVishwanatha Subbanna    ns.pop(0)
444a29a3eb7SVishwanatha Subbanna %>\
445a29a3eb7SVishwanatha Subbanna % for n in ns:
446a29a3eb7SVishwanatha Subbanna <%
447a29a3eb7SVishwanatha Subbanna     classname += "::" + n
448a29a3eb7SVishwanatha Subbanna %>\
449a29a3eb7SVishwanatha Subbanna % endfor
450a29a3eb7SVishwanatha Subbanna CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
451a29a3eb7SVishwanatha Subbanna % endfor
452