PEL: Remove a PEL based on an ID

When someone deletes an OpenBMC event log, the corresponding PEL should
also be deleted.  This commit adds support for that by keeping an
internal map of the IDs to the files that contain the PEL data in the
repository in order to find the file to remove.  This will then get
called in the phosphor-logging extension's delete hook.

The actual map key is a structure of both the PEL ID and OpenBMC log ID,
so either can be used to find a PEL in the repository, which will be
useful in other cases, for example for retrieving PEL data based on the
PEL ID.

As the map needs to match the actual repository file contents, it will
get built on startup, and modified when PELs are added and removed.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I33bb96da297c770e175c5c6b19705dda1c8766b6
diff --git a/extensions/openpower-pels/repository.cpp b/extensions/openpower-pels/repository.cpp
index c9f9521..aa6a18b 100644
--- a/extensions/openpower-pels/repository.cpp
+++ b/extensions/openpower-pels/repository.cpp
@@ -20,6 +20,50 @@
     {
         fs::create_directories(_logPath);
     }
+
+    restore();
+}
+
+void Repository::restore()
+{
+    for (auto& dirEntry : fs::directory_iterator(_logPath))
+    {
+        try
+        {
+            if (!fs::is_regular_file(dirEntry.path()))
+            {
+                continue;
+            }
+
+            std::ifstream file{dirEntry.path()};
+            std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
+                                      std::istreambuf_iterator<char>()};
+            file.close();
+
+            PEL pel(std::move(data));
+            if (pel.valid())
+            {
+                using pelID = LogID::Pel;
+                using obmcID = LogID::Obmc;
+                _idsToPELs.emplace(
+                    LogID(pelID(pel.id()), obmcID(pel.obmcLogID())),
+                    dirEntry.path());
+            }
+            else
+            {
+                log<level::ERR>(
+                    "Found invalid PEL file while restoring.  Removing.",
+                    entry("FILENAME=%s", dirEntry.path().c_str()));
+                fs::remove(dirEntry.path());
+            }
+        }
+        catch (std::exception& e)
+        {
+            log<level::ERR>("Hit exception while restoring PEL File",
+                            entry("FILENAME=%s", dirEntry.path().c_str()),
+                            entry("ERROR=%s", e.what()));
+        }
+    }
 }
 
 std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
@@ -65,6 +109,20 @@
                         entry("PATH=%s", path.c_str()));
         throw file_error::Write();
     }
+
+    using pelID = LogID::Pel;
+    using obmcID = LogID::Obmc;
+    _idsToPELs.emplace(LogID(pelID(pel->id()), obmcID(pel->obmcLogID())), path);
+}
+
+void Repository::remove(const LogID& id)
+{
+    auto pel = findPEL(id);
+    if (pel != _idsToPELs.end())
+    {
+        fs::remove(pel->second);
+        _idsToPELs.erase(pel);
+    }
 }
 
 } // namespace pels