blob: 6e64833c945d1ecbd964eb114ac4a62c87026f49 [file] [edit]
#include "polling_state_monitor.h"
#include <memory>
#include <string>
#include <utility>
#include "daemon_context.h"
#include "safepower_agent.pb.h"
#include "state_updater.h"
#include "absl/functional/bind_front.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
namespace safepower_agent {
PollingStateMonitor::PollingStateMonitor(
std::string entity_tag, absl::Duration interval,
std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>>
system_state_updater,
std::string monitor_name)
: monitor_name_(std::move(monitor_name)),
entity_tag_(std::move(entity_tag)),
interval_(interval),
system_state_updater_(std::move(system_state_updater)) {}
void PollingStateMonitor::StopTimer() {
if (task_name_.empty()) {
return;
}
LOG(INFO) << "Stopping " << task_name_;
absl::Status status = DaemonContext::Get().scheduler().CancelCall(task_name_);
if (!status.ok()) {
LOG(WARNING) << "Failed to cancel polling state monitor: " << status;
}
task_name_.clear();
}
void PollingStateMonitor::StartTimer(absl::Duration interval) {
LOG(INFO) << "Starting " << monitor_name_ << " for " << entity_tag_
<< " with interval " << interval;
std::string task_name = absl::StrCat(monitor_name_, "_", entity_tag_);
absl::Status status = DaemonContext::Get().scheduler().PeriodicCall(
absl::bind_front(&PollingStateMonitor::Check, this), interval, task_name);
if (!status.ok()) {
LOG(DFATAL) << "Failed to start " << monitor_name_ << ": " << status;
return;
}
task_name_ = std::move(task_name);
}
void PollingStateMonitor::Pause() {
{
absl::MutexLock lock(task_mutex_);
if (task_name_.empty()) {
LOG(DFATAL) << "PollingStateMonitor paused while task not started";
}
StopTimer();
OnPause();
}
activate_callback_handle_ = system_state_updater_->OnActive(
absl::bind_front(&PollingStateMonitor::Resume, this));
}
void PollingStateMonitor::Resume() {
{
absl::MutexLock lock(task_mutex_);
if (!task_name_.empty()) {
LOG(DFATAL) << "PollingStateMonitor resumed while task started";
return;
}
StartTimer(interval_);
}
idle_callback_handle_ = system_state_updater_->OnIdle(
absl::bind_front(&PollingStateMonitor::Pause, this));
}
absl::Status PollingStateMonitor::Start() {
// Will start immediately if the state updater is idle.
activate_callback_handle_ = system_state_updater_->OnActive(
absl::bind_front(&PollingStateMonitor::Resume, this));
return absl::OkStatus();
}
PollingStateMonitor::~PollingStateMonitor() {
idle_callback_handle_.TryCancel();
idle_callback_handle_.Wait();
activate_callback_handle_.TryCancel();
activate_callback_handle_.Wait();
if (!task_mutex_.try_lock()) {
LOG(DFATAL) << "PollingStateMonitor destroyed while mutex was held";
task_mutex_.lock();
}
StopTimer();
task_mutex_.unlock();
}
} // namespace safepower_agent