external_storer: Add a log entry limit
This is to ensure that we don't get uncapped log entries. Default is set
to the first 20 logs being saved, and the next 980 being in a circualr
queue (1000 entries in total).
Tested:
Added unit test to ensure that the queue works as intended. Also
verified by injecting 1000 entries to ensure that the buffer indeed
saves the first 20, and caps it 1000.
```
//LogEntry1:
Created: ...Entries/66a97808-1e22-4c1e-b0f6-4b9eb7c714e7/index.json
...
//LogEntry20:
Created: ...Entries/9c07937a-9524-40f1-acef-19db73b46678/index.json
//LogEntry21:
Created: ...Entries/0bfb7ede-8020-4613-bfcf-5815ca176c79/index.json
...
//LogEntry1001:
Removed: ...Entries/0bfb7ede-8020-4613-bfcf-5815ca176c79
Created: ...Entries/31bdf3be-1e87-4e77-922d-9bbac09ac824/index.json
```
We can see that starting on the 1001st log, log entry 21 is deleted to
make room.
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: Ic2badd7f01741d788cad829c9e203b7c4962fc8e
diff --git a/src/rde/external_storer_file.cpp b/src/rde/external_storer_file.cpp
index 1ffea44..3aa0abf 100644
--- a/src/rde/external_storer_file.cpp
+++ b/src/rde/external_storer_file.cpp
@@ -45,12 +45,27 @@
return true;
}
+bool ExternalStorerFileWriter::removeAll(const std::string& filePath) const
+{
+ // Attempt to delete the file
+ std::error_code ec;
+ std::filesystem::remove_all(filePath, ec);
+ if (ec)
+ {
+ return false;
+ }
+ stdplus::print(stderr, "Removed: {}\n", filePath);
+ return true;
+}
+
ExternalStorerFileInterface::ExternalStorerFileInterface(
const std::shared_ptr<sdbusplus::asio::connection>& conn,
std::string_view rootPath,
- std::unique_ptr<FileHandlerInterface> fileHandler) :
+ std::unique_ptr<FileHandlerInterface> fileHandler,
+ uint32_t numSavedLogEntries, uint32_t numLogEntries) :
rootPath(rootPath), fileHandler(std::move(fileHandler)), logServiceId(""),
- cperNotifier(std::make_unique<CperFileNotifierHandler>(conn))
+ cperNotifier(std::make_unique<CperFileNotifierHandler>(conn)),
+ maxNumSavedLogEntries(numSavedLogEntries), maxNumLogEntries(numLogEntries)
{}
bool ExternalStorerFileInterface::publishJson(std::string_view jsonStr)
@@ -118,6 +133,23 @@
return false;
}
+ // Check to see if we are hitting the limit of filePathQueue, delete oldest
+ // log entry first before processing another entry
+ if (logEntryQueue.size() == maxNumLogEntries)
+ {
+ std::string oldestFilePath = std::move(logEntryQueue.front());
+ logEntryQueue.pop();
+
+ if (!fileHandler->removeAll(oldestFilePath))
+ {
+ stdplus::print(
+ stderr,
+ "Failed to delete the oldest entry path, not processing the next log,: {}\n",
+ oldestFilePath);
+ return false;
+ }
+ }
+
std::string id = boost::uuids::to_string(randomGen());
std::string fullPath =
std::format("{}/redfish/v1/Systems/system/LogServices/{}/Entries/{}",
@@ -138,6 +170,18 @@
}
cperNotifier->createEntry(fullPath + "/index.json");
+
+ // Attempt to push to logEntrySavedQueue first, before pushing to
+ // logEntryQueue that can be popped
+ if (logEntrySavedQueue.size() < maxNumSavedLogEntries)
+ {
+ logEntrySavedQueue.push(std::move(fullPath));
+ }
+ else
+ {
+ logEntryQueue.push(std::move(fullPath));
+ }
+
return true;
}