PNOR: Store a redundant copy of the priority persistence file

In this commit, the priority persistence functionality is extended by
storing a second copy of each persistence file in the RW volume for its
version.

Upon a reboot, the corresponding restoration from file checks the second
location if necessary.

Resolves openbmc/openbmc#2133

Change-Id: Ie1926ad8500d49e7ec7cf71bd703664ac23c6a7a
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
diff --git a/serialize.cpp b/serialize.cpp
index a499798..8c63264 100644
--- a/serialize.cpp
+++ b/serialize.cpp
@@ -19,28 +19,54 @@
     {
         fs::create_directory(PERSIST_DIR);
     }
-    std::string path = PERSIST_DIR + versionId;
 
-    std::ofstream os(path.c_str());
-    cereal::JSONOutputArchive oarchive(os);
-    oarchive(cereal::make_nvp("priority", priority));
+    // store one copy in /var/lib/obmc/openpower-pnor-code-mgmt/[versionId]
+    auto varPath = PERSIST_DIR + versionId;
+    std::ofstream varOutput(varPath.c_str());
+    cereal::JSONOutputArchive varArchive(varOutput);
+    varArchive(cereal::make_nvp("priority", priority));
+
+    if(fs::is_directory(PNOR_RW_PREFIX + versionId))
+    {
+        // store another copy in /media/pnor-rw-[versionId]/[versionId]
+        auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
+        std::ofstream rwOutput(rwPath.c_str());
+        cereal::JSONOutputArchive rwArchive(rwOutput);
+        rwArchive(cereal::make_nvp("priority", priority));
+    }
 }
 
 bool restoreFromFile(std::string versionId, uint8_t& priority)
 {
-    std::string path = PERSIST_DIR + versionId;
-    if (fs::exists(path))
+    auto varPath = PERSIST_DIR + versionId;
+    if (fs::exists(varPath))
     {
-        std::ifstream is(path.c_str(), std::ios::in);
+        std::ifstream varInput(varPath.c_str(), std::ios::in);
         try
         {
-            cereal::JSONInputArchive iarchive(is);
-            iarchive(cereal::make_nvp("priority", priority));
+            cereal::JSONInputArchive varArchive(varInput);
+            varArchive(cereal::make_nvp("priority", priority));
             return true;
         }
         catch(cereal::RapidJSONException& e)
         {
-            fs::remove(path);
+            fs::remove(varPath);
+        }
+    }
+
+    auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
+    if (fs::exists(rwPath))
+    {
+        std::ifstream rwInput(rwPath.c_str(), std::ios::in);
+        try
+        {
+            cereal::JSONInputArchive rwArchive(rwInput);
+            rwArchive(cereal::make_nvp("priority", priority));
+            return true;
+        }
+        catch(cereal::RapidJSONException& e)
+        {
+            fs::remove(rwPath);
         }
     }
     return false;
diff --git a/serialize.hpp b/serialize.hpp
index 4e6e99f..5198847 100644
--- a/serialize.hpp
+++ b/serialize.hpp
@@ -1,8 +1,5 @@
 #pragma once
 
-#include <experimental/filesystem>
-#include "config.h"
-
 namespace openpower
 {
 namespace software
@@ -10,8 +7,6 @@
 namespace updater
 {
 
-namespace fs = std::experimental::filesystem;
-
 /** @brief Serialization function - stores activation information to file
  *  @param[in] versionId - The version for which to store information.
  *  @param[in] priority - RedundancyPriority value for that version.