blob: b41412c22778bd35c2d411ac76fd6b5e8c8eb905 [file] [log] [blame] [edit]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/devices/bin/driver_manager/bootup_tracker.h"
#include <lib/async/cpp/time.h>
#include <src/devices/lib/log/log.h>
#include "src/devices/bin/driver_manager/bind/bind_manager.h"
namespace driver_manager {
namespace {
zx::duration kBootupTimeoutDuration = zx::sec(2);
zx::duration kLastUpdatedTimeoutDuration = zx::sec(10);
} // namespace
void BootupTracker::Start() { UpdateTrackerAndResetTimer(); }
void BootupTracker::WaitForBootup(fit::callback<void()> callback) {
if (bootup_done_) {
callback();
} else {
callbacks_.push_back(std::move(callback));
}
}
void BootupTracker::NotifyNewStartRequest(std::string node_moniker, std::string driver_url) {
if (outstanding_start_requests_.find(node_moniker) != outstanding_start_requests_.end()) {
fdf_log::warn("Bootup tracker received conflicting start requests for node {}", node_moniker);
}
outstanding_start_requests_[node_moniker] = driver_url;
UpdateTrackerAndResetTimer();
}
void BootupTracker::NotifyStartComplete(std::string node_moniker) {
if (auto itr = outstanding_start_requests_.find(node_moniker);
itr != outstanding_start_requests_.end()) {
outstanding_start_requests_.erase(itr);
} else {
fdf_log::info("Bootup tracker notified for an unknown start request for {}", node_moniker);
}
UpdateTrackerAndResetTimer();
}
void BootupTracker::NotifyBindingChanged() { UpdateTrackerAndResetTimer(); }
void BootupTracker::BootupDoneForTesting() {
for (auto& callback : callbacks_) {
callback();
}
callbacks_.clear();
bootup_done_ = true;
}
void BootupTracker::CheckBootupDone() {
if (IsUpdateDeadlineExceeded()) {
fdf_log::warn("Deadline exceeded in the bootup tracker with:");
fdf_log::warn(" {} unfinished start requests:", outstanding_start_requests_.size());
for (const auto& [moniker, url] : outstanding_start_requests_) {
fdf_log::warn(" - {} - {}", moniker, url);
}
if (bind_manager_->HasOngoingBind()) {
fdf_log::warn(" a hanging bind process in the bind manager");
}
}
if (!outstanding_start_requests_.empty() || bind_manager_->HasOngoingBind()) {
ResetBootupTimer();
return;
}
// LINT.IfChange
fdf_log::info("Bootup completed.");
// LINT.ThenChange(//tools/testing/testrunner/tester.go)
for (auto& callback : callbacks_) {
callback();
}
callbacks_.clear();
bootup_done_ = true;
}
void BootupTracker::UpdateTrackerAndResetTimer() {
last_update_timestamp_ = async::Now(dispatcher_);
ResetBootupTimer();
}
void BootupTracker::OnBootupTimeout() {
bootup_timeout_ = true;
CheckBootupDone();
}
bool BootupTracker::IsUpdateDeadlineExceeded() const {
auto time_delta = async::Now(dispatcher_) - last_update_timestamp_;
return time_delta >= kLastUpdatedTimeoutDuration;
}
void BootupTracker::ResetBootupTimer() {
if (bootup_done_) {
return;
}
if (bootup_timeout_task_.is_pending()) {
bootup_timeout_task_.Cancel();
}
bootup_timeout_task_.PostDelayed(dispatcher_, kBootupTimeoutDuration);
}
} // namespace driver_manager