1 #include "config.h" 2 3 #include "elog_serialize.hpp" 4 5 #include <cereal/archives/binary.hpp> 6 #include <cereal/types/string.hpp> 7 #include <cereal/types/tuple.hpp> 8 #include <cereal/types/vector.hpp> 9 #include <fstream> 10 #include <phosphor-logging/log.hpp> 11 12 // Register class version 13 // From cereal documentation; 14 // "This macro should be placed at global scope" 15 CEREAL_CLASS_VERSION(phosphor::logging::Entry, CLASS_VERSION); 16 17 namespace phosphor 18 { 19 namespace logging 20 { 21 22 /** @brief Function required by Cereal to perform serialization. 23 * @tparam Archive - Cereal archive type (binary in our case). 24 * @param[in] a - reference to Cereal archive. 25 * @param[in] e - const reference to error 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& a, const Entry& e, const std::uint32_t version) 31 { 32 a(e.id(), e.severity(), e.timestamp(), e.message(), e.additionalData(), 33 e.associations(), e.resolved(), e.version()); 34 } 35 36 /** @brief Function required by Cereal to perform deserialization. 37 * @tparam Archive - Cereal archive type (binary in our case). 38 * @param[in] a - reference to Cereal archive. 39 * @param[in] e - reference to error 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& a, Entry& e, const std::uint32_t version) 45 { 46 using namespace sdbusplus::xyz::openbmc_project::Logging::server; 47 48 uint32_t id{}; 49 Entry::Level severity{}; 50 uint64_t timestamp{}; 51 std::string message{}; 52 std::vector<std::string> additionalData{}; 53 bool resolved{}; 54 AssociationList associations{}; 55 std::string fwVersion{}; 56 57 if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_FWLEVEL)) 58 { 59 a(id, severity, timestamp, message, additionalData, associations, 60 resolved); 61 } 62 else 63 { 64 a(id, severity, timestamp, message, additionalData, associations, 65 resolved, fwVersion); 66 } 67 68 e.id(id); 69 e.severity(severity); 70 e.timestamp(timestamp); 71 e.message(message); 72 e.additionalData(additionalData); 73 e.sdbusplus::xyz::openbmc_project::Logging::server::Entry::resolved( 74 resolved); 75 e.associations(associations); 76 e.version(fwVersion); 77 e.purpose(sdbusplus::xyz::openbmc_project::Software::server::Version:: 78 VersionPurpose::BMC); 79 } 80 81 fs::path serialize(const Entry& e, const fs::path& dir) 82 { 83 auto path = dir / std::to_string(e.id()); 84 std::ofstream os(path.c_str(), std::ios::binary); 85 cereal::BinaryOutputArchive oarchive(os); 86 oarchive(e); 87 return path; 88 } 89 90 bool deserialize(const fs::path& path, Entry& e) 91 { 92 try 93 { 94 if (fs::exists(path)) 95 { 96 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); 97 cereal::BinaryInputArchive iarchive(is); 98 iarchive(e); 99 return true; 100 } 101 return false; 102 } 103 catch (cereal::Exception& e) 104 { 105 log<level::ERR>(e.what()); 106 fs::remove(path); 107 return false; 108 } 109 catch (const std::length_error& e) 110 { 111 // Running into: USCiLab/cereal#192 112 // This may be indicating some other issue in the 113 // way vector may have been used inside the logging. 114 // possibly associations ??. But handling it here for 115 // now since we are anyway tossing the log 116 // TODO: openbmc/phosphor-logging#8 117 log<level::ERR>(e.what()); 118 fs::remove(path); 119 return false; 120 } 121 } 122 123 } // namespace logging 124 } // namespace phosphor 125