blob: 55a99ca212cc8ba422588450f203109971673034 [file] [log] [blame]
Deepak Kodihalli5de09572017-05-16 23:53:40 -05001## 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!
Deepak Kodihalli5de09572017-05-16 23:53:40 -05004<%
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -05005import re
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -05006from collections import defaultdict
Patrick Williamsbcf95782021-05-05 16:20:32 -05007from sdbusplus.namedelement import NamedElement
Patrick Williams2b7152f2020-04-02 07:18:32 -05008objects = settingsDict.keys()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -05009sdbusplus_includes = []
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050010props = defaultdict(list)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050011validators = defaultdict(tuple)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050012
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050013def get_setting_sdbusplus_type(setting_intf):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050014 setting = "sdbusplus::" + setting_intf.replace('.', '::')
15 i = setting.rfind('::')
16 setting = setting[:i] + '::server::' + setting[i+2:]
17 return setting
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050018
Deepak Kodihallidb838622017-08-27 02:46:47 -050019def get_setting_type(path):
20 path = path[1:]
21 path = path.replace('/', '::')
22 return path
Matt Spinlerffdf8652023-05-24 11:09:54 -050023
24def get_default_value(object, interface, prop):
25 default_value = None
26 for item in settingsDict[object]:
27 if item['Interface'] == interface:
28 default_value = item['Properties'][prop]['Default']
29 break
30
31 if isinstance(default_value, str) and not \
32 default_value.startswith('"') and '::' in default_value:
33 ns = get_setting_sdbusplus_type(interface)
34 i = ns.rfind('::')
35 default_value = "{}::{}".format(ns[:i], default_value)
36
37 return default_value
Deepak Kodihalli5de09572017-05-16 23:53:40 -050038%>\
39#pragma once
40
41% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050042 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050043<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050044 include = item['Interface']
Deepak Kodihalli5de09572017-05-16 23:53:40 -050045 include = include.replace('.', '/')
46 include = include + "/server.hpp"
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050047 sdbusplus_includes.append(include)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050048%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050049 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050050% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050051#include <cereal/archives/json.hpp>
James Feist74e3be72019-02-15 09:59:42 -080052#include <cereal/types/vector.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050053#include <fstream>
54#include <utility>
Patrick Williams6306e5e2022-06-16 17:14:54 -050055#include <filesystem>
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050056#include <regex>
57#include <phosphor-logging/elog.hpp>
58#include <phosphor-logging/elog-errors.hpp>
59#include <phosphor-logging/log.hpp>
Matt Spinlerc2f84c72023-05-24 13:51:03 -050060#include <phosphor-logging/lg2.hpp>
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050061#include <xyz/openbmc_project/Common/error.hpp>
Tom Joseph4636e072017-09-24 20:47:24 +053062using namespace phosphor::logging;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050063
Jagpal Singh Gill4d28bcd2023-04-23 23:34:05 -070064/* The DBus busname to own */
65#define SETTINGS_BUSNAME "xyz.openbmc_project.Settings"
66/* Path of directory housing persisted settings */
67#define SETTINGS_PERSIST_PATH "/var/lib/phosphor-settings-manager/settings"
68
69/* Class version to register with Cereal */
Matt Spinlerc2f84c72023-05-24 13:51:03 -050070static constexpr size_t CLASS_VERSION = 2;
71static constexpr size_t CLASS_VERSION_WITH_NVP = 2;
Jagpal Singh Gill4d28bcd2023-04-23 23:34:05 -070072
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050073% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050074#include "${i}"
75% endfor
76
Deepak Kodihalli5de09572017-05-16 23:53:40 -050077namespace phosphor
78{
79namespace settings
80{
81
Patrick Williams6306e5e2022-06-16 17:14:54 -050082namespace fs = std::filesystem;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050083
Deepak Kodihalli242bc772017-08-04 02:47:54 -050084namespace persistent
85{
86
87// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
88// same path. This eases re-construction of settings objects when we restore
89// from the filesystem. This can be a problem though when you have two objects
90// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
91// a file in the first case, and a subdir in the second. To solve this, suffix
92// files with a trailing __. The __ is a safe character sequence to use, because
93// we won't have d-bus object paths ending with this.
94// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
95constexpr auto fileSuffix = "__";
96
97}
98
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -050099static fs::path getFilePath(const fs::path& objectPath)
100{
101 fs::path p(SETTINGS_PERSIST_PATH);
102 p /= objectPath.relative_path();
103 p += persistent::fileSuffix;
104 return p;
105}
106
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500107% for object in objects:
108<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500109 ns = object.split('/')
110 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500111%>\
112% for n in ns:
113namespace ${n}
114{
115% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500116<%
117 interfaces = []
118 aliases = []
119 for item in settingsDict[object]:
120 interfaces.append(item['Interface'])
121 for name, meta in item['Properties'].items():
122 if 'Validation' in meta:
123 dict = meta['Validation']
124 if dict['Type'] == "range":
125 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
126 else:
127 validators[name] = (dict['Type'], dict['Validator'])
128%>
129% for index, intf in enumerate(interfaces):
130using Iface${index} = ${get_setting_sdbusplus_type(intf)};
131<% aliases.append("Iface" + str(index)) %>\
132% endfor
133<%
Patrick Williams7c4181c2022-07-22 19:26:52 -0500134 parent = "sdbusplus::server::object_t" + "<" + ", ".join(aliases) + ">"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500135%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500136using Parent = ${parent};
137
138class Impl : public Parent
139{
140 public:
Patrick Williams7c4181c2022-07-22 19:26:52 -0500141 Impl(sdbusplus::bus_t& bus, const char* path):
Patrick Williams74c4f3b2022-04-05 16:16:20 -0500142 Parent(bus, path, Parent::action::defer_emit),
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500143 path(path)
144 {
145 }
146 virtual ~Impl() = default;
147
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500148 void setInitialVersion(std::uint32_t v)
149 {
150 initialVersion = v;
151 }
152
153 std::uint32_t getInitialVersion() const
154 {
155 return initialVersion;
156 }
157
158 bool deserialize()
159 {
160 auto p = getFilePath(path);
161 if (fs::exists(p))
162 {
163 std::ifstream is(p.c_str(), std::ios::in);
164 cereal::JSONInputArchive iarchive(is);
165 iarchive(*this);
166 return true;
167 }
168 return false;
169 }
170
171 void serialize()
172 {
173 auto p = getFilePath(path);
174 if (!fs::exists(p.parent_path()))
175 {
176 fs::create_directories(p.parent_path());
177 }
178 std::ofstream os(p.c_str(), std::ios::binary);
179 cereal::JSONOutputArchive oarchive(os);
180 oarchive(*this);
181 }
182
183 void removeFile() const
184 {
185 std::error_code ec;
186 fs::remove(getFilePath(path), ec);
187 }
188
Deepak Kodihallidb838622017-08-27 02:46:47 -0500189% for index, item in enumerate(settingsDict[object]):
190 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500191<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500192<% fname = "validate" + propName %>\
193 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500194 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500195 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500196 if (value != result)
197 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500198 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500199 if (!${fname}(value))
200 {
201 namespace error =
202 sdbusplus::xyz::openbmc_project::Common::Error;
203 namespace metadata =
204 phosphor::logging::xyz::openbmc_project::Common;
205 phosphor::logging::report<error::InvalidArgument>(
206 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500207 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500208 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
209 % else:
210 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
211 % endif
212 return result;
213 }
214 % endif
Deepak Kodihallidb838622017-08-27 02:46:47 -0500215 result = Iface${index}::${t}(value);
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500216 serialize();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500217 }
218 return result;
219 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500220 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500221
Deepak Kodihallidb838622017-08-27 02:46:47 -0500222 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500223% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500224 private:
225 fs::path path;
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500226 std::uint32_t initialVersion = 0;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500227% for index, item in enumerate(settingsDict[object]):
228 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500229<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500230<% fname = "validate" + propName %>\
231 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500232
Deepak Kodihallidb838622017-08-27 02:46:47 -0500233 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500234 {
235 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500236 % if (validators[propName][0] == 'regex'):
237 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500238 matched = std::regex_search(value, regexToCheck);
239 if (!matched)
240 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500241 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500242 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500243 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500244 using namespace phosphor::logging;
245 log<level::ERR>(err.c_str());
246 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500247 % elif (validators[propName][0] == 'range'):
248<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700249 % if lowhigh[0] == '0':
250 if (value <= ${lowhigh[1]})
251 % else:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500252 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700253 % endif
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500254 {
255 matched = true;
256 }
257 else
258 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500259 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500260 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500261 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500262 using namespace phosphor::logging;
263 log<level::ERR>(err.c_str());
264 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500265 % else:
266 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500267 % endif
268 return matched;
269 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500270 % endif
271 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500272% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500273};
274
275template<class Archive>
276void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530277 const Impl& setting,
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700278 [[maybe_unused]] const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500279{
280<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500281props = []
282for index, item in enumerate(settingsDict[object]):
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500283 props.extend(item['Properties'].keys())
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500284%>\
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500285## Since the iface isn't saved, property names need to be unique on
286## the object path. This could be supported by providing unique
287## field names to make_nvp() if ever necessary.
288% if len(set(props)) != len(props):
289#error Duplicate property names on object path ${object}
290%endif
291<%
292args = []
293for prop in props:
294 t = "setting." + NamedElement(name=prop).camelCase + "()"
295 args.append(f"cereal::make_nvp(\"{prop}\", {t})")
296args = ", ".join(args)
297%>\
298 a(${args});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500299}
300
301template<class Archive>
302void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530303 Impl& setting,
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500304 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500305{
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500306 setting.setInitialVersion(version);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500307<%
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500308props = []
309for index, item in enumerate(settingsDict[object]):
310 for prop in item['Properties'].keys():
311 t = "setting." + NamedElement(name=prop).camelCase + "()"
312 props.append({'prop' : prop, 'iface': item['Interface'], 'func': t})
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500313%>\
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500314% for p in props:
315 decltype(${p['func']}) ${p['prop']}{};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500316% endfor
Matt Spinlerc2f84c72023-05-24 13:51:03 -0500317<% propList = ', '.join([p['prop'] for p in props]) %>
318% if propList:
319 if (version < CLASS_VERSION_WITH_NVP)
320 {
321 a(${propList});
322 }
323 else
324 {
325 % for p in props:
326 try
327 {
328 a(CEREAL_NVP(${p['prop']}));
329 }
330 catch (const cereal::Exception& e)
331 {
332 lg2::info("Could not restore property ${p['prop']} on ${object}, setting to default value");
333 ${p['prop']} = ${get_default_value(object, p['iface'], p['prop'])};
334 }
335 % endfor
336 }
Lei YUc0ce9922022-03-09 16:01:10 +0800337% endif
Deepak Kodihallidb838622017-08-27 02:46:47 -0500338<% props = [] %>
339% for index, item in enumerate(settingsDict[object]):
340 % for prop, metaDict in item['Properties'].items():
341<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500342 t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500343%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500344 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500345 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500346% endfor
347}
348
349% for n in reversed(ns):
350} // namespace ${n}
351% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500352
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500353% endfor
354
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500355/** @class Manager
356 *
357 * @brief Compose settings objects and put them on the bus.
358 */
359class Manager
360{
361 public:
362 Manager() = delete;
363 Manager(const Manager&) = delete;
364 Manager& operator=(const Manager&) = delete;
365 Manager(Manager&&) = delete;
366 Manager& operator=(Manager&&) = delete;
367 virtual ~Manager() = default;
368
369 /** @brief Constructor to put settings objects on to the bus.
370 * @param[in] bus - Bus to attach to.
371 */
Patrick Williams7c4181c2022-07-22 19:26:52 -0500372 explicit Manager(sdbusplus::bus_t& bus) :
Patrick Williams0f6903d2022-04-15 10:03:58 -0500373 settings(
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500374 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500375% for index, path in enumerate(objects):
376<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500377 std::make_unique<${type}>(
378 bus,
379 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500380 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500381 % else:
Patrick Williams0f6903d2022-04-15 10:03:58 -0500382 "${path}")
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500383 % endif
384% endfor
Patrick Williams0f6903d2022-04-15 10:03:58 -0500385 )
386 )
387 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500388% for index, path in enumerate(objects):
Tom Joseph4636e072017-09-24 20:47:24 +0530389 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500390 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500391 % for item in settingsDict[path]:
392 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500393<% p = NamedElement(name=propName).camelCase %>\
Matt Spinlerffdf8652023-05-24 11:09:54 -0500394<% defaultValue = get_default_value(path, item['Interface'], propName) %>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500395 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530396 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500397 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530398% endfor
399 };
400
401 try
402 {
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500403 if (std::get<${index}>(settings)->deserialize())
Tom Joseph4636e072017-09-24 20:47:24 +0530404 {
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500405 /* Update the archive to use name/value pairs if it isn't. */
406 if (std::get<${index}>(settings)->getInitialVersion() < CLASS_VERSION_WITH_NVP)
407 {
408 std::get<${index}>(settings)->serialize();
409 }
Tom Joseph4636e072017-09-24 20:47:24 +0530410 }
411 else
412 {
413 initSetting${index}();
414 }
415 }
Patrick Williamsb6fa9bb2021-10-06 12:27:57 -0500416 catch (const cereal::Exception& e)
Tom Joseph4636e072017-09-24 20:47:24 +0530417 {
418 log<level::ERR>(e.what());
Matt Spinlerfb1ad7c2023-05-24 14:28:29 -0500419 std::get<${index}>(settings)->removeFile();
Tom Joseph4636e072017-09-24 20:47:24 +0530420 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500421 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500422 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500423
424% endfor
425 }
426
427 private:
428 /* @brief Composition of settings objects. */
429 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500430% for index, path in enumerate(objects):
431<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500432 % if index < len(settingsDict) - 1:
433 std::unique_ptr<${type}>,
434 % else:
435 std::unique_ptr<${type}>> settings;
436 % endif
437% endfor
438};
439
440} // namespace settings
441} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530442
443// Now register the class version with Cereal
444% for object in objects:
445<%
446 classname = "phosphor::settings"
447 ns = object.split('/')
448 ns.pop(0)
449%>\
450% for n in ns:
451<%
452 classname += "::" + n
453%>\
454% endfor
455CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
456% endfor