summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRatan Gupta <ratagupt@in.ibm.com>2017-09-03 18:01:22 +0530
committerRatan Gupta <ratagupt@in.ibm.com>2017-09-13 17:06:10 +0530
commit4f80c1a7273a7bfc376d2891d2200022f8b38c50 (patch)
tree1edec10196b3b841df462ade9c3903291b5d6522
parent0f9dc1b2c4097b4c54cddfd43bf7f2a24117fec7 (diff)
downloadphosphor-networkd-4f80c1a7273a7bfc376d2891d2200022f8b38c50.tar.gz
phosphor-networkd-4f80c1a7273a7bfc376d2891d2200022f8b38c50.zip
Add the timer class
Usage would be instantiate the timer with the call back and start the timer with the time. callback will be called once the timer expires. Change-Id: I09394264ba18bd90a1c101fc77bc45f7268c5db0 Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
-rw-r--r--Makefile.am6
-rw-r--r--timer.cpp127
-rw-r--r--timer.hpp99
3 files changed, 230 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index aacb465..eac5692 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,8 @@ noinst_HEADERS = \
system_configuration.hpp \
dhcp_configuration.hpp \
vlan_interface.hpp \
- rtnetlink_server.hpp
+ rtnetlink_server.hpp \
+ timer.hpp
phosphor_network_manager_SOURCES = \
ethernet_interface.cpp \
@@ -37,7 +38,8 @@ phosphor_network_manager_SOURCES = \
config_parser.cpp \
dhcp_configuration.cpp \
vlan_interface.cpp \
- rtnetlink_server.cpp
+ rtnetlink_server.cpp \
+ timer.cpp
CLEANFILES = \
xyz/openbmc_project/Network/VLAN/Create/server.cpp \
diff --git a/timer.cpp b/timer.cpp
new file mode 100644
index 0000000..0aaf7d8
--- /dev/null
+++ b/timer.cpp
@@ -0,0 +1,127 @@
+#include <chrono>
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+
+#include "timer.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+namespace phosphor
+{
+namespace network
+{
+
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+// Initializes the timer object
+void Timer::initialize()
+{
+ // This can not be called more than once.
+ if (eventSource)
+ {
+ log<level::ERR>("Timer already initialized");
+ elog<InternalFailure>();
+ }
+
+ auto r = sd_event_default(&timeEvent);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure in creating the sd_event",
+ entry("ERROR=%d", r));
+
+ elog<InternalFailure>();
+ }
+
+ // Add infinite expiration time
+ r = sd_event_add_time(timeEvent,
+ &eventSource,
+ CLOCK_MONOTONIC, // Time base
+ UINT64_MAX, // Expire time - way long time
+ 0, // Use default event accuracy
+ timeoutHandler, // Callback handler on timeout
+ this); // User data
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set initial expiration time value",
+ entry("ERROR=%d", r));
+
+ elog<InternalFailure>();
+ }
+
+ // Disable the timer for now
+ r = setTimer(SD_EVENT_OFF);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to disable timer",
+ entry("ERROR=%d", r));
+
+ elog<InternalFailure>();
+ }
+ return;
+}
+
+/** @brief callback handler on timeout */
+int Timer::timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData)
+{
+ auto timer = static_cast<Timer*>(userData);
+ timer->expired = true;
+
+ // Call optional user call back function if available
+ if (timer->userCallBack)
+ {
+ timer->userCallBack();
+ }
+
+ log<level::INFO>("Timer expired");
+ return 0;
+}
+
+// Gets the time from steady_clock
+std::chrono::microseconds Timer::getTime()
+{
+ using namespace std::chrono;
+ auto usec = steady_clock::now().time_since_epoch();
+ return duration_cast<microseconds>(usec);
+}
+
+// Enables or disables the timer
+int Timer::setTimer(int action)
+{
+ return sd_event_source_set_enabled(eventSource, action);
+}
+
+// Sets the time and arms the timer
+int Timer::startTimer(std::chrono::microseconds timeValue)
+{
+ // Disable the timer
+ setTimer(SD_EVENT_OFF);
+ expired = false;
+
+ // Get the current MONOTONIC time and add the delta
+ auto expireTime = getTime() + timeValue;
+
+ // Set the time
+ auto r = sd_event_source_set_time(eventSource, expireTime.count());
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set timer",
+ entry("ERROR=%d", r));
+
+ elog<InternalFailure>();
+ }
+
+ // A ONESHOT timer means that when the timer goes off,
+ // its moves to disabled state.
+ r = setTimer(SD_EVENT_ONESHOT);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to start timer",
+ entry("ERROR=%d", r));
+
+ elog<InternalFailure>();
+ }
+ return r;
+}
+
+} // namespace network
+} // namespace phosphor
diff --git a/timer.hpp b/timer.hpp
new file mode 100644
index 0000000..408ded4
--- /dev/null
+++ b/timer.hpp
@@ -0,0 +1,99 @@
+#pragma once
+
+#include <chrono>
+#include <functional>
+#include <systemd/sd-event.h>
+
+namespace phosphor
+{
+namespace network
+{
+
+/** @class Timer
+ * @brief Usage would be,instantiate the timer with the call back
+ * and start the timer for the given time.
+ */
+class Timer
+{
+ public:
+ /** @brief Only need the default Timer */
+ Timer() = delete;
+ Timer(const Timer&) = delete;
+ Timer& operator=(const Timer&) = delete;
+ Timer(Timer&&) = delete;
+ Timer& operator=(Timer&&) = delete;
+
+ /** @brief Constructs timer object
+ *
+ * @param[in] funcCallBack - optional function callback for timer
+ * expirations
+ */
+ Timer(std::function<void()> userCallBack = nullptr):
+ userCallBack(userCallBack)
+ {
+ // Initialize the timer
+ initialize();
+ }
+
+ ~Timer()
+ {
+ if (eventSource)
+ {
+ eventSource = sd_event_source_unref(eventSource);
+ }
+ if(timeEvent)
+ {
+ timeEvent = sd_event_unref(timeEvent);
+ }
+ }
+
+ inline auto isExpired() const
+ {
+ return expired;
+ }
+
+ /** @brief Starts the timer with specified expiration value.
+ * input is an offset from the current steady_clock
+ */
+ int startTimer(std::chrono::microseconds usec);
+
+ /** @brief Enables / disables the timer */
+ int setTimer(int action);
+
+ private:
+ /** @brief the sd_event structure */
+ sd_event* timeEvent = nullptr;
+
+ /** @brief Source of events */
+ sd_event_source* eventSource = nullptr;
+
+ bool expired = true;
+
+ /** @brief Initializes the timer object with infinite
+ * expiration time and sets up the callback handler
+ *
+ * @return None.
+ *
+ * @error std::runtime exception thrown
+ */
+ void initialize();
+
+ /** @brief Callback function when timer goes off
+ *
+ * @param[in] eventSource - Source of the event
+ * @param[in] usec - time in micro seconds
+ * @param[in] userData - User data pointer
+ *
+ */
+ static int timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData);
+
+ /** @brief Gets the current time from steady clock */
+ static std::chrono::microseconds getTime();
+
+ /** @brief Optional function to call on timer expiration */
+ std::function<void()> userCallBack;
+};
+
+} // namespace network
+} // namespace phosphor
OpenPOWER on IntegriCloud