diff options
author | Ratan Gupta <ratagupt@in.ibm.com> | 2018-03-12 16:21:37 +0530 |
---|---|---|
committer | Ratan Gupta <ratagupt@in.ibm.com> | 2018-03-12 16:26:56 +0530 |
commit | 408013630a1ffded4fe035f1e39b8fcac85eccea (patch) | |
tree | 050f5d7077f65118a9b7ec634f5c57a747c34b9b | |
parent | 7e9e2ef68a1c53e022970d85566945d5bdc5a78e (diff) | |
download | phosphor-net-ipmid-408013630a1ffded4fe035f1e39b8fcac85eccea.tar.gz phosphor-net-ipmid-408013630a1ffded4fe035f1e39b8fcac85eccea.zip |
SetLan: Define the global network timer
As timer is being referred in the provider library
so it should be defined in per process(host-ipmid, net-ipmid)
context.
Defining the timer requires to pull the code of timer in this
repository so adding the timer class.
Change-Id: I4ea5f51fed03dd87d70868b0bc76ff1fb683931c
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | main.cpp | 4 | ||||
-rw-r--r-- | timer.cpp | 110 | ||||
-rw-r--r-- | timer.hpp | 101 |
4 files changed, 217 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 33735fd..1d1a370 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,8 @@ netipmid_SOURCES = \ sol_module.hpp \ sol_module.cpp \ settings.hpp \ - settings.cpp + settings.cpp \ + timer.cpp netipmid_CPPFLAGS = -DNET_IPMID_LIB_PATH=\"/usr/lib/net-ipmid/\" @@ -20,6 +20,7 @@ #include "provider_registration.hpp" #include "socket_channel.hpp" #include "sol_module.hpp" +#include "timer.hpp" // Tuple of Global Singletons session::Manager manager; @@ -32,6 +33,9 @@ std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&, sd_bus* bus = nullptr; +// Global timer for network changes +std::unique_ptr<phosphor::ipmi::Timer> networkTimer = nullptr; + FILE* ipmidbus = nullptr; unsigned short g_sel_reserve = 0xFFFF; sd_bus_slot* ipmid_slot = nullptr; diff --git a/timer.cpp b/timer.cpp new file mode 100644 index 0000000..06965de --- /dev/null +++ b/timer.cpp @@ -0,0 +1,110 @@ +#include <chrono> +#include <phosphor-logging/log.hpp> +#include "timer.hpp" +namespace phosphor +{ +namespace ipmi +{ + +using namespace phosphor::logging; + +// Initializes the timer object +void Timer::initialize() +{ + // This can not be called more than once. + if (eventSource) + { + throw std::runtime_error("Timer already initialized"); + } + + // Add infinite expiration time + auto 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=%s", strerror(-r))); + + throw std::runtime_error("Timer initialization failed"); + } + + // Disable the timer for now + r = setTimer(SD_EVENT_OFF); + if (r < 0) + { + log<level::ERR>("Failure to disable timer", + entry("ERROR=%s", strerror(-r))); + + throw std::runtime_error("Disabling the timer failed"); + } + 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; + + log<level::INFO>("Timer expired"); + // Call optional user call back function if available + if(timer->userCallBack) + { + timer->userCallBack(); + } + + sd_event_source_set_enabled(eventSource, SD_EVENT_OFF); + 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=%s", strerror(-r))); + return r; + } + + // 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=%s", strerror(-r))); + } + return r; +} + +} // namespace ipmi +} // namespace phosphor diff --git a/timer.hpp b/timer.hpp new file mode 100644 index 0000000..e39d85c --- /dev/null +++ b/timer.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include <chrono> +#include <functional> +#include <systemd/sd-event.h> +namespace phosphor +{ +namespace ipmi +{ + +/** @class Timer + * @brief Manages starting watchdog timers and handling timeouts + */ +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] events - sd_event pointer + * @param[in] funcCallBack - optional function callback for timer + * expirations + */ + Timer(sd_event* events, + std::function<void()> userCallBack = nullptr) + : timeEvent(events), userCallBack(userCallBack) + { + // Initialize the timer + initialize(); + } + + ~Timer() + { + if (eventSource) + { + eventSource = sd_event_source_unref(eventSource); + } + } + + 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; + + /** @brief Returns if the associated timer is expired + * + * This is set to true when the timeoutHandler is called into + */ + 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 + * + * On getting the signal, initiate the hard power off request + * + * @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 ipmi +} // namespace phosphor |