diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/event_entry.hpp | 11 | ||||
-rw-r--r-- | src/event_manager.cpp | 58 | ||||
-rw-r--r-- | src/event_manager.hpp | 5 | ||||
-rw-r--r-- | src/event_serialize.cpp | 97 | ||||
-rw-r--r-- | src/event_serialize.hpp | 30 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/test/Makefile.am | 1 |
8 files changed, 203 insertions, 5 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 73ebca8..e5827e6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,9 @@ phosphor_dbus_monitor_SOURCES = \ main.cpp \ propertywatch.cpp \ resolve_errors.cpp \ - event_manager.cpp + event_manager.cpp \ + event_serialize.cpp + phosphor_dbus_monitor_LDADD = \ $(SDBUSPLUS_LIBS) \ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ diff --git a/src/event_entry.hpp b/src/event_entry.hpp index e39f1e2..899e5ec 100644 --- a/src/event_entry.hpp +++ b/src/event_entry.hpp @@ -50,6 +50,17 @@ class Entry : public EntryIface this->emit_object_added(); } + /** @brief Constructor to create an empty event object with only + * timestamp, caller should make a call to emit added signal. + * @param[in] path - Path to attach at. + * @param[in] timestamp - timestamp when the event created. + */ + Entry(const std::string& path, uint64_t eventTimestamp) : + EntryIface(SDBusPlus::getBus(), path.c_str(), true), objectPath(path) + { + timestamp(eventTimestamp); + } + /** @brief Path of Object. */ std::string objectPath; }; diff --git a/src/event_manager.cpp b/src/event_manager.cpp index 6e7d302..57a8478 100644 --- a/src/event_manager.cpp +++ b/src/event_manager.cpp @@ -17,6 +17,7 @@ #include "config.h" #include "event.hpp" #include "event_manager.hpp" +#include "event_serialize.hpp" #include <experimental/filesystem> @@ -66,13 +67,62 @@ void Manager::create(const std::string& eventName, // event. if (eventQueue.size() == MAX_EVENTS) { + fs::path eventPath(EVENTS_PERSIST_PATH); + eventPath /= eventName; + eventPath /= std::to_string(eventQueue.front()->timestamp()); eventQueue.pop(); + std::error_code ec; + fs::remove(eventPath, ec); } - eventQueue.emplace(std::make_unique<Entry>(objPath, - ms, // Milliseconds since 1970 - std::move(msg), - std::move(additionalData))); + auto event = + std::make_unique<Entry>(objPath, + ms, // Milliseconds since 1970 + std::move(msg), std::move(additionalData)); + serialize(*event, eventName); + eventQueue.push(std::move(event)); +} + +void Manager::restore() +{ + if (!fs::exists(EVENTS_PERSIST_PATH) || fs::is_empty(EVENTS_PERSIST_PATH)) + { + return; + } + + for (auto& eventFile : + fs::recursive_directory_iterator(EVENTS_PERSIST_PATH)) + { + if (!fs::is_regular_file(eventFile)) + { + continue; + } + + EventQueue events; + + auto eventPath = eventFile.path().string(); + auto pos1 = eventPath.rfind("/"); + auto pos2 = eventPath.rfind("/", pos1 - 1) + 1; + auto eventName = eventPath.substr(pos2, (pos1 - pos2)); + auto validEvent = false; + auto timestamp = eventFile.path().filename().string(); + auto tsNum = std::stoll(timestamp); + auto objPath = + std::string(OBJ_EVENT) + '/' + eventName + '/' + timestamp; + + auto event = std::make_unique<Entry>(objPath, tsNum); + if (deserialize(eventFile.path(), *event)) + { + event->emit_object_added(); + events.push(std::move(event)); + validEvent = true; + } + + if (validEvent) + { + eventMap[eventName] = std::move(events); + } + } } Manager& getManager() diff --git a/src/event_manager.hpp b/src/event_manager.hpp index a177739..a4ccf18 100644 --- a/src/event_manager.hpp +++ b/src/event_manager.hpp @@ -38,6 +38,11 @@ class Manager const std::string& objectPath, const std::string& propertyName, const std::string& propertyValue); + /** @brief Construct event d-bus objects from their persisted + * representations. + */ + void restore(); + private: using EventName = std::string; /** @brief Queue of events */ diff --git a/src/event_serialize.cpp b/src/event_serialize.cpp new file mode 100644 index 0000000..c7e78d9 --- /dev/null +++ b/src/event_serialize.cpp @@ -0,0 +1,97 @@ +#include <cereal/types/string.hpp> +#include <cereal/types/vector.hpp> +#include <cereal/archives/binary.hpp> +#include <fstream> + +#include "event_serialize.hpp" +#include <phosphor-logging/log.hpp> +#include "config.h" + +// Register class version +// From cereal documentation; +// "This macro should be placed at global scope" +CEREAL_CLASS_VERSION(phosphor::events::Entry, CLASS_VERSION); + +namespace phosphor +{ +namespace events +{ + +using namespace phosphor::logging; + +/** @brief Function required by Cereal to perform serialization. + * @tparam Archive - Cereal archive type (binary in our case). + * @param[in] archive - reference to Cereal archive. + * @param[in] event - const reference to event entry. + * @param[in] version - Class version that enables handling + * a serialized data across code levels + */ +template <class Archive> +void save(Archive& archive, const Entry& event, const std::uint32_t version) +{ + archive(event.timestamp(), event.message(), event.additionalData()); +} + +/** @brief Function required by Cereal to perform deserialization. + * @tparam Archive - Cereal archive type (binary in our case). + * @param[in] archive - reference to Cereal archive. + * @param[in] event - reference to event entry. + * @param[in] version - Class version that enables handling + * a serialized data across code levels + */ +template <class Archive> +void load(Archive& archive, Entry& event, const std::uint32_t version) +{ + using namespace sdbusplus::xyz::openbmc_project::Logging::server; + + uint64_t timestamp{}; + std::string message{}; + std::vector<std::string> additionalData{}; + + archive(timestamp, message, additionalData); + + event.timestamp(timestamp); + event.message(message); + event.additionalData(additionalData); +} + +fs::path serialize(const Entry& event, const std::string& eventName) +{ + fs::path dir(EVENTS_PERSIST_PATH); + auto path = dir / eventName; + fs::create_directories(path); + path /= std::to_string(event.timestamp()); + std::ofstream os(path.string(), std::ios::binary); + cereal::BinaryOutputArchive oarchive(os); + oarchive(event); + return path; +} + +bool deserialize(const fs::path& path, Entry& event) +{ + try + { + if (fs::exists(path)) + { + std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); + cereal::BinaryInputArchive iarchive(is); + iarchive(event); + return true; + } + return false; + } + catch (cereal::Exception& e) + { + log<level::ERR>(e.what()); + std::error_code ec; + fs::remove(path, ec); + return false; + } + catch (const fs::filesystem_error& e) + { + return false; + } +} + +} // namespace event +} // namespace phosphor diff --git a/src/event_serialize.hpp b/src/event_serialize.hpp new file mode 100644 index 0000000..f052845 --- /dev/null +++ b/src/event_serialize.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include <experimental/filesystem> +#include "event_entry.hpp" +#include "config.h" + +namespace phosphor +{ +namespace events +{ + +namespace fs = std::experimental::filesystem; + +/** @brief Serialize and persist event d-bus object + * @param[in] event - const reference to event entry. + * @param[in] eventName - Name of the event. + * @return fs::path - pathname of persisted events file + */ +fs::path serialize(const Entry& event, const std::string& eventName); + +/** @brief Deserialze a persisted event into a d-bus object + * @param[in] path - pathname of persisted event file + * @param[in] event - reference to event object which is the target of + * deserialization. + * @return bool - true if the deserialization was successful, false otherwise. + */ +bool deserialize(const fs::path& path, Entry& event); + +} // namespace events +} // namespace phosphor diff --git a/src/main.cpp b/src/main.cpp index 5e191e1..68cef3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,8 @@ int main(void) sdbusplus::server::manager::manager objManager(bus, OBJ_EVENT); bus.request_name(BUSNAME_EVENT); + phosphor::events::getManager().restore(); + for (auto& watch : ConfigPropertyWatches::get()) { watch->start(); diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 717bacc..8f3cd02 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -199,4 +199,5 @@ callbacktest_LDADD = \ $(builddir)/../elog.o \ $(builddir)/../resolve_errors.o \ $(builddir)/../event_manager.o \ + $(builddir)/../event_serialize.o \ -lstdc++fs |