OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/domain_reliability/scheduler.h" | 5 #include "components/domain_reliability/scheduler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/metrics/field_trial.h" | 9 #include "base/metrics/field_trial.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "components/domain_reliability/config.h" | 11 #include "components/domain_reliability/config.h" |
12 #include "components/domain_reliability/util.h" | 12 #include "components/domain_reliability/util.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 const int kInvalidCollectorIndex = -1; | 16 const unsigned kInvalidCollectorIndex = -1; |
17 | 17 |
18 const int kDefaultMinimumUploadDelaySec = 60; | 18 const unsigned kDefaultMinimumUploadDelaySec = 60; |
19 const int kDefaultMaximumUploadDelaySec = 300; | 19 const unsigned kDefaultMaximumUploadDelaySec = 300; |
20 const int kDefaultUploadRetryIntervalSec = 60; | 20 const unsigned kDefaultUploadRetryIntervalSec = 60; |
21 | 21 |
22 const char* kMinimumUploadDelayFieldTrialName = "DomRel-MinimumUploadDelay"; | 22 const char* kMinimumUploadDelayFieldTrialName = "DomRel-MinimumUploadDelay"; |
23 const char* kMaximumUploadDelayFieldTrialName = "DomRel-MaximumUploadDelay"; | 23 const char* kMaximumUploadDelayFieldTrialName = "DomRel-MaximumUploadDelay"; |
24 const char* kUploadRetryIntervalFieldTrialName = "DomRel-UploadRetryInterval"; | 24 const char* kUploadRetryIntervalFieldTrialName = "DomRel-UploadRetryInterval"; |
25 | 25 |
26 int GetIntegerFieldTrialValueOrDefault( | 26 unsigned GetUnsignedFieldTrialValueOrDefault(std::string field_trial_name, |
27 std::string field_trial_name, | 27 unsigned default_value) { |
28 int default_value) { | |
29 if (!base::FieldTrialList::TrialExists(field_trial_name)) | 28 if (!base::FieldTrialList::TrialExists(field_trial_name)) |
30 return default_value; | 29 return default_value; |
31 | 30 |
32 std::string group_name = base::FieldTrialList::FindFullName(field_trial_name); | 31 std::string group_name = base::FieldTrialList::FindFullName(field_trial_name); |
33 int value; | 32 unsigned value; |
34 if (!base::StringToInt(group_name, &value)) { | 33 if (!base::StringToUint(group_name, &value)) { |
35 LOG(ERROR) << "Expected integer for field trial " << field_trial_name | 34 LOG(ERROR) << "Expected unsigned integer for field trial " |
36 << " group name, but got \"" << group_name << "\"."; | 35 << field_trial_name << " group name, but got \"" << group_name |
36 << "\"."; | |
37 return default_value; | 37 return default_value; |
38 } | 38 } |
39 | 39 |
40 return value; | 40 return value; |
41 } | 41 } |
42 | 42 |
43 } // namespace | 43 } // namespace |
44 | 44 |
45 namespace domain_reliability { | 45 namespace domain_reliability { |
46 | 46 |
47 // static | 47 // static |
48 DomainReliabilityScheduler::Params | 48 DomainReliabilityScheduler::Params |
49 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults() { | 49 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults() { |
50 DomainReliabilityScheduler::Params params; | 50 DomainReliabilityScheduler::Params params; |
51 | 51 |
52 params.minimum_upload_delay = base::TimeDelta::FromSeconds( | 52 params.minimum_upload_delay = |
53 GetIntegerFieldTrialValueOrDefault(kMinimumUploadDelayFieldTrialName, | 53 base::TimeDelta::FromSeconds(GetUnsignedFieldTrialValueOrDefault( |
54 kDefaultMinimumUploadDelaySec)); | 54 kMinimumUploadDelayFieldTrialName, kDefaultMinimumUploadDelaySec)); |
55 params.maximum_upload_delay = base::TimeDelta::FromSeconds( | 55 params.maximum_upload_delay = |
56 GetIntegerFieldTrialValueOrDefault(kMaximumUploadDelayFieldTrialName, | 56 base::TimeDelta::FromSeconds(GetUnsignedFieldTrialValueOrDefault( |
57 kDefaultMaximumUploadDelaySec)); | 57 kMaximumUploadDelayFieldTrialName, kDefaultMaximumUploadDelaySec)); |
58 params.upload_retry_interval = base::TimeDelta::FromSeconds( | 58 params.upload_retry_interval = |
59 GetIntegerFieldTrialValueOrDefault(kUploadRetryIntervalFieldTrialName, | 59 base::TimeDelta::FromSeconds(GetUnsignedFieldTrialValueOrDefault( |
60 kDefaultUploadRetryIntervalSec)); | 60 kUploadRetryIntervalFieldTrialName, kDefaultUploadRetryIntervalSec)); |
61 | 61 |
62 return params; | 62 return params; |
63 } | 63 } |
64 | 64 |
65 DomainReliabilityScheduler::DomainReliabilityScheduler( | 65 DomainReliabilityScheduler::DomainReliabilityScheduler( |
66 MockableTime* time, | 66 MockableTime* time, |
67 size_t num_collectors, | 67 size_t num_collectors, |
68 const Params& params, | 68 const Params& params, |
69 const ScheduleUploadCallback& callback) | 69 const ScheduleUploadCallback& callback) |
70 : time_(time), | 70 : time_(time), |
71 collectors_(num_collectors), | 71 collectors_(num_collectors), |
72 params_(params), | 72 params_(params), |
73 callback_(callback), | 73 callback_(callback), |
74 upload_pending_(false), | 74 upload_pending_(false), |
75 upload_scheduled_(false), | 75 upload_scheduled_(false), |
76 upload_running_(false), | 76 upload_running_(false), |
77 collector_index_(kInvalidCollectorIndex) { | 77 collector_index_(kInvalidCollectorIndex) { |
78 } | 78 } |
79 | 79 |
80 DomainReliabilityScheduler::~DomainReliabilityScheduler() {} | 80 DomainReliabilityScheduler::~DomainReliabilityScheduler() {} |
81 | 81 |
82 void DomainReliabilityScheduler::OnBeaconAdded() { | 82 void DomainReliabilityScheduler::OnBeaconAdded() { |
83 if (!upload_pending_) | 83 if (!upload_pending_) |
84 first_beacon_time_ = time_->NowTicks(); | 84 first_beacon_time_ = time_->NowTicks(); |
85 upload_pending_ = true; | 85 upload_pending_ = true; |
86 VLOG(2) << "OnBeaconAdded"; | 86 VLOG(2) << "OnBeaconAdded"; |
87 MaybeScheduleUpload(); | 87 MaybeScheduleUpload(); |
88 } | 88 } |
89 | 89 |
90 void DomainReliabilityScheduler::OnUploadStart(int* collector_index_out) { | 90 size_t DomainReliabilityScheduler::OnUploadStart() { |
91 DCHECK(collector_index_out); | |
92 DCHECK(upload_scheduled_); | 91 DCHECK(upload_scheduled_); |
93 DCHECK_EQ(kInvalidCollectorIndex, collector_index_); | 92 DCHECK_EQ(kInvalidCollectorIndex, collector_index_); |
94 upload_scheduled_ = false; | 93 upload_scheduled_ = false; |
95 upload_running_ = true; | 94 upload_running_ = true; |
96 | 95 |
97 base::TimeTicks now = time_->NowTicks(); | 96 base::TimeTicks now = time_->NowTicks(); |
98 base::TimeTicks min_upload_time; | 97 base::TimeTicks min_upload_time; |
99 GetNextUploadTimeAndCollector(now, &min_upload_time, &collector_index_); | 98 GetNextUploadTimeAndCollector(now, &min_upload_time, &collector_index_); |
100 DCHECK(min_upload_time <= now); | 99 DCHECK(min_upload_time <= now); |
101 | 100 |
102 *collector_index_out = collector_index_; | 101 VLOG(1) << "Starting upload to collector " << collector_index_ << "."; |
Ryan Sleevi
2014/04/30 23:58:11
DVLOG? VLOG2? Seems spammy
Deprecated (see juliatuttle)
2014/05/02 19:23:40
Uploads aren't super common, so I'm leaving this.
| |
103 | 102 |
104 VLOG(1) << "Starting upload to collector " << collector_index_ << "."; | 103 return collector_index_; |
105 } | 104 } |
106 | 105 |
107 void DomainReliabilityScheduler::OnUploadComplete(bool success) { | 106 void DomainReliabilityScheduler::OnUploadComplete(bool success) { |
108 DCHECK(upload_running_); | 107 DCHECK(upload_running_); |
109 DCHECK_NE(kInvalidCollectorIndex, collector_index_); | 108 DCHECK_NE(kInvalidCollectorIndex, collector_index_); |
110 upload_running_ = false; | 109 upload_running_ = false; |
111 | 110 |
112 VLOG(1) << "Upload to collector " << collector_index_ | 111 VLOG(1) << "Upload to collector " << collector_index_ |
113 << (success ? " succeeded." : " failed."); | 112 << (success ? " succeeded." : " failed."); |
114 | 113 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 old_first_beacon_time_ = first_beacon_time_; | 145 old_first_beacon_time_ = first_beacon_time_; |
147 | 146 |
148 base::TimeTicks now = time_->NowTicks(); | 147 base::TimeTicks now = time_->NowTicks(); |
149 | 148 |
150 base::TimeTicks min_by_deadline, max_by_deadline; | 149 base::TimeTicks min_by_deadline, max_by_deadline; |
151 min_by_deadline = first_beacon_time_ + params_.minimum_upload_delay; | 150 min_by_deadline = first_beacon_time_ + params_.minimum_upload_delay; |
152 max_by_deadline = first_beacon_time_ + params_.maximum_upload_delay; | 151 max_by_deadline = first_beacon_time_ + params_.maximum_upload_delay; |
153 DCHECK(min_by_deadline <= max_by_deadline); | 152 DCHECK(min_by_deadline <= max_by_deadline); |
154 | 153 |
155 base::TimeTicks min_by_backoff; | 154 base::TimeTicks min_by_backoff; |
156 int collector_index; | 155 size_t collector_index; |
157 GetNextUploadTimeAndCollector(now, &min_by_backoff, &collector_index); | 156 GetNextUploadTimeAndCollector(now, &min_by_backoff, &collector_index); |
158 | 157 |
159 base::TimeDelta min_delay = std::max(min_by_deadline, min_by_backoff) - now; | 158 base::TimeDelta min_delay = std::max(min_by_deadline, min_by_backoff) - now; |
160 base::TimeDelta max_delay = std::max(max_by_deadline, min_by_backoff) - now; | 159 base::TimeDelta max_delay = std::max(max_by_deadline, min_by_backoff) - now; |
161 | 160 |
162 VLOG(1) << "Scheduling upload for between " << min_delay.InSeconds() | 161 VLOG(1) << "Scheduling upload for between " << min_delay.InSeconds() |
163 << " and " << max_delay.InSeconds() << " seconds from now."; | 162 << " and " << max_delay.InSeconds() << " seconds from now."; |
164 | 163 |
165 callback_.Run(min_delay, max_delay); | 164 callback_.Run(min_delay, max_delay); |
166 } | 165 } |
167 | 166 |
168 // TODO(ttuttle): Add min and max interval to config, use that instead. | 167 // TODO(ttuttle): Add min and max interval to config, use that instead. |
168 | |
169 // TODO(ttuttle): Cap min and max intervals received from config. | 169 // TODO(ttuttle): Cap min and max intervals received from config. |
170 | 170 |
171 void DomainReliabilityScheduler::GetNextUploadTimeAndCollector( | 171 void DomainReliabilityScheduler::GetNextUploadTimeAndCollector( |
172 base::TimeTicks now, | 172 base::TimeTicks now, |
173 base::TimeTicks* upload_time_out, | 173 base::TimeTicks* upload_time_out, |
174 int* collector_index_out) { | 174 size_t* collector_index_out) { |
175 DCHECK(upload_time_out); | 175 DCHECK(upload_time_out); |
176 DCHECK(collector_index_out); | 176 DCHECK(collector_index_out); |
177 | 177 |
178 base::TimeTicks min_time; | 178 base::TimeTicks min_time; |
179 int min_index = kInvalidCollectorIndex; | 179 size_t min_index = kInvalidCollectorIndex; |
180 | 180 |
181 for (unsigned i = 0; i < collectors_.size(); ++i) { | 181 for (size_t i = 0; i < collectors_.size(); ++i) { |
182 CollectorState* collector = &collectors_[i]; | 182 CollectorState* collector = &collectors_[i]; |
183 // If a collector is usable, use the first one in the list. | 183 // If a collector is usable, use the first one in the list. |
184 if (collector->failures == 0 || collector->next_upload <= now) { | 184 if (collector->failures == 0 || collector->next_upload <= now) { |
185 min_time = now; | 185 min_time = now; |
186 min_index = i; | 186 min_index = i; |
187 break; | 187 break; |
188 // If not, keep track of which will be usable soonest: | 188 // If not, keep track of which will be usable soonest: |
189 } else if (min_index == kInvalidCollectorIndex || | 189 } else if (min_index == kInvalidCollectorIndex || |
190 collector->next_upload < min_time) { | 190 collector->next_upload < min_time) { |
191 min_time = collector->next_upload; | 191 min_time = collector->next_upload; |
192 min_index = i; | 192 min_index = i; |
193 } | 193 } |
194 } | 194 } |
195 | 195 |
196 DCHECK_NE(kInvalidCollectorIndex, min_index); | 196 DCHECK_NE(kInvalidCollectorIndex, min_index); |
197 *upload_time_out = min_time; | 197 *upload_time_out = min_time; |
198 *collector_index_out = min_index; | 198 *collector_index_out = min_index; |
199 } | 199 } |
200 | 200 |
201 base::TimeDelta DomainReliabilityScheduler::GetUploadRetryInterval( | 201 base::TimeDelta DomainReliabilityScheduler::GetUploadRetryInterval( |
202 int failures) { | 202 unsigned failures) { |
203 if (failures == 0) | 203 if (failures == 0) |
204 return base::TimeDelta::FromSeconds(0); | 204 return base::TimeDelta::FromSeconds(0); |
205 else { | 205 else { |
206 return params_.upload_retry_interval * (1 << std::min(failures - 1, 5)); | 206 // Don't back off more than 64x the original delay. |
207 if (failures > 7) | |
208 failures = 7; | |
209 return params_.upload_retry_interval * (1 << (failures - 1)); | |
207 } | 210 } |
208 } | 211 } |
209 | 212 |
210 } // namespace domain_reliability | 213 } // namespace domain_reliability |
OLD | NEW |