|  | #include "config.h" | 
|  |  | 
|  | #include "elog_serialize.hpp" | 
|  |  | 
|  | #include <cereal/archives/binary.hpp> | 
|  | #include <cereal/types/map.hpp> | 
|  | #include <cereal/types/string.hpp> | 
|  | #include <cereal/types/tuple.hpp> | 
|  | #include <cereal/types/vector.hpp> | 
|  | #include <phosphor-logging/lg2.hpp> | 
|  |  | 
|  | #include <fstream> | 
|  |  | 
|  | // Register class version | 
|  | // From cereal documentation; | 
|  | // "This macro should be placed at global scope" | 
|  | CEREAL_CLASS_VERSION(phosphor::logging::Entry, CLASS_VERSION) | 
|  |  | 
|  | namespace phosphor | 
|  | { | 
|  | namespace logging | 
|  | { | 
|  |  | 
|  | /** @brief Function required by Cereal to perform serialization. | 
|  | *  @tparam Archive - Cereal archive type (binary in our case). | 
|  | *  @param[in] a       - reference to Cereal archive. | 
|  | *  @param[in] e       - const reference to error entry. | 
|  | *  @param[in] version - Class version that enables handling | 
|  | *                       a serialized data across code levels | 
|  | */ | 
|  | template <class Archive> | 
|  | void save(Archive& a, const Entry& e, const std::uint32_t /*version*/) | 
|  | { | 
|  | a(e.id(), e.severity(), e.timestamp(), e.message(), e.additionalData2(), | 
|  | e.associations(), e.resolved(), e.version(), e.updateTimestamp(), | 
|  | e.eventId(), e.resolution()); | 
|  | } | 
|  |  | 
|  | /** @brief Function required by Cereal to perform deserialization. | 
|  | *  @tparam Archive - Cereal archive type (binary in our case). | 
|  | *  @param[in] a       - reference to Cereal archive. | 
|  | *  @param[in] e       - reference to error entry. | 
|  | *  @param[in] version - Class version that enables handling | 
|  | *                       a serialized data across code levels | 
|  | */ | 
|  | template <class Archive> | 
|  | void load(Archive& a, Entry& e, const std::uint32_t version) | 
|  | { | 
|  | using namespace sdbusplus::server::xyz::openbmc_project::logging; | 
|  |  | 
|  | uint32_t id{}; | 
|  | Entry::Level severity{}; | 
|  | uint64_t timestamp{}; | 
|  | std::string message{}; | 
|  | std::map<std::string, std::string> additionalData{}; | 
|  | bool resolved{}; | 
|  | AssociationList associations{}; | 
|  | std::string fwVersion{}; | 
|  | uint64_t updateTimestamp{}; | 
|  | std::string eventId{}; | 
|  | std::string resolution{}; | 
|  |  | 
|  | if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_FWLEVEL)) | 
|  | { | 
|  | std::vector<std::string> additionalData_old{}; | 
|  | a(id, severity, timestamp, message, additionalData_old, associations, | 
|  | resolved); | 
|  | updateTimestamp = timestamp; | 
|  | additionalData = util::additional_data::parse(additionalData_old); | 
|  | } | 
|  | else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_UPDATE_TS)) | 
|  | { | 
|  | std::vector<std::string> additionalData_old{}; | 
|  | a(id, severity, timestamp, message, additionalData_old, associations, | 
|  | resolved, fwVersion); | 
|  | updateTimestamp = timestamp; | 
|  | additionalData = util::additional_data::parse(additionalData_old); | 
|  | } | 
|  | else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_EVENTID)) | 
|  | { | 
|  | std::vector<std::string> additionalData_old{}; | 
|  | a(id, severity, timestamp, message, additionalData_old, associations, | 
|  | resolved, fwVersion, updateTimestamp); | 
|  | additionalData = util::additional_data::parse(additionalData_old); | 
|  | } | 
|  | else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_RESOLUTION)) | 
|  | { | 
|  | std::vector<std::string> additionalData_old{}; | 
|  | a(id, severity, timestamp, message, additionalData_old, associations, | 
|  | resolved, fwVersion, updateTimestamp, eventId); | 
|  | additionalData = util::additional_data::parse(additionalData_old); | 
|  | } | 
|  | else if (version < | 
|  | std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_METADATA_DICT)) | 
|  | { | 
|  | std::vector<std::string> additionalData_old{}; | 
|  | a(id, severity, timestamp, message, additionalData_old, associations, | 
|  | resolved, fwVersion, updateTimestamp, eventId, resolution); | 
|  | additionalData = util::additional_data::parse(additionalData_old); | 
|  | } | 
|  | else | 
|  | { | 
|  | a(id, severity, timestamp, message, additionalData, associations, | 
|  | resolved, fwVersion, updateTimestamp, eventId, resolution); | 
|  | } | 
|  |  | 
|  | e.id(id, true); | 
|  | e.severity(severity, true); | 
|  | e.timestamp(timestamp, true); | 
|  | e.message(message, true); | 
|  | e.additionalData(additionalData, true); | 
|  | e.additionalData2(additionalData, true); | 
|  | e.sdbusplus::server::xyz::openbmc_project::logging::Entry::resolved( | 
|  | resolved, true); | 
|  | e.associations(associations, true); | 
|  | e.version(fwVersion, true); | 
|  | e.purpose(sdbusplus::server::xyz::openbmc_project::software::Version:: | 
|  | VersionPurpose::BMC, | 
|  | true); | 
|  | e.updateTimestamp(updateTimestamp, true); | 
|  | e.eventId(eventId, true); | 
|  | e.resolution(resolution, true); | 
|  | } | 
|  |  | 
|  | fs::path getEntrySerializePath(uint32_t id, const fs::path& dir) | 
|  | { | 
|  | return dir / std::to_string(id); | 
|  | } | 
|  |  | 
|  | fs::path serialize(const Entry& e, const fs::path& dir) | 
|  | { | 
|  | auto path = getEntrySerializePath(e.id(), dir); | 
|  | std::ofstream os(path.c_str(), std::ios::binary); | 
|  | cereal::BinaryOutputArchive oarchive(os); | 
|  | oarchive(e); | 
|  | return path; | 
|  | } | 
|  |  | 
|  | bool deserialize(const fs::path& path, Entry& e) | 
|  | { | 
|  | try | 
|  | { | 
|  | if (fs::exists(path)) | 
|  | { | 
|  | std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); | 
|  | cereal::BinaryInputArchive iarchive(is); | 
|  | iarchive(e); | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  | catch (const cereal::Exception& ex) | 
|  | { | 
|  | lg2::error("{EXCEPTION}", "EXCEPTION", ex); | 
|  | fs::remove(path); | 
|  | return false; | 
|  | } | 
|  | catch (const std::length_error& ex) | 
|  | { | 
|  | // Running into: USCiLab/cereal#192 | 
|  | // This may be indicating some other issue in the | 
|  | // way vector may have been used inside the logging. | 
|  | // possibly associations ??. But handling it here for | 
|  | // now since we are anyway tossing the log | 
|  | // TODO: openbmc/phosphor-logging#8 | 
|  | lg2::error("{EXCEPTION}", "EXCEPTION", ex); | 
|  | fs::remove(path); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace logging | 
|  | } // namespace phosphor |