Enable Cereal class versioning

Cereal class versioning helps to handle data de-serialization
across different class versions that differ in the way, a
particular data is serialized.

Change-Id: Ica01c4cb0c213e0dca8824fcfcfaa5cb43c5bc2e
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/configure.ac b/configure.ac
index 5cc1c2e..f912e14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,6 +93,10 @@
 AS_IF([test "x$ERROR_CAP" == "x"], [ERROR_CAP=100])
 AC_DEFINE_UNQUOTED([ERROR_CAP], [$ERROR_CAP], [Max number of error entries allowed for commit])
 
+AC_ARG_VAR(CLASS_VERSION, [Class version to register with Cereal])
+AS_IF([test "x$CLASS_VERSION" == "x"], [CLASS_VERSION=1])
+AC_DEFINE_UNQUOTED([CLASS_VERSION], [$CLASS_VERSION], [Class version to register with Cereal])
+
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile test/Makefile])
 AC_CONFIG_FILES([phosphor-logging.pc])
diff --git a/elog_serialize.cpp b/elog_serialize.cpp
index f8c40e1..1af1946 100644
--- a/elog_serialize.cpp
+++ b/elog_serialize.cpp
@@ -6,6 +6,12 @@
 
 #include "elog_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::logging::Entry, CLASS_VERSION);
 
 namespace phosphor
 {
@@ -14,11 +20,13 @@
 
 /** @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] 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)
+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());
@@ -26,11 +34,13 @@
 
 /** @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] 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)
+void load(Archive& a, Entry& e, const std::uint32_t version)
 {
     using namespace
         sdbusplus::xyz::openbmc_project::Logging::server;
@@ -84,6 +94,18 @@
         fs::remove(path);
         return false;
     }
+    catch(const std::length_error& e)
+    {
+        // 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
+        log<level::ERR>(e.what());
+        fs::remove(path);
+        return false;
+    }
 }
 
 } // namespace logging
diff --git a/log_manager.cpp b/log_manager.cpp
index c1fe383..1efec9c 100644
--- a/log_manager.cpp
+++ b/log_manager.cpp
@@ -245,7 +245,10 @@
         }
     }
 
-    entryId = *(std::max_element(errorIds.begin(), errorIds.end()));
+    if (!errorIds.empty())
+    {
+        entryId = *(std::max_element(errorIds.begin(), errorIds.end()));
+    }
 }
 
 } // namespace internal