Add one second timer to save POST codes to file

A lot of POST codes are sent to BMC from BIC
in a short time.

In BMC, there is an ipmi handler to get POST codes
and upload to dbus property.

The xyz.openbmc_project.State.Boot@.PostCode service
listens the PropertiesChanged signal and saves to POST
codes history file.

The xyz.openbmc_project.State.Boot@.PostCode service
is hanged if there are too many POST codes in a short time.

At this time, the memory usage of dbus-broker increases,
and the out-of-memory(OOM) issue happens.

The processes are killed when OOM happens,
and BMC may reset unexpected.

Test Case:
Check the frequency for post code file getting larger

Signed-off-by: Bonnie Lo <Bonnie_Lo@wiwynn.com>
Change-Id: Ic5a397cfa7f053e196cc3d0eeae3e2b2fa5089b7
diff --git a/inc/post_code.hpp b/inc/post_code.hpp
index 3ae58d8..53aa320 100644
--- a/inc/post_code.hpp
+++ b/inc/post_code.hpp
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include <phosphor-logging/elog-errors.hpp>
+#include <sdbusplus/timer.hpp>
 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
 #include <xyz/openbmc_project/Common/error.hpp>
 #include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
@@ -62,9 +63,10 @@
 
 struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
 {
-    PostCode(sdbusplus::bus_t& bus, const char* path, int nodeIndex) :
-        sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
-        node(nodeIndex),
+    PostCode(sdbusplus::bus_t& bus, const char* path, EventPtr& event,
+             int nodeIndex) :
+        sdbusplus::server::object_t<post_code, delete_all>(bus, path),
+        bus(bus), event(event), node(nodeIndex),
         postCodeListPath(PostCodeListPathPrefix + std::to_string(node)),
         propertiesChangedSignalRaw(
             bus,
@@ -137,7 +139,9 @@
     void incrBootCycle();
     uint16_t getBootNum(const uint16_t index) const;
 
+    std::unique_ptr<phosphor::Timer> timer;
     sdbusplus::bus_t& bus;
+    EventPtr& event;
     int node;
     std::chrono::time_point<std::chrono::steady_clock> firstPostCodeTimeSteady;
     uint64_t firstPostCodeUsSinceEpoch;
diff --git a/src/main.cpp b/src/main.cpp
index 6d53629..be4b6b9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -64,7 +64,7 @@
 
     bus.request_name(intfName.c_str());
 
-    PostCode postCode{bus, dbusObjName.c_str(), node};
+    PostCode postCode{bus, dbusObjName.c_str(), eventP, node};
 
     try
     {
diff --git a/src/post_code.cpp b/src/post_code.cpp
index 8ab2e32..327e29e 100644
--- a/src/post_code.cpp
+++ b/src/post_code.cpp
@@ -24,6 +24,8 @@
 
 #include <iomanip>
 
+const static constexpr auto timeoutMicroSeconds = 1000000;
+
 void PostCode::deleteAll()
 {
     std::uintmax_t n = fs::remove_all(postCodeListPath);
@@ -72,6 +74,12 @@
 
 void PostCode::savePostCodes(postcode_t code)
 {
+    if (!timer)
+    {
+        timer = std::make_unique<phosphor::Timer>(
+            event.get(), [this]() { serialize(postCodeListPath); });
+    }
+
     // steady_clock is a monotonic clock that is guaranteed to never be adjusted
     auto postCodeTimeSteady = std::chrono::steady_clock::now();
     uint64_t tsUS = std::chrono::duration_cast<std::chrono::microseconds>(
@@ -98,7 +106,11 @@
     {
         postCodes.erase(postCodes.begin());
     }
-    serialize(postCodeListPath);
+
+    if (!timer->isRunning())
+    {
+        timer->start(std::chrono::microseconds(timeoutMicroSeconds));
+    }
 
 #ifdef ENABLE_BIOS_POST_CODE_LOG
     uint64_t usTimeOffset = tsUS - firstPostCodeUsSinceEpoch;