metric-collector: Update reboot time if LastRebootTime changed

After
https://gerrit.openbmc.org/c/openbmc/phosphor-state-manager/+/66936 is
in, the LastRebootTime can change once the timsync happens. This is
needed becuase it is possible tha the lastRebootTime at bootup is less
than the saved value from the previous reboot in a reboot loop. This
allows us to update the count after timesync to make sure that we have
the proper lastRebootTime.

Example failures:
After the system rebooted, the reboot count wasn't updated. Restart the
metric-collector and found that the current reboot time doesn't match
the one that was saved...

```
$ /tmp/metric-collector
current reboot time: 1704819274000 vs. saved reboot time: 1704819146000
```

Suggesting that the reboot time fetched pre-timesync was less than the
saved reboot time. With the signal matcher, the new reboot time will
be used and update the count properly.

Tested:
```
root@dddev2-nfd01:~# busctl  get-property xyz.openbmc_project.State.BMC /xyz/openbmc_project/state/bmc0 xyz.openbmc_project.State.BMC LastRebootTime
t 1704859755000

root@dddev2-nfd01:~# cat /var/google/bootinfo
11 0 1704859755000

root@dddev2-nfd01:~# systemctl status phosphor-metric-collector.service
● phosphor-metric-collector.service - BMC Metric Collection
     Loaded: loaded (/usr/lib/systemd/system/phosphor-metric-collector.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-01-09 20:17:06 PST; 3min 38s ago
   Main PID: 4256 (metric-collecto)
        CPU: 3.340s
     CGroup: /system.slice/phosphor-metric-collector.service
             └─4256 /usr/bin/metric-collector

Jan 09 20:17:06 dddev2-nfd01.prod.google.com systemd[1]: Started BMC Metric Collection.
root@dddev2-nfd01:~# systemctl status xyz.openbmc_project.State.BMC
● xyz.openbmc_project.State.BMC.service - Phosphor BMC State Manager
     Loaded: loaded (/usr/lib/systemd/system/xyz.openbmc_project.State.BMC.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-01-09 20:07:39 PST; 13min ago
   Main PID: 437 (phosphor-bmc-st)
        CPU: 300ms
     CGroup: /system.slice/xyz.openbmc_project.State.BMC.service
             └─437 /usr/bin/phosphor-bmc-state-manager

```

Google-Bug-Id: 313338463
Change-Id: Idd13f28dc238c6803281d3195e2dd63bf680a94e
Signed-off-by: Willy Tu <wltu@google.com>
(cherry picked from commit ce4946a231a417b92a30f34f407f3d482fa594d1)
diff --git a/recipes-google/metric-collector/metric-collector/0002-Metric-Collection-Daemon.patch b/recipes-google/metric-collector/metric-collector/0002-Metric-Collection-Daemon.patch
index d7b782c..4cca4f1 100644
--- a/recipes-google/metric-collector/metric-collector/0002-Metric-Collection-Daemon.patch
+++ b/recipes-google/metric-collector/metric-collector/0002-Metric-Collection-Daemon.patch
@@ -1,4 +1,4 @@
-From 72cbfbea9d2f9fafec035d1bd5c89a0eb22cb7a3 Mon Sep 17 00:00:00 2001
+From e561a16af403c525e44dcff7e0a06ce8ecb3410a Mon Sep 17 00:00:00 2001
 From: Edward Lee <edwarddl@google.com>
 Date: Wed, 18 Jan 2023 21:37:49 +0000
 Subject: [PATCH] Metric-Collection-Daemon
@@ -76,21 +76,22 @@
 Signed-off-by: Edward Lee <edwarddl@google.com>
 Signed-off-by: Willy Tu <wltu@google.com>
 Change-Id: I88ec028efcd9373f72589a321bc8246c3664d40f
+Signed-off-by: Willy Tu <wltu@google.com>
 ---
  .gitignore                                    |   1 +
  meson.build                                   |   1 +
  metric-collection-daemon                      |   1 +
- .../metric-collection-daemon/daemon.cpp       | 221 ++++++++++
+ .../metric-collection-daemon/daemon.cpp       | 221 +++++++++
  .../metric-collection-daemon/daemon.hpp       |  55 +++
  .../metric-collection-daemon/meson.build      |  44 ++
- .../metricCollector.cpp                       | 398 ++++++++++++++++++
- .../metricCollector.hpp                       |  79 ++++
+ .../metricCollector.cpp                       | 430 ++++++++++++++++++
+ .../metricCollector.hpp                       |  81 ++++
  .../phosphor-metric-collector.service.in      |  11 +
- subprojects/metric-collection-daemon/port.cpp | 197 +++++++++
+ subprojects/metric-collection-daemon/port.cpp | 197 ++++++++
  subprojects/metric-collection-daemon/port.hpp |  64 +++
  .../metric-collection-daemon/utils.cpp        | 186 ++++++++
  .../metric-collection-daemon/utils.hpp        |  36 ++
- 13 files changed, 1294 insertions(+)
+ 13 files changed, 1328 insertions(+)
  create mode 120000 metric-collection-daemon
  create mode 100644 subprojects/metric-collection-daemon/daemon.cpp
  create mode 100644 subprojects/metric-collection-daemon/daemon.hpp
@@ -475,10 +476,10 @@
 +  install_dir: systemd.get_pkgconfig_variable('systemdsystemunitdir'))
 diff --git a/subprojects/metric-collection-daemon/metricCollector.cpp b/subprojects/metric-collection-daemon/metricCollector.cpp
 new file mode 100644
-index 0000000..80f4aee
+index 0000000..880a0d0
 --- /dev/null
 +++ b/subprojects/metric-collection-daemon/metricCollector.cpp
-@@ -0,0 +1,398 @@
+@@ -0,0 +1,430 @@
 +#include "metricCollector.hpp"
 +
 +#include "utils.hpp"
@@ -506,6 +507,7 @@
 +#include <tuple>
 +#include <unordered_map>
 +#include <unordered_set>
++#include <variant>
 +#include <vector>
 +
 +// TODO: Make this configurable
@@ -519,7 +521,27 @@
 +    std::shared_ptr<sdbusplus::asio::connection> conn,
 +    sdbusplus::asio::object_server& objServer) :
 +    ioc(ioc),
-+    conn(conn), objServer(objServer)
++    conn(conn), objServer(objServer),
++    rebootTimeSignal(std::make_unique<decltype(rebootTimeSignal)::element_type>(
++        *conn,
++        sdbusplus::bus::match::rules::propertiesChanged(
++            "/xyz/openbmc_project/state/bmc0", "xyz.openbmc_project.State.BMC"),
++        [this](sdbusplus::message_t& m) {
++    std::string interface;
++    std::unordered_map<std::string, std::variant<uint64_t>> propertyChanged;
++    m.read(interface, propertyChanged);
++
++    for (const auto& [key, value] : propertyChanged)
++    {
++        if (key == "LastRebootTime" && std::holds_alternative<uint64_t>(value))
++        {
++            stdplus::println(stderr, "LastRebootTime updated post timesync");
++            updateBootCount();
++            rebootTimeSignal.reset();
++            break;
++        }
++    }
++}))
 +{
 +    registerAssociations();
 +    updateBootCount();
@@ -774,10 +796,16 @@
 +
 +        if (updateRebootCount)
 +        {
-+            ++bootinfo[0];
-+            if (updateCrashCount)
++            // If this is triggered by rebootTimeSignal and that we have already
++            // updated the reboot count, then only update the last reboot time
++            // to make sure that time is valid.
++            if (!updatedBootCount)
 +            {
-+                ++bootinfo[1];
++                ++bootinfo[0];
++                if (updateCrashCount)
++                {
++                    ++bootinfo[1];
++                }
 +            }
 +
 +            std::ofstream bootinfoFile("/var/google/bootinfo");
@@ -788,7 +816,12 @@
 +
 +        bootCount = bootinfo[0];
 +        crashCount = bootinfo[1];
++        if (updatedBootCount)
++        {
++            return;
++        }
 +
++        updatedBootCount = true;
 +        metrics->set_property("BootCount", bootCount);
 +        metrics->set_property("CrashCount", crashCount);
 +    },
@@ -879,10 +912,10 @@
 +}
 diff --git a/subprojects/metric-collection-daemon/metricCollector.hpp b/subprojects/metric-collection-daemon/metricCollector.hpp
 new file mode 100644
-index 0000000..a3da156
+index 0000000..0423fa8
 --- /dev/null
 +++ b/subprojects/metric-collection-daemon/metricCollector.hpp
-@@ -0,0 +1,79 @@
+@@ -0,0 +1,81 @@
 +#include "daemon.hpp"
 +#include "port.hpp"
 +#include "utils.hpp"
@@ -959,6 +992,8 @@
 +    std::shared_ptr<sdbusplus::asio::dbus_interface> association_interface;
 +    std::shared_ptr<std::vector<Association>> associations;
 +    uint32_t associationCounter = 0;
++    std::unique_ptr<sdbusplus::bus::match_t> rebootTimeSignal;
++    bool updatedBootCount;
 +};
 +
 +} // namespace
@@ -1486,6 +1521,6 @@
 +std::array<uint64_t, 3> parseBootInfo();
 +
 +std::optional<std::string> getPortIdByNum(const int portNum);
---
+-- 
 2.43.0.472.g3155946c3a-goog