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