Initial implementation of HostEpoch
When host time is set, the diff between the BmcTime and the value is
saved to persistent storage;
When host time is retrieved, return the BmcTime plus the diff as
host's time.
Add the unit test cases for HostEpoch.
Change-Id: Ia55b93bfcba4f226ceaed8491136ea7afda7bd77
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/host_epoch.cpp b/host_epoch.cpp
new file mode 100644
index 0000000..f45581d
--- /dev/null
+++ b/host_epoch.cpp
@@ -0,0 +1,74 @@
+#include "host_epoch.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+#include <fstream>
+
+namespace phosphor
+{
+namespace time
+{
+using namespace sdbusplus::xyz::openbmc_project::Time;
+using namespace phosphor::logging;
+
+HostEpoch::HostEpoch(sdbusplus::bus::bus& bus,
+ const char* objPath)
+ : EpochBase(bus, objPath),
+ offset(readData<decltype(offset)::rep>(offsetFile))
+{
+ // Empty
+}
+
+uint64_t HostEpoch::elapsed() const
+{
+ // It does not needs to check owner when getting time
+ return (getTime() + offset).count();
+}
+
+uint64_t HostEpoch::elapsed(uint64_t value)
+{
+ if (timeOwner == Owner::BMC)
+ {
+ log<level::ERR>("Setting HostTime in BMC owner is not allowed");
+ // TODO: throw NotAllowed exception
+ return 0;
+ }
+
+ // TODO: implement the logic of setting host time
+ // based on timeOwner and timeMode
+
+ auto time = std::chrono::microseconds(value);
+ offset = time - getTime();
+
+ // Store the offset to file
+ writeData(offsetFile, offset.count());
+
+ server::EpochTime::elapsed(value);
+ return value;
+}
+
+template <typename T>
+T HostEpoch::readData(const char* fileName)
+{
+ T data{};
+ std::ifstream fs(fileName);
+ if (fs.is_open())
+ {
+ fs >> data;
+ }
+ return data;
+}
+
+template <typename T>
+void HostEpoch::writeData(const char* fileName, T&& data)
+{
+ std::ofstream fs(fileName, std::ios::out);
+ if (fs.is_open())
+ {
+ fs << std::forward<T>(data);
+ }
+}
+
+} // namespace time
+} // namespace phosphor
+