sel-cache: Use sel cache for getSELEntry()

Use the cached SEL info in getSELEntry().
There will be future commits to use the cached SEL for other handlers.

Tested: Verify ipmi sel list and sel get works OK.
        Verify the sel list time is reduced, e.g. on g220a with 100 SEL
        entries, the list time is reduced from about 6s to 2s.

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: I908b21baf47220c8556ad92446a9cb04879090d4
diff --git a/storagehandler.cpp b/storagehandler.cpp
index dd247c0..0f2fc2f 100644
--- a/storagehandler.cpp
+++ b/storagehandler.cpp
@@ -76,6 +76,7 @@
 using SELCacheMap = std::map<SELRecordID, SELEntry>;
 
 SELCacheMap selCacheMap __attribute__((init_priority(101)));
+bool selCacheMapInitialized;
 std::unique_ptr<sdbusplus::bus::match::match> selAddedMatch
     __attribute__((init_priority(101)));
 std::unique_ptr<sdbusplus::bus::match::match> selRemovedMatch
@@ -93,8 +94,17 @@
 std::pair<uint16_t, SELEntry> parseLoggingEntry(const std::string& p)
 {
     auto id = getLoggingId(p);
-    // TODO: parse the sel data
-    return {id, {}};
+    ipmi::sel::GetSELEntryResponse record{};
+    try
+    {
+        record = ipmi::sel::convertLogEntrytoSEL(p);
+    }
+    catch (const std::exception& e)
+    {
+        fprintf(stderr, "Failed to convert %s to SEL: %s\n", p.c_str(),
+                e.what());
+    }
+    return {id, std::move(record.event)};
 }
 
 static void selAddedCallback(sdbusplus::message::message& m)
@@ -179,6 +189,7 @@
         selCacheMap.insert(parseLoggingEntry(p));
     }
     registerSelCallbackHandler();
+    selCacheMapInitialized = true;
 }
 
 /**
@@ -285,74 +296,58 @@
         }
     }
 
-    if (cache::paths.empty())
+    if (!selCacheMapInitialized)
+    {
+        // In case the initSELCache() fails, try it again
+        initSELCache();
+    }
+
+    if (selCacheMap.empty())
     {
         *data_len = 0;
         return IPMI_CC_SENSOR_INVALID;
     }
 
-    ipmi::sel::ObjectPaths::const_iterator iter;
+    SELCacheMap::const_iterator iter;
 
     // Check for the requested SEL Entry.
     if (requestData->selRecordID == ipmi::sel::firstEntry)
     {
-        iter = cache::paths.begin();
+        iter = selCacheMap.begin();
     }
     else if (requestData->selRecordID == ipmi::sel::lastEntry)
     {
-        iter = cache::paths.end();
+        if (selCacheMap.size() > 1)
+        {
+            iter = selCacheMap.end();
+            --iter;
+        }
+        else
+        {
+            // Only one entry exists, return the first
+            iter = selCacheMap.begin();
+        }
     }
     else
     {
-        std::string objPath = std::string(ipmi::sel::logBasePath) + "/" +
-                              std::to_string(requestData->selRecordID);
-
-        iter = std::find(cache::paths.begin(), cache::paths.end(), objPath);
-        if (iter == cache::paths.end())
+        iter = selCacheMap.find(requestData->selRecordID);
+        if (iter == selCacheMap.end())
         {
             *data_len = 0;
             return IPMI_CC_SENSOR_INVALID;
         }
     }
 
-    ipmi::sel::GetSELEntryResponse record{};
-
-    // Convert the log entry into SEL record.
-    try
-    {
-        record = ipmi::sel::convertLogEntrytoSEL(*iter);
-    }
-    catch (const InternalFailure& e)
-    {
-        *data_len = 0;
-        return IPMI_CC_UNSPECIFIED_ERROR;
-    }
-    catch (const std::runtime_error& e)
-    {
-        log<level::ERR>(e.what());
-        *data_len = 0;
-        return IPMI_CC_UNSPECIFIED_ERROR;
-    }
-
+    ipmi::sel::GetSELEntryResponse record{0, iter->second};
     // Identify the next SEL record ID
-    if (iter != cache::paths.end())
+    ++iter;
+    if (iter == selCacheMap.end())
     {
-        ++iter;
-        if (iter == cache::paths.end())
-        {
-            record.nextRecordID = ipmi::sel::lastEntry;
-        }
-        else
-        {
-            namespace fs = std::filesystem;
-            fs::path path(*iter);
-            record.nextRecordID = static_cast<uint16_t>(
-                std::stoul(std::string(path.filename().c_str())));
-        }
+        record.nextRecordID = ipmi::sel::lastEntry;
     }
     else
     {
-        record.nextRecordID = ipmi::sel::lastEntry;
+        record.nextRecordID = iter->first;
     }
 
     if (requestData->readLength == ipmi::sel::entireRecord)
@@ -866,6 +861,7 @@
 
 void register_netfn_storage_functions()
 {
+    selCacheMapInitialized = false;
     initSELCache();
     // <Get SEL Info>
     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,