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/log.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 using namespace phosphor::logging;
23 
24 /** @brief Function required by Cereal to perform serialization.
25  *  @tparam Archive - Cereal archive type (binary in our case).
26  *  @param[in] archive - reference to Cereal archive.
27  *  @param[in] event - const reference to event entry.
28  *  @param[in] version - Class version that enables handling
29  *                       a serialized data across code levels
30  */
31 template <class Archive>
32 void save(Archive& archive, const Entry& event, const std::uint32_t version)
33 {
34     archive(event.timestamp(), event.message(), event.additionalData());
35 }
36 
37 /** @brief Function required by Cereal to perform deserialization.
38  *  @tparam Archive - Cereal archive type (binary in our case).
39  *  @param[in] archive - reference to Cereal archive.
40  *  @param[in] event - reference to event entry.
41  *  @param[in] version - Class version that enables handling
42  *                       a serialized data across code levels
43  */
44 template <class Archive>
45 void load(Archive& archive, Entry& event, const std::uint32_t version)
46 {
47     using namespace sdbusplus::xyz::openbmc_project::Logging::server;
48 
49     uint64_t timestamp{};
50     std::string message{};
51     std::vector<std::string> additionalData{};
52 
53     archive(timestamp, message, additionalData);
54 
55     event.timestamp(timestamp);
56     event.message(message);
57     event.additionalData(additionalData);
58 }
59 
60 fs::path serialize(const Entry& event, const std::string& eventName)
61 {
62     fs::path dir(EVENTS_PERSIST_PATH);
63     auto path = dir / eventName;
64     fs::create_directories(path);
65     path /= std::to_string(event.timestamp());
66     std::ofstream os(path.string(), std::ios::binary);
67     cereal::BinaryOutputArchive oarchive(os);
68     oarchive(event);
69     return path;
70 }
71 
72 bool deserialize(const fs::path& path, Entry& event)
73 {
74     try
75     {
76         if (fs::exists(path))
77         {
78             std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
79             cereal::BinaryInputArchive iarchive(is);
80             iarchive(event);
81             return true;
82         }
83         return false;
84     }
85     catch (const cereal::Exception& e)
86     {
87         log<level::ERR>(e.what());
88         std::error_code ec;
89         fs::remove(path, ec);
90         return false;
91     }
92     catch (const fs::filesystem_error& e)
93     {
94         return false;
95     }
96 }
97 
98 } // namespace events
99 } // namespace phosphor
100