summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2017-06-12 04:33:29 -0500
committerPatrick Williams <patrick@stwcx.xyz>2017-06-26 02:33:34 +0000
commit72654f10e45056ab55b77d835e2bfd01e8d98480 (patch)
treea81c82f786690244abf0a8be2185e6c775cabac5
parent979632aeb629b4cb62aed276f7422c34cd7983bc (diff)
downloadphosphor-logging-72654f10e45056ab55b77d835e2bfd01e8d98480.tar.gz
phosphor-logging-72654f10e45056ab55b77d835e2bfd01e8d98480.zip
Persist error d-bus objects
Use Cereal to implement serialization and de-serialization of properties of error d-bus objects. Serialize and persist error d-bus objects as they are put on the bus. De-serialize and restore them (if persistent ones exist) when phosphor-log-manager starts up. Change-Id: I1f5df1abbe74bfdb86e3e82a78ff7115e90e2112 Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac6
-rw-r--r--elog_entry.hpp20
-rw-r--r--elog_serialize.cpp35
-rw-r--r--elog_serialize.hpp78
-rw-r--r--log_manager.cpp54
-rw-r--r--log_manager.hpp5
-rw-r--r--log_manager_main.cpp7
8 files changed, 198 insertions, 13 deletions
diff --git a/Makefile.am b/Makefile.am
index 6ca02d3..29f18d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,7 +36,8 @@ phosphor_log_manager_SOURCES = \
elog_entry.cpp \
org.openbmc.Associations.cpp \
elog-process-metadata.cpp \
- elog_meta.cpp
+ elog_meta.cpp \
+ elog_serialize.cpp
# Be sure to build needed files before compiling
BUILT_SOURCES = \
@@ -64,7 +65,8 @@ callout_test_CXXFLAGS = $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
phosphor_log_manager_LDFLAGS = \
$(SYSTEMD_LIBS) \
$(SDBUSPLUS_LIBS) \
- $(PHOSPHOR_DBUS_INTERFACES_LIBS)
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+ -lstdc++fs
phosphor_log_manager_CXXFLAGS = \
$(SYSTEMD_CFLAGS) \
$(SDBUSPLUS_CFLAGS) \
diff --git a/configure.ac b/configure.ac
index 7055888..977bcb0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,6 +77,12 @@ AC_ARG_VAR(CALLOUTS_YAML, [YAML filepath containing generated callouts.])
AS_IF([test "x$CALLOUTS_YAML" == "x"], \
[CALLOUTS_YAML="callouts-example.yaml"])
+AC_ARG_VAR(ERRLOG_PERSIST_PATH, [Path of directory housing persisted errors.])
+AS_IF([test "x$ERRLOG_PERSIST_PATH" == "x"], \
+ [ERRLOG_PERSIST_PATH="/var/lib/phosphor-logging/errors"])
+AC_DEFINE_UNQUOTED([ERRLOG_PERSIST_PATH], ["$ERRLOG_PERSIST_PATH"], \
+ [Path of directory housing persisted errors])
+
# Compile error metadata handlers if we're asked to do so.
AC_ARG_ENABLE([metadata-processing],
AS_HELP_STRING([--enable-metadata-processing], [Compile metadata handlers]),
diff --git a/elog_entry.hpp b/elog_entry.hpp
index 06f6bc2..ffff8af 100644
--- a/elog_entry.hpp
+++ b/elog_entry.hpp
@@ -75,6 +75,24 @@ class Entry : public EntryIfaces
this->emit_object_added();
};
+ /** @brief Constructor that puts an "empty" error object on the bus,
+ * with only the id property populated. Rest of the properties
+ * to be set by the caller. Caller should emit the added signal.
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - Path to attach at.
+ * @param[in] id - The error entry id.
+ * @param[in] parent - The error's parent.
+ */
+ Entry(sdbusplus::bus::bus& bus,
+ const std::string& path,
+ uint32_t entryId,
+ Manager& parent) :
+ EntryIfaces(bus, path.c_str(), true),
+ parent(parent)
+ {
+ id(entryId);
+ };
+
/** @brief Set resolution status of the error.
* @param[in] value - boolean indicating resolution
* status (true = resolved)
@@ -89,6 +107,8 @@ class Entry : public EntryIfaces
return sdbusplus::xyz::openbmc_project::
Logging::server::Entry::resolved(value);
}
+ using sdbusplus::xyz::openbmc_project::
+ Logging::server::Entry::resolved;
/** @brief Delete this d-bus object.
*/
diff --git a/elog_serialize.cpp b/elog_serialize.cpp
new file mode 100644
index 0000000..0468e11
--- /dev/null
+++ b/elog_serialize.cpp
@@ -0,0 +1,35 @@
+#include <cereal/types/string.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/types/tuple.hpp>
+#include <cereal/archives/binary.hpp>
+#include <fstream>
+#include "elog_serialize.hpp"
+
+namespace phosphor
+{
+namespace logging
+{
+
+fs::path serialize(const Entry& e, const fs::path& dir)
+{
+ auto path = dir / std::to_string(e.id());
+ 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)
+{
+ 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;
+}
+
+} // namespace logging
+} // namespace phosphor
diff --git a/elog_serialize.hpp b/elog_serialize.hpp
new file mode 100644
index 0000000..d1bcbfb
--- /dev/null
+++ b/elog_serialize.hpp
@@ -0,0 +1,78 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <experimental/filesystem>
+#include "elog_entry.hpp"
+#include "config.h"
+
+namespace phosphor
+{
+namespace logging
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @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.
+ */
+template<class Archive>
+void save(Archive& a, const Entry& e)
+{
+ a(e.id(), e.severity(), e.timestamp(),
+ e.message(), e.additionalData(), e.associations(), e.resolved());
+}
+
+/** @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.
+ */
+template<class Archive>
+void load(Archive& a, Entry& e)
+{
+ using namespace
+ sdbusplus::xyz::openbmc_project::Logging::server;
+
+ uint32_t id{};
+ Entry::Level severity{};
+ uint64_t timestamp{};
+ std::string message{};
+ std::vector<std::string> additionalData{};
+ bool resolved{};
+ AssociationList associations{};
+
+ a(id, severity, timestamp, message,
+ additionalData, associations, resolved);
+
+ e.id(id);
+ e.severity(severity);
+ e.timestamp(timestamp);
+ e.message(message);
+ e.additionalData(additionalData);
+ e.sdbusplus::xyz::openbmc_project::
+ Logging::server::Entry::resolved(resolved);
+ e.associations(associations);
+}
+
+/** @brief Serialize and persist error d-bus object
+ * @param[in] a - const reference to error entry.
+ * @param[in] dir - pathname of directory where the serialized error will
+ * be placed.
+ * @return fs::path - pathname of persisted error file
+ */
+fs::path serialize(const Entry& e,
+ const fs::path& dir = fs::path(ERRLOG_PERSIST_PATH));
+
+/** @brief Deserialze a persisted error into a d-bus object
+ * @param[in] path - pathname of persisted error file
+ * @param[in] e - reference to error object which is the target of
+ * deserialization.
+ * @return bool - true if the deserialization was successful, false otherwise.
+ */
+bool deserialize(const fs::path& path, Entry& e);
+
+} // namespace logging
+} // namespace phosphor
diff --git a/log_manager.cpp b/log_manager.cpp
index 8ab495b..3f61e91 100644
--- a/log_manager.cpp
+++ b/log_manager.cpp
@@ -14,6 +14,7 @@
#include <phosphor-logging/log.hpp>
#include "log_manager.hpp"
#include "elog_meta.hpp"
+#include "elog_serialize.hpp"
using namespace phosphor::logging;
extern const std::map<metadata::Metadata,
@@ -145,17 +146,18 @@ void Manager::commit(uint64_t transactionId, std::string errMsg)
{
reqLevel = levelmap->second;
}
- entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
- busLog,
- objPath,
- entryId,
- ms, // Milliseconds since 1970
- static_cast<Entry::Level>(reqLevel),
- std::move(errMsg),
- std::move(additionalData),
- std::move(objects),
- *this)));
- return;
+ auto e = std::make_unique<Entry>(
+ busLog,
+ objPath,
+ entryId,
+ ms, // Milliseconds since 1970
+ static_cast<Entry::Level>(reqLevel),
+ std::move(errMsg),
+ std::move(additionalData),
+ std::move(objects),
+ *this);
+ serialize(*e);
+ entries.insert(std::make_pair(entryId, std::move(e)));
}
void Manager::processMetadata(const std::string& errorName,
@@ -188,5 +190,35 @@ void Manager::erase(uint32_t entryId)
}
}
+void Manager::restore()
+{
+ std::vector<uint32_t> errorIds;
+
+ fs::path dir(ERRLOG_PERSIST_PATH);
+ if (!fs::exists(dir) || fs::is_empty(dir))
+ {
+ return;
+ }
+
+ for(auto& file: fs::directory_iterator(dir))
+ {
+ auto id = file.path().filename().c_str();
+ auto idNum = std::stol(id);
+ auto e = std::make_unique<Entry>(
+ busLog,
+ std::string(OBJ_ENTRY) + '/' + id,
+ idNum,
+ *this);
+ if (deserialize(file.path(), *e))
+ {
+ e->emit_object_added();
+ entries.insert(std::make_pair(idNum, std::move(e)));
+ errorIds.push_back(idNum);
+ }
+ }
+
+ entryId = *(std::max_element(errorIds.begin(), errorIds.end()));
+}
+
} // namespace logging
} // namepsace phosphor
diff --git a/log_manager.hpp b/log_manager.hpp
index 71b6e71..730f63e 100644
--- a/log_manager.hpp
+++ b/log_manager.hpp
@@ -67,6 +67,11 @@ class Manager : public details::ServerObject<details::ManagerIface>
*/
void erase(uint32_t entryId);
+ /** @brief Construct error d-bus objects from their persisted
+ * representations.
+ */
+ void restore();
+
private:
/** @brief Call metadata handler(s), if any. Handlers may create
* associations.
diff --git a/log_manager_main.cpp b/log_manager_main.cpp
index a3b26a3..b04c0e3 100644
--- a/log_manager_main.cpp
+++ b/log_manager_main.cpp
@@ -1,5 +1,6 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/manager.hpp>
+#include <experimental/filesystem>
#include "config.h"
#include "log_manager.hpp"
@@ -12,6 +13,12 @@ int main(int argc, char *argv[])
phosphor::logging::Manager manager(bus, OBJ_INTERNAL);
+ // Create a directory to persist errors.
+ std::experimental::filesystem::create_directories(ERRLOG_PERSIST_PATH);
+
+ // Recreate error d-bus objects from persisted errors.
+ manager.restore();
+
bus.request_name(BUSNAME_LOGGING);
while(true)
OpenPOWER on IntegriCloud