1 #include "config.h"
2
3 #include "event_serialize.hpp"
4
5 #include <cereal/archives/binary.hpp>
6 #include <cereal/types/string.hpp>
7 #include <cereal/types/vector.hpp>
8 #include <phosphor-logging/lg2.hpp>
9
10 #include <fstream>
11
12 // Register class version
13 // From cereal documentation;
14 // "This macro should be placed at global scope"
15 CEREAL_CLASS_VERSION(phosphor::events::Entry, CLASS_VERSION);
16
17 namespace phosphor
18 {
19 namespace events
20 {
21
22 /** @brief Function required by Cereal to perform serialization.
23 * @tparam Archive - Cereal archive type (binary in our case).
24 * @param[in] archive - reference to Cereal archive.
25 * @param[in] event - const reference to event entry.
26 * @param[in] version - Class version that enables handling
27 * a serialized data across code levels
28 */
29 template <class Archive>
save(Archive & archive,const Entry & event,const std::uint32_t)30 void save(Archive& archive, const Entry& event,
31 const std::uint32_t /* version */)
32 {
33 archive(event.timestamp(), event.message(), event.additionalData());
34 }
35
36 /** @brief Function required by Cereal to perform deserialization.
37 * @tparam Archive - Cereal archive type (binary in our case).
38 * @param[in] archive - reference to Cereal archive.
39 * @param[in] event - reference to event entry.
40 * @param[in] version - Class version that enables handling
41 * a serialized data across code levels
42 */
43 template <class Archive>
load(Archive & archive,Entry & event,const std::uint32_t)44 void load(Archive& archive, Entry& event, const std::uint32_t /* version */)
45 {
46 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
47
48 uint64_t timestamp{};
49 std::string message{};
50 std::vector<std::string> additionalData{};
51
52 archive(timestamp, message, additionalData);
53
54 event.timestamp(timestamp);
55 event.message(message);
56 event.additionalData(additionalData);
57 }
58
serialize(const Entry & event,const std::string & eventName)59 fs::path serialize(const Entry& event, const std::string& eventName)
60 {
61 fs::path dir(EVENTS_PERSIST_PATH);
62 auto path = dir / eventName;
63 fs::create_directories(path);
64 path /= std::to_string(event.timestamp());
65 std::ofstream os(path.string(), std::ios::binary);
66 cereal::BinaryOutputArchive oarchive(os);
67 oarchive(event);
68 return path;
69 }
70
deserialize(const fs::path & path,Entry & event)71 bool deserialize(const fs::path& path, Entry& event)
72 {
73 try
74 {
75 if (fs::exists(path))
76 {
77 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
78 cereal::BinaryInputArchive iarchive(is);
79 iarchive(event);
80 return true;
81 }
82 return false;
83 }
84 catch (const cereal::Exception& e)
85 {
86 lg2::error("Failed to deserialize: {ERROR}", "ERROR", e);
87 std::error_code ec;
88 fs::remove(path, ec);
89 return false;
90 }
91 catch (const fs::filesystem_error& e)
92 {
93 return false;
94 }
95 }
96
97 } // namespace events
98 } // namespace phosphor
99