| #include "config.h" |
| |
| #include "elog_serialize.hpp" |
| |
| #include <cereal/archives/binary.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.additionalData(), |
| 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::vector<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)) |
| { |
| a(id, severity, timestamp, message, additionalData, associations, |
| resolved); |
| updateTimestamp = timestamp; |
| } |
| else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_UPDATE_TS)) |
| { |
| a(id, severity, timestamp, message, additionalData, associations, |
| resolved, fwVersion); |
| updateTimestamp = timestamp; |
| } |
| else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_EVENTID)) |
| { |
| a(id, severity, timestamp, message, additionalData, associations, |
| resolved, fwVersion, updateTimestamp); |
| } |
| else if (version < std::stoul(FIRST_CEREAL_CLASS_VERSION_WITH_RESOLUTION)) |
| { |
| a(id, severity, timestamp, message, additionalData, associations, |
| resolved, fwVersion, updateTimestamp, eventId); |
| } |
| 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.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 |