| // Copyright 2018 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/uploader/upload_scheduler.h" |
| |
| #include "src/public/lib/status.h" |
| #include "src/public/lib/statusor/statusor.h" |
| |
| namespace cobalt::uploader { |
| |
| // Definition of the static constant declared in shipping_manager.h. |
| // This must be less than 2^31. There appears to be a bug in |
| // std::condition_variable::wait_for() in which setting the wait time to |
| // std::chrono::seconds::max() effectively sets the wait time to zero. |
| constexpr std::chrono::seconds UploadScheduler::kMaxSeconds(999999999); |
| |
| lib::statusor::StatusOr<UploadScheduler> UploadScheduler::Create(UploadScheduleConfig cfg) { |
| if (cfg.jitter < 0.0 || cfg.jitter >= 1.0) { |
| return Status(StatusCode::INVALID_ARGUMENT, "Jitter must be in the range [0.0, 1.0)"); |
| } |
| if (cfg.min_interval.count() < 0) { |
| return Status(StatusCode::INVALID_ARGUMENT, |
| "min_interval must be greater than or equal to zero"); |
| } |
| if (cfg.initial_interval.count() > cfg.target_interval.count()) { |
| return Status(StatusCode::INVALID_ARGUMENT, |
| "initial_interval must be less than or equal to target_interval"); |
| } |
| if (cfg.min_interval.count() > cfg.target_interval.count()) { |
| return Status(StatusCode::INVALID_ARGUMENT, |
| "min_interval must be less than or equal to target_interval"); |
| } |
| if (cfg.target_interval.count() > kMaxSeconds.count()) { |
| return Status(StatusCode::INVALID_ARGUMENT, "target_interval must be less than kMaxSeconds"); |
| } |
| |
| return UploadScheduler(cfg); |
| } |
| |
| UploadScheduler::UploadScheduler(UploadScheduleConfig config) |
| : current_interval_(config.initial_interval), |
| target_interval_(config.target_interval), |
| min_interval_(config.min_interval), |
| jitter_(config.jitter) {} |
| |
| std::chrono::seconds UploadScheduler::Interval() { |
| auto interval = current_interval_; |
| if (current_interval_ < target_interval_) { |
| current_interval_ *= 2; |
| if (current_interval_ >= target_interval_) { |
| current_interval_ = target_interval_; |
| } |
| } |
| int64_t interval_count = std::chrono::duration_cast<std::chrono::seconds>(interval).count(); |
| if (interval_count == 0) { |
| return interval; |
| } |
| |
| // Generate a random offset between [-n, n): n = jitter*current_interval. |
| auto unscaled_offset = static_cast<float>(rand() % (2 * interval_count) - interval_count); |
| std::chrono::seconds offset = std::chrono::seconds(static_cast<int>(unscaled_offset * jitter_)); |
| return interval + offset; |
| } |
| |
| } // namespace cobalt::uploader |