Implement Report persistency
Now Report properties are stored in non-volatile memory. It allows
to restore Report after system restart. Persistency of a report is
controlled by Persistency property in Report interface.
Tested:
- Passed unit tests
- Verified that report is stored in /var/lib/telemetry dir
- Verified that report is restored from storage after telemetry
service start
Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
Change-Id: Iccfe21603eecffc4e174a4403f699b03de320db9
diff --git a/src/utils/labeled_tuple.hpp b/src/utils/labeled_tuple.hpp
new file mode 100644
index 0000000..7e75322
--- /dev/null
+++ b/src/utils/labeled_tuple.hpp
@@ -0,0 +1,117 @@
+#pragma once
+
+#include <nlohmann/json.hpp>
+#include <sdbusplus/message/types.hpp>
+
+namespace utils
+{
+
+inline void from_json(const nlohmann::json& j,
+ sdbusplus::message::object_path& o)
+{
+ o = j.get<std::string>();
+}
+
+inline void from_json(const nlohmann::json& j,
+ std::vector<sdbusplus::message::object_path>& o)
+{
+ o.clear();
+ for (const nlohmann::json& item : j)
+ {
+ o.emplace_back(item.get<std::string>());
+ }
+}
+
+namespace detail
+{
+
+template <class T>
+struct has_utils_from_json
+{
+ template <class U>
+ static U& ref();
+
+ template <class U>
+ static std::true_type check(
+ decltype(utils::from_json(ref<const nlohmann::json>(), ref<U>()))*);
+
+ template <class>
+ static std::false_type check(...);
+
+ static constexpr bool value =
+ decltype(check<std::decay_t<T>>(nullptr))::value;
+};
+
+template <class T>
+constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value;
+
+} // namespace detail
+
+template <class, class...>
+struct LabeledTuple;
+
+template <class... Args, class... Labels>
+struct LabeledTuple<std::tuple<Args...>, Labels...>
+{
+ LabeledTuple() = delete;
+
+ static_assert(sizeof...(Args) == sizeof...(Labels));
+
+ static nlohmann::json to_json(const std::tuple<Args...>& tuple)
+ {
+ nlohmann::json j;
+ to_json_all(j, tuple, std::make_index_sequence<sizeof...(Args)>());
+ return j;
+ }
+
+ static std::tuple<Args...> from_json(const nlohmann::json& j)
+ {
+ std::tuple<Args...> value;
+ from_json_all(j, value, std::make_index_sequence<sizeof...(Args)>());
+ return value;
+ }
+
+ private:
+ template <size_t... Idx>
+ static void to_json_all(nlohmann::json& j, const std::tuple<Args...>& tuple,
+ std::index_sequence<Idx...>)
+ {
+ (to_json_item<Idx>(j, tuple), ...);
+ }
+
+ template <size_t Idx>
+ static void to_json_item(nlohmann::json& j,
+ const std::tuple<Args...>& tuple)
+ {
+ using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
+ j[Label::str()] = std::get<Idx>(tuple);
+ }
+
+ template <size_t... Idx>
+ static void from_json_all(const nlohmann::json& j,
+ std::tuple<Args...>& value,
+ std::index_sequence<Idx...>)
+ {
+ (from_json_item<Idx>(j, value), ...);
+ }
+
+ template <size_t Idx>
+ static void from_json_item(const nlohmann::json& j,
+ std::tuple<Args...>& value)
+ {
+ using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
+ using T = std::tuple_element_t<Idx, std::tuple<Args...>>;
+ const nlohmann::json& item = j.at(Label::str());
+ if constexpr (detail::has_utils_from_json_v<T>)
+ {
+ T& v = std::get<Idx>(value);
+ utils::from_json(item, v);
+ }
+ else
+ {
+ std::get<Idx>(value) = item.get<T>();
+ }
+ }
+};
+
+} // namespace utils
diff --git a/src/utils/transform.hpp b/src/utils/transform.hpp
new file mode 100644
index 0000000..b354b0f
--- /dev/null
+++ b/src/utils/transform.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <algorithm>
+#include <iterator>
+
+namespace utils
+{
+namespace detail
+{
+
+template <class T>
+struct has_member_reserve
+{
+ template <class U>
+ static U& ref();
+
+ template <class U>
+ static std::true_type check(decltype(ref<U>().reserve(size_t{}))*);
+
+ template <class>
+ static std::false_type check(...);
+
+ static constexpr bool value =
+ decltype(check<std::decay_t<T>>(nullptr))::value;
+};
+
+template <class T>
+constexpr bool has_member_reserve_v = has_member_reserve<T>::value;
+
+} // namespace detail
+
+template <template <class, class...> class Container, class T, class... Args,
+ class F>
+auto transform(const Container<T, Args...>& container, F&& functor)
+{
+ using R = decltype(functor(*container.begin()));
+
+ Container<R> result;
+ if constexpr (detail::has_member_reserve_v<Container<T, Args...>>)
+ {
+ result.reserve(container.size());
+ }
+ std::transform(container.begin(), container.end(),
+ std::inserter(result, result.end()),
+ std::forward<F>(functor));
+ return result;
+}
+
+} // namespace utils
diff --git a/src/utils/tstring.hpp b/src/utils/tstring.hpp
new file mode 100644
index 0000000..7fcddb3
--- /dev/null
+++ b/src/utils/tstring.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <array>
+#include <string>
+
+namespace utils
+{
+namespace literals
+{
+
+constexpr char id[] = "id";
+constexpr char sensorPaths[] = "sensorPaths";
+constexpr char operationType[] = "operationType";
+constexpr char metricMetadata[] = "metricMetadata";
+
+} // namespace literals
+
+template <const char* const V>
+struct Label
+{
+ static std::string str()
+ {
+ return V;
+ }
+};
+
+namespace tstring
+{
+
+using Id = utils::Label<utils::literals::id>;
+using SensorPaths = utils::Label<utils::literals::sensorPaths>;
+using OperationType = utils::Label<utils::literals::operationType>;
+using MetricMetadata = utils::Label<utils::literals::metricMetadata>;
+
+} // namespace tstring
+} // namespace utils