171230efdSCarol Wang #pragma once
271230efdSCarol Wang 
3e426b589SAndrew Geissler #include "config.h"
4e426b589SAndrew Geissler 
5e426b589SAndrew Geissler #include <sdbusplus/bus.hpp>
66a5db3d3SCarol Wang #include <sdeventplus/event.hpp>
76a5db3d3SCarol Wang #include <sdeventplus/utility/timer.hpp>
871230efdSCarol Wang #include <xyz/openbmc_project/State/ScheduledHostTransition/server.hpp>
971230efdSCarol Wang 
104ca6f3f4SCarol Wang class TestScheduledHostTransition;
114ca6f3f4SCarol Wang 
1271230efdSCarol Wang namespace phosphor
1371230efdSCarol Wang {
1471230efdSCarol Wang namespace state
1571230efdSCarol Wang {
1671230efdSCarol Wang namespace manager
1771230efdSCarol Wang {
1871230efdSCarol Wang 
196a5db3d3SCarol Wang using Transition =
206a5db3d3SCarol Wang     sdbusplus::xyz::openbmc_project::State::server::Host::Transition;
21f053e6feSPatrick Williams using ScheduledHostTransitionInherit = sdbusplus::server::object_t<
2271230efdSCarol Wang     sdbusplus::xyz::openbmc_project::State::server::ScheduledHostTransition>;
2371230efdSCarol Wang 
2471230efdSCarol Wang /** @class ScheduledHostTransition
2571230efdSCarol Wang  *  @brief Scheduled host transition implementation.
2671230efdSCarol Wang  *  @details A concrete implementation for
2771230efdSCarol Wang  *  xyz.openbmc_project.State.ScheduledHostTransition
2871230efdSCarol Wang  */
2971230efdSCarol Wang class ScheduledHostTransition : public ScheduledHostTransitionInherit
3071230efdSCarol Wang {
3171230efdSCarol Wang   public:
32f053e6feSPatrick Williams     ScheduledHostTransition(sdbusplus::bus_t& bus, const char* objPath,
33211d972dSPatrick Williams                             size_t id, const sdeventplus::Event& event) :
3476070747SPatrick Williams         ScheduledHostTransitionInherit(
3576070747SPatrick Williams             bus, objPath, ScheduledHostTransition::action::defer_emit),
36211d972dSPatrick Williams         bus(bus), id(id), event(event),
37*bd28f025SWilliam A. Kennington III         timer(event, [this](auto&) { callback(); })
3871230efdSCarol Wang     {
39ef7abe19SCarol Wang         initialize();
401dbbef42SCarol Wang 
411dbbef42SCarol Wang         restoreScheduledValues();
421dbbef42SCarol Wang 
431dbbef42SCarol Wang         // We deferred this until we could get our property correct
441dbbef42SCarol Wang         this->emit_object_added();
4571230efdSCarol Wang     }
4671230efdSCarol Wang 
47ef7abe19SCarol Wang     ~ScheduledHostTransition();
4871230efdSCarol Wang 
4971230efdSCarol Wang     /**
5071230efdSCarol Wang      * @brief Handle with scheduled time
5171230efdSCarol Wang      *
5271230efdSCarol Wang      * @param[in] value - The seconds since epoch
5371230efdSCarol Wang      * @return The time for the transition. It is the same as the input value if
5471230efdSCarol Wang      * it is set successfully. Otherwise, it won't return value, but throw an
5571230efdSCarol Wang      * error.
5671230efdSCarol Wang      **/
5771230efdSCarol Wang     uint64_t scheduledTime(uint64_t value) override;
584ca6f3f4SCarol Wang 
594ca6f3f4SCarol Wang   private:
604ca6f3f4SCarol Wang     friend class TestScheduledHostTransition;
616a5db3d3SCarol Wang 
626a5db3d3SCarol Wang     /** @brief sdbusplus bus client connection */
63f053e6feSPatrick Williams     sdbusplus::bus_t& bus;
646a5db3d3SCarol Wang 
65211d972dSPatrick Williams     /** @brief Host id. **/
66211d972dSPatrick Williams     const size_t id = 0;
67211d972dSPatrick Williams 
68ef7abe19SCarol Wang     /** @brief sdbusplus event */
69ef7abe19SCarol Wang     const sdeventplus::Event& event;
70ef7abe19SCarol Wang 
716a5db3d3SCarol Wang     /** @brief Timer used for host transition with seconds */
726a5db3d3SCarol Wang     sdeventplus::utility::Timer<sdeventplus::ClockId::RealTime> timer;
736a5db3d3SCarol Wang 
74ef7abe19SCarol Wang     /** @brief The fd for time change event */
75ef7abe19SCarol Wang     int timeFd = -1;
76ef7abe19SCarol Wang 
774ca6f3f4SCarol Wang     /** @brief Get current time
784ca6f3f4SCarol Wang      *
794ca6f3f4SCarol Wang      *  @return - return current epoch time
804ca6f3f4SCarol Wang      */
814ca6f3f4SCarol Wang     std::chrono::seconds getTime();
826a5db3d3SCarol Wang 
836a5db3d3SCarol Wang     /** @brief Implement host transition
846a5db3d3SCarol Wang      *
856a5db3d3SCarol Wang      *  @return - Does not return anything. Error will result in exception
866a5db3d3SCarol Wang      *            being thrown
876a5db3d3SCarol Wang      */
886a5db3d3SCarol Wang     void hostTransition();
896a5db3d3SCarol Wang 
906a5db3d3SCarol Wang     /** @brief Used by the timer to do host transition */
916a5db3d3SCarol Wang     void callback();
92ef7abe19SCarol Wang 
93ef7abe19SCarol Wang     /** @brief Initialize timerFd related resource */
94ef7abe19SCarol Wang     void initialize();
95ef7abe19SCarol Wang 
96ef7abe19SCarol Wang     /** @brief The callback function on system time change
97ef7abe19SCarol Wang      *
98ef7abe19SCarol Wang      * @param[in] es - Source of the event
99ef7abe19SCarol Wang      * @param[in] fd - File descriptor of the timer
100ef7abe19SCarol Wang      * @param[in] revents - Not used
101ef7abe19SCarol Wang      * @param[in] userdata - User data pointer
102ef7abe19SCarol Wang      */
103ef7abe19SCarol Wang     static int onTimeChange(sd_event_source* es, int fd, uint32_t revents,
104ef7abe19SCarol Wang                             void* userdata);
105ef7abe19SCarol Wang 
106ef7abe19SCarol Wang     /** @brief The deleter of sd_event_source */
107ef7abe19SCarol Wang     std::function<void(sd_event_source*)> sdEventSourceDeleter =
108ef7abe19SCarol Wang         [](sd_event_source* p) {
109ef7abe19SCarol Wang             if (p)
110ef7abe19SCarol Wang             {
111ef7abe19SCarol Wang                 sd_event_source_unref(p);
112ef7abe19SCarol Wang             }
113ef7abe19SCarol Wang         };
114ef7abe19SCarol Wang 
115ef7abe19SCarol Wang     using SdEventSource =
116ef7abe19SCarol Wang         std::unique_ptr<sd_event_source, decltype(sdEventSourceDeleter)>;
117ef7abe19SCarol Wang 
118ef7abe19SCarol Wang     /** @brief The event source on system time change */
119ef7abe19SCarol Wang     SdEventSource timeChangeEventSource{nullptr, sdEventSourceDeleter};
120ef7abe19SCarol Wang 
121ef7abe19SCarol Wang     /** @brief Handle with the process when bmc time is changed*/
122ef7abe19SCarol Wang     void handleTimeUpdates();
1231dbbef42SCarol Wang 
1241dbbef42SCarol Wang     /** @brief Serialize the scheduled values */
1251dbbef42SCarol Wang     void serializeScheduledValues();
1261dbbef42SCarol Wang 
1271dbbef42SCarol Wang     /** @brief Deserialize the scheduled values
1281dbbef42SCarol Wang      *
1291dbbef42SCarol Wang      *  @param[out] time - Deserialized scheduled time
1301dbbef42SCarol Wang      *  @param[out] trans - Deserialized requested transition
1311dbbef42SCarol Wang      *
1321dbbef42SCarol Wang      *  @return bool - true if successful, false otherwise
1331dbbef42SCarol Wang      */
1341dbbef42SCarol Wang     bool deserializeScheduledValues(uint64_t& time, Transition& trans);
1351dbbef42SCarol Wang 
1361dbbef42SCarol Wang     /** @brief Restore scheduled time and requested transition from persisted
1371dbbef42SCarol Wang      * file */
1381dbbef42SCarol Wang     void restoreScheduledValues();
13971230efdSCarol Wang };
14071230efdSCarol Wang } // namespace manager
14171230efdSCarol Wang } // namespace state
14271230efdSCarol Wang } // namespace phosphor
143