Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(716)

Side by Side Diff: components/proximity_auth/cryptauth/sync_scheduler_impl.cc

Issue 2502343003: Moved //components/proximity_auth/cryptauth to //components/cryptauth. (Closed)
Patch Set: Fixed proto #includes. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/proximity_auth/cryptauth/sync_scheduler_impl.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <limits>
10
11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/rand_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "components/proximity_auth/logging/logging.h"
17
18 namespace proximity_auth {
19
20 namespace {
21
22 // Returns a human readable string given a |time_delta|.
23 std::string TimeDeltaToString(const base::TimeDelta& time_delta) {
24 if (time_delta.InDays() > 0)
25 return base::StringPrintf("%d days", time_delta.InDays());
26
27 if (time_delta.InHours() > 0)
28 return base::StringPrintf("%d hours", time_delta.InHours());
29
30 if (time_delta.InMinutes() > 0)
31 return base::StringPrintf("%d minutes", time_delta.InMinutes());
32
33 return base::StringPrintf("%d seconds",
34 base::saturated_cast<int>(time_delta.InSeconds()));
35 }
36
37 } // namespace
38
39 SyncSchedulerImpl::SyncSchedulerImpl(Delegate* delegate,
40 base::TimeDelta refresh_period,
41 base::TimeDelta base_recovery_period,
42 double max_jitter_ratio,
43 const std::string& scheduler_name)
44 : delegate_(delegate),
45 refresh_period_(refresh_period),
46 base_recovery_period_(base_recovery_period),
47 max_jitter_ratio_(max_jitter_ratio),
48 scheduler_name_(scheduler_name),
49 strategy_(Strategy::PERIODIC_REFRESH),
50 sync_state_(SyncState::NOT_STARTED),
51 failure_count_(0),
52 weak_ptr_factory_(this) {
53 }
54
55 SyncSchedulerImpl::~SyncSchedulerImpl() {
56 }
57
58 void SyncSchedulerImpl::Start(
59 const base::TimeDelta& elapsed_time_since_last_sync,
60 Strategy strategy) {
61 strategy_ = strategy;
62 sync_state_ = SyncState::WAITING_FOR_REFRESH;
63 // We reset the failure backoff when the scheduler is started again, as the
64 // configuration that caused the previous attempts to fail most likely won't
65 // be present after a restart.
66 if (strategy_ == Strategy::AGGRESSIVE_RECOVERY)
67 failure_count_ = 1;
68
69 // To take into account the time waited when the system is powered off, we
70 // subtract the time elapsed with a normal sync period to the initial time
71 // to wait.
72 base::TimeDelta sync_delta =
73 GetJitteredPeriod() - elapsed_time_since_last_sync;
74
75 // The elapsed time may be negative if the system clock is changed. In this
76 // case, we immediately schedule a sync.
77 base::TimeDelta zero_delta = base::TimeDelta::FromSeconds(0);
78 if (elapsed_time_since_last_sync < zero_delta || sync_delta < zero_delta)
79 sync_delta = zero_delta;
80
81 ScheduleNextSync(sync_delta);
82 }
83
84 void SyncSchedulerImpl::ForceSync() {
85 OnTimerFired();
86 }
87
88 base::TimeDelta SyncSchedulerImpl::GetTimeToNextSync() const {
89 if (!timer_)
90 return base::TimeDelta::FromSeconds(0);
91 return timer_->GetCurrentDelay();
92 }
93
94 SyncScheduler::Strategy SyncSchedulerImpl::GetStrategy() const {
95 return strategy_;
96 }
97
98 SyncScheduler::SyncState SyncSchedulerImpl::GetSyncState() const {
99 return sync_state_;
100 }
101
102 void SyncSchedulerImpl::OnTimerFired() {
103 timer_.reset();
104 if (strategy_ == Strategy::PERIODIC_REFRESH) {
105 PA_LOG(INFO) << "Timer fired for periodic refresh, making request...";
106 sync_state_ = SyncState::SYNC_IN_PROGRESS;
107 } else if (strategy_ == Strategy::AGGRESSIVE_RECOVERY) {
108 PA_LOG(INFO) << "Timer fired for aggressive recovery, making request...";
109 sync_state_ = SyncState::SYNC_IN_PROGRESS;
110 } else {
111 NOTREACHED();
112 return;
113 }
114
115 delegate_->OnSyncRequested(
116 base::MakeUnique<SyncRequest>(weak_ptr_factory_.GetWeakPtr()));
117 }
118
119 std::unique_ptr<base::Timer> SyncSchedulerImpl::CreateTimer() {
120 bool retain_user_task = false;
121 bool is_repeating = false;
122 return base::MakeUnique<base::Timer>(retain_user_task, is_repeating);
123 }
124
125 void SyncSchedulerImpl::ScheduleNextSync(const base::TimeDelta& sync_delta) {
126 if (sync_state_ != SyncState::WAITING_FOR_REFRESH) {
127 PA_LOG(ERROR) << "Unexpected state when scheduling next sync: sync_state="
128 << static_cast<int>(sync_state_);
129 return;
130 }
131
132 bool is_aggressive_recovery = (strategy_ == Strategy::AGGRESSIVE_RECOVERY);
133 PA_LOG(INFO) << "Scheduling next sync for " << scheduler_name_ << ":\n"
134 << " Strategy: " << (is_aggressive_recovery
135 ? "Aggressive Recovery"
136 : "Periodic Refresh") << "\n"
137 << " Time Delta: " << TimeDeltaToString(sync_delta)
138 << (is_aggressive_recovery
139 ? base::StringPrintf(
140 "\n Previous Failures: %d",
141 base::saturated_cast<int>(failure_count_))
142 : "");
143
144 timer_ = CreateTimer();
145 timer_->Start(FROM_HERE, sync_delta,
146 base::Bind(&SyncSchedulerImpl::OnTimerFired,
147 weak_ptr_factory_.GetWeakPtr()));
148 }
149
150 void SyncSchedulerImpl::OnSyncCompleted(bool success) {
151 if (sync_state_ != SyncState::SYNC_IN_PROGRESS) {
152 PA_LOG(ERROR) << "Unexpected state when sync completed: sync_state="
153 << static_cast<int>(sync_state_)
154 << ", strategy_=" << static_cast<int>(strategy_);
155 return;
156 }
157 sync_state_ = SyncState::WAITING_FOR_REFRESH;
158
159 if (success) {
160 strategy_ = Strategy::PERIODIC_REFRESH;
161 failure_count_ = 0;
162 } else {
163 strategy_ = Strategy::AGGRESSIVE_RECOVERY;
164 ++failure_count_;
165 }
166
167 ScheduleNextSync(GetJitteredPeriod());
168 }
169
170 base::TimeDelta SyncSchedulerImpl::GetJitteredPeriod() {
171 double jitter = 2 * max_jitter_ratio_ * (base::RandDouble() - 0.5);
172 base::TimeDelta period = GetPeriod();
173 base::TimeDelta jittered_time_delta = period + (period * jitter);
174 if (jittered_time_delta.InMilliseconds() < 0)
175 jittered_time_delta = base::TimeDelta::FromMilliseconds(0);
176 return jittered_time_delta;
177 }
178
179 base::TimeDelta SyncSchedulerImpl::GetPeriod() {
180 if (strategy_ == Strategy::PERIODIC_REFRESH) {
181 return refresh_period_;
182 } else if (strategy_ == Strategy::AGGRESSIVE_RECOVERY && failure_count_ > 0) {
183 // The backoff for each consecutive failure is exponentially doubled until
184 // it is equal to the normal refresh period.
185 // Note: |backoff_factor| may evaulate to INF if |failure_count_| is large,
186 // but multiplication operations for TimeDelta objects are saturated.
187 double backoff_factor = pow(2, failure_count_ - 1);
188 base::TimeDelta backoff_period = base_recovery_period_ * backoff_factor;
189 return backoff_period < refresh_period_ ? backoff_period : refresh_period_;
190 } else {
191 PA_LOG(ERROR) << "Error getting period for strategy: "
192 << static_cast<int>(strategy_);
193 return base::TimeDelta();
194 }
195 }
196
197 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698