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

Side by Side Diff: components/sync/sessions_impl/nudge_tracker.cc

Issue 2258873003: [Sync] Move sessions/ to engine/cycle/ and rename things to match. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments. Created 4 years, 4 months 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 (c) 2013 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/sync/sessions_impl/nudge_tracker.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10
11 #include "base/memory/ptr_util.h"
12 #include "components/sync/engine/polling_constants.h"
13 #include "components/sync/protocol/sync.pb.h"
14
15 namespace syncer {
16 namespace sessions {
17
18 namespace {
19
20 // Delays for syncer nudges.
21 const int kDefaultNudgeDelayMilliseconds = 200;
22 const int kSlowNudgeDelayMilliseconds = 2000;
23 const int kDefaultSessionsCommitDelaySeconds = 10;
24 const int kSyncRefreshDelayMilliseconds = 500;
25 const int kSyncSchedulerDelayMilliseconds = 250;
26
27 base::TimeDelta GetDefaultDelayForType(ModelType model_type,
28 base::TimeDelta minimum_delay) {
29 switch (model_type) {
30 case AUTOFILL:
31 // Accompany types rely on nudges from other types, and hence have long
32 // nudge delays.
33 return base::TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds);
34 case BOOKMARKS:
35 case PREFERENCES:
36 // Types with sometimes automatic changes get longer delays to allow more
37 // coalescing.
38 return base::TimeDelta::FromMilliseconds(kSlowNudgeDelayMilliseconds);
39 case SESSIONS:
40 case FAVICON_IMAGES:
41 case FAVICON_TRACKING:
42 // Types with navigation triggered changes get longer delays to allow more
43 // coalescing.
44 return base::TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds);
45 default:
46 return minimum_delay;
47 }
48 }
49
50 } // namespace
51
52 size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10;
53
54 NudgeTracker::NudgeTracker()
55 : invalidations_enabled_(false),
56 invalidations_out_of_sync_(true),
57 minimum_local_nudge_delay_(
58 base::TimeDelta::FromMilliseconds(kDefaultNudgeDelayMilliseconds)),
59 local_refresh_nudge_delay_(
60 base::TimeDelta::FromMilliseconds(kSyncRefreshDelayMilliseconds)),
61 remote_invalidation_nudge_delay_(
62 base::TimeDelta::FromMilliseconds(kSyncSchedulerDelayMilliseconds)) {
63 ModelTypeSet protocol_types = ProtocolTypes();
64 // Default initialize all the type trackers.
65 for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good();
66 it.Inc()) {
67 type_trackers_.insert(
68 std::make_pair(it.Get(), base::WrapUnique(new DataTypeTracker())));
69 }
70 }
71
72 NudgeTracker::~NudgeTracker() {}
73
74 bool NudgeTracker::IsSyncRequired() const {
75 if (IsRetryRequired())
76 return true;
77
78 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
79 it != type_trackers_.end(); ++it) {
80 if (it->second->IsSyncRequired()) {
81 return true;
82 }
83 }
84
85 return false;
86 }
87
88 bool NudgeTracker::IsGetUpdatesRequired() const {
89 if (invalidations_out_of_sync_)
90 return true;
91
92 if (IsRetryRequired())
93 return true;
94
95 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
96 it != type_trackers_.end(); ++it) {
97 if (it->second->IsGetUpdatesRequired()) {
98 return true;
99 }
100 }
101 return false;
102 }
103
104 bool NudgeTracker::IsRetryRequired() const {
105 if (sync_cycle_start_time_.is_null())
106 return false;
107
108 if (current_retry_time_.is_null())
109 return false;
110
111 return current_retry_time_ <= sync_cycle_start_time_;
112 }
113
114 void NudgeTracker::RecordSuccessfulSyncCycle() {
115 // If a retry was required, we've just serviced it. Unset the flag.
116 if (IsRetryRequired())
117 current_retry_time_ = base::TimeTicks();
118
119 // A successful cycle while invalidations are enabled puts us back into sync.
120 invalidations_out_of_sync_ = !invalidations_enabled_;
121
122 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
123 it != type_trackers_.end(); ++it) {
124 it->second->RecordSuccessfulSyncCycle();
125 }
126 }
127
128 base::TimeDelta NudgeTracker::RecordLocalChange(ModelTypeSet types) {
129 // Start with the longest delay.
130 base::TimeDelta delay =
131 base::TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds);
132 for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good();
133 type_it.Inc()) {
134 TypeTrackerMap::const_iterator tracker_it =
135 type_trackers_.find(type_it.Get());
136 DCHECK(tracker_it != type_trackers_.end());
137
138 // Only if the type tracker has a valid delay (non-zero) that is shorter
139 // than the calculated delay do we update the calculated delay.
140 base::TimeDelta type_delay = tracker_it->second->RecordLocalChange();
141 if (type_delay.is_zero()) {
142 type_delay =
143 GetDefaultDelayForType(type_it.Get(), minimum_local_nudge_delay_);
144 }
145 if (type_delay < delay)
146 delay = type_delay;
147 }
148 return delay;
149 }
150
151 base::TimeDelta NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) {
152 for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
153 TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(it.Get());
154 DCHECK(tracker_it != type_trackers_.end());
155 tracker_it->second->RecordLocalRefreshRequest();
156 }
157 return local_refresh_nudge_delay_;
158 }
159
160 base::TimeDelta NudgeTracker::RecordRemoteInvalidation(
161 syncer::ModelType type,
162 std::unique_ptr<InvalidationInterface> invalidation) {
163 // Forward the invalidations to the proper recipient.
164 TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type);
165 DCHECK(tracker_it != type_trackers_.end());
166 tracker_it->second->RecordRemoteInvalidation(std::move(invalidation));
167 return remote_invalidation_nudge_delay_;
168 }
169
170 void NudgeTracker::RecordInitialSyncRequired(syncer::ModelType type) {
171 TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type);
172 DCHECK(tracker_it != type_trackers_.end());
173 tracker_it->second->RecordInitialSyncRequired();
174 }
175
176 void NudgeTracker::RecordCommitConflict(syncer::ModelType type) {
177 TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type);
178 DCHECK(tracker_it != type_trackers_.end());
179 tracker_it->second->RecordCommitConflict();
180 }
181
182 void NudgeTracker::OnInvalidationsEnabled() {
183 invalidations_enabled_ = true;
184 }
185
186 void NudgeTracker::OnInvalidationsDisabled() {
187 invalidations_enabled_ = false;
188 invalidations_out_of_sync_ = true;
189 }
190
191 void NudgeTracker::SetTypesThrottledUntil(ModelTypeSet types,
192 base::TimeDelta length,
193 base::TimeTicks now) {
194 for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
195 TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(it.Get());
196 tracker_it->second->ThrottleType(length, now);
197 }
198 }
199
200 void NudgeTracker::UpdateTypeThrottlingState(base::TimeTicks now) {
201 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
202 it != type_trackers_.end(); ++it) {
203 it->second->UpdateThrottleState(now);
204 }
205 }
206
207 bool NudgeTracker::IsAnyTypeThrottled() const {
208 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
209 it != type_trackers_.end(); ++it) {
210 if (it->second->IsThrottled()) {
211 return true;
212 }
213 }
214 return false;
215 }
216
217 bool NudgeTracker::IsTypeThrottled(ModelType type) const {
218 DCHECK(type_trackers_.find(type) != type_trackers_.end());
219 return type_trackers_.find(type)->second->IsThrottled();
220 }
221
222 base::TimeDelta NudgeTracker::GetTimeUntilNextUnthrottle(
223 base::TimeTicks now) const {
224 DCHECK(IsAnyTypeThrottled()) << "This function requires a pending unthrottle";
225
226 // Return min of GetTimeUntilUnthrottle() values for all IsThrottled() types.
227 base::TimeDelta time_until_next_unthrottle = base::TimeDelta::Max();
228 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
229 it != type_trackers_.end(); ++it) {
230 if (it->second->IsThrottled()) {
231 time_until_next_unthrottle = std::min(
232 time_until_next_unthrottle, it->second->GetTimeUntilUnthrottle(now));
233 }
234 }
235 DCHECK(!time_until_next_unthrottle.is_max());
236
237 return time_until_next_unthrottle;
238 }
239
240 ModelTypeSet NudgeTracker::GetThrottledTypes() const {
241 ModelTypeSet result;
242 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
243 it != type_trackers_.end(); ++it) {
244 if (it->second->IsThrottled()) {
245 result.Put(it->first);
246 }
247 }
248 return result;
249 }
250
251 ModelTypeSet NudgeTracker::GetNudgedTypes() const {
252 ModelTypeSet result;
253 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
254 it != type_trackers_.end(); ++it) {
255 if (it->second->HasLocalChangePending()) {
256 result.Put(it->first);
257 }
258 }
259 return result;
260 }
261
262 ModelTypeSet NudgeTracker::GetNotifiedTypes() const {
263 ModelTypeSet result;
264 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
265 it != type_trackers_.end(); ++it) {
266 if (it->second->HasPendingInvalidation()) {
267 result.Put(it->first);
268 }
269 }
270 return result;
271 }
272
273 ModelTypeSet NudgeTracker::GetRefreshRequestedTypes() const {
274 ModelTypeSet result;
275 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
276 it != type_trackers_.end(); ++it) {
277 if (it->second->HasRefreshRequestPending()) {
278 result.Put(it->first);
279 }
280 }
281 return result;
282 }
283
284 void NudgeTracker::SetLegacyNotificationHint(
285 ModelType type,
286 sync_pb::DataTypeProgressMarker* progress) const {
287 DCHECK(type_trackers_.find(type) != type_trackers_.end());
288 type_trackers_.find(type)->second->SetLegacyNotificationHint(progress);
289 }
290
291 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource()
292 const {
293 // There's an order to these sources: NOTIFICATION, DATATYPE_REFRESH, LOCAL,
294 // RETRY. The server makes optimization decisions based on this field, so
295 // it's important to get this right. Setting it wrong could lead to missed
296 // updates.
297 //
298 // This complexity is part of the reason why we're deprecating 'source' in
299 // favor of 'origin'.
300 bool has_invalidation_pending = false;
301 bool has_refresh_request_pending = false;
302 bool has_commit_pending = false;
303 bool is_initial_sync_required = false;
304 bool has_retry = IsRetryRequired();
305
306 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
307 it != type_trackers_.end(); ++it) {
308 const DataTypeTracker& tracker = *it->second;
309 if (!tracker.IsThrottled() && tracker.HasPendingInvalidation()) {
310 has_invalidation_pending = true;
311 }
312 if (!tracker.IsThrottled() && tracker.HasRefreshRequestPending()) {
313 has_refresh_request_pending = true;
314 }
315 if (!tracker.IsThrottled() && tracker.HasLocalChangePending()) {
316 has_commit_pending = true;
317 }
318 if (!tracker.IsThrottled() && tracker.IsInitialSyncRequired()) {
319 is_initial_sync_required = true;
320 }
321 }
322
323 if (has_invalidation_pending) {
324 return sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
325 } else if (has_refresh_request_pending) {
326 return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
327 } else if (is_initial_sync_required) {
328 // Not quite accurate, but good enough for our purposes. This setting of
329 // SOURCE is just a backward-compatibility hack anyway.
330 return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
331 } else if (has_commit_pending) {
332 return sync_pb::GetUpdatesCallerInfo::LOCAL;
333 } else if (has_retry) {
334 return sync_pb::GetUpdatesCallerInfo::RETRY;
335 } else {
336 return sync_pb::GetUpdatesCallerInfo::UNKNOWN;
337 }
338 }
339
340 void NudgeTracker::FillProtoMessage(ModelType type,
341 sync_pb::GetUpdateTriggers* msg) const {
342 DCHECK(type_trackers_.find(type) != type_trackers_.end());
343
344 // Fill what we can from the global data.
345 msg->set_invalidations_out_of_sync(invalidations_out_of_sync_);
346
347 // Delegate the type-specific work to the DataTypeTracker class.
348 type_trackers_.find(type)->second->FillGetUpdatesTriggersMessage(msg);
349 }
350
351 void NudgeTracker::SetSyncCycleStartTime(base::TimeTicks now) {
352 sync_cycle_start_time_ = now;
353
354 // If current_retry_time_ is still set, that means we have an old retry time
355 // left over from a previous cycle. For example, maybe we tried to perform
356 // this retry, hit a network connection error, and now we're in exponential
357 // backoff. In that case, we want this sync cycle to include the GU retry
358 // flag so we leave this variable set regardless of whether or not there is an
359 // overwrite pending.
360 if (!current_retry_time_.is_null()) {
361 return;
362 }
363
364 // If do not have a current_retry_time_, but we do have a next_retry_time_ and
365 // it is ready to go, then we set it as the current_retry_time_. It will stay
366 // there until a GU retry has succeeded.
367 if (!next_retry_time_.is_null() &&
368 next_retry_time_ <= sync_cycle_start_time_) {
369 current_retry_time_ = next_retry_time_;
370 next_retry_time_ = base::TimeTicks();
371 }
372 }
373
374 void NudgeTracker::SetHintBufferSize(size_t size) {
375 for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
376 it != type_trackers_.end(); ++it) {
377 it->second->UpdatePayloadBufferSize(size);
378 }
379 }
380
381 void NudgeTracker::SetNextRetryTime(base::TimeTicks retry_time) {
382 next_retry_time_ = retry_time;
383 }
384
385 void NudgeTracker::OnReceivedCustomNudgeDelays(
386 const std::map<ModelType, base::TimeDelta>& delay_map) {
387 for (std::map<ModelType, base::TimeDelta>::const_iterator iter =
388 delay_map.begin();
389 iter != delay_map.end(); ++iter) {
390 ModelType type = iter->first;
391 DCHECK(syncer::ProtocolTypes().Has(type));
392 TypeTrackerMap::const_iterator type_iter = type_trackers_.find(type);
393 if (type_iter == type_trackers_.end())
394 continue;
395
396 if (iter->second > minimum_local_nudge_delay_) {
397 type_iter->second->UpdateLocalNudgeDelay(iter->second);
398 } else {
399 type_iter->second->UpdateLocalNudgeDelay(
400 GetDefaultDelayForType(type, minimum_local_nudge_delay_));
401 }
402 }
403 }
404
405 void NudgeTracker::SetDefaultNudgeDelay(base::TimeDelta nudge_delay) {
406 minimum_local_nudge_delay_ = nudge_delay;
407 }
408
409 } // namespace sessions
410 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/sessions_impl/nudge_tracker.h ('k') | components/sync/sessions_impl/nudge_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698