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> 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> 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 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 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