OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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 "sync/sessions/nudge_tracker.h" | 5 #include "sync/sessions/nudge_tracker.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "sync/internal_api/public/base/invalidation.h" | 8 #include "sync/internal_api/public/base/invalidation.h" |
9 #include "sync/notifier/invalidation_util.h" | 9 #include "sync/notifier/invalidation_util.h" |
10 #include "sync/notifier/object_id_invalidation_map.h" | 10 #include "sync/notifier/object_id_invalidation_map.h" |
11 #include "sync/protocol/sync.pb.h" | 11 #include "sync/protocol/sync.pb.h" |
12 | 12 |
13 namespace syncer { | 13 namespace syncer { |
14 namespace sessions { | 14 namespace sessions { |
15 | 15 |
16 size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10; | 16 size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10; |
17 | 17 |
18 NudgeTracker::NudgeTracker() | 18 NudgeTracker::NudgeTracker() |
19 : updates_source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN), | 19 : invalidations_enabled_(false), |
20 invalidations_enabled_(false), | |
21 invalidations_out_of_sync_(true) { | 20 invalidations_out_of_sync_(true) { |
22 ModelTypeSet protocol_types = ProtocolTypes(); | 21 ModelTypeSet protocol_types = ProtocolTypes(); |
23 // Default initialize all the type trackers. | 22 // Default initialize all the type trackers. |
24 for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); | 23 for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); |
25 it.Inc()) { | 24 it.Inc()) { |
26 invalidation::ObjectId id; | 25 invalidation::ObjectId id; |
27 if (!RealModelTypeToObjectId(it.Get(), &id)) { | 26 if (!RealModelTypeToObjectId(it.Get(), &id)) { |
28 NOTREACHED(); | 27 NOTREACHED(); |
29 } else { | 28 } else { |
30 type_trackers_.insert(std::make_pair(it.Get(), DataTypeTracker(id))); | 29 type_trackers_.insert(std::make_pair(it.Get(), DataTypeTracker(id))); |
31 } | 30 } |
32 } | 31 } |
33 } | 32 } |
34 | 33 |
35 NudgeTracker::~NudgeTracker() { } | 34 NudgeTracker::~NudgeTracker() { } |
36 | 35 |
37 bool NudgeTracker::IsSyncRequired() const { | 36 bool NudgeTracker::IsSyncRequired() const { |
| 37 if (IsRetryRequired()) |
| 38 return true; |
| 39 |
38 for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); | 40 for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); |
39 it != type_trackers_.end(); ++it) { | 41 it != type_trackers_.end(); ++it) { |
40 if (it->second.IsSyncRequired()) { | 42 if (it->second.IsSyncRequired()) { |
41 return true; | 43 return true; |
42 } | 44 } |
43 } | 45 } |
| 46 |
44 return false; | 47 return false; |
45 } | 48 } |
46 | 49 |
47 bool NudgeTracker::IsGetUpdatesRequired() const { | 50 bool NudgeTracker::IsGetUpdatesRequired() const { |
48 if (invalidations_out_of_sync_) | 51 if (invalidations_out_of_sync_) |
49 return true; | 52 return true; |
50 | 53 |
51 if (IsRetryRequired()) | 54 if (IsRetryRequired()) |
52 return true; | 55 return true; |
53 | 56 |
(...skipping 10 matching lines...) Expand all Loading... |
64 if (sync_cycle_start_time_.is_null()) | 67 if (sync_cycle_start_time_.is_null()) |
65 return false; | 68 return false; |
66 | 69 |
67 if (current_retry_time_.is_null()) | 70 if (current_retry_time_.is_null()) |
68 return false; | 71 return false; |
69 | 72 |
70 return current_retry_time_ < sync_cycle_start_time_; | 73 return current_retry_time_ < sync_cycle_start_time_; |
71 } | 74 } |
72 | 75 |
73 void NudgeTracker::RecordSuccessfulSyncCycle() { | 76 void NudgeTracker::RecordSuccessfulSyncCycle() { |
74 updates_source_ = sync_pb::GetUpdatesCallerInfo::UNKNOWN; | |
75 | |
76 // If a retry was required, we've just serviced it. Unset the flag. | 77 // If a retry was required, we've just serviced it. Unset the flag. |
77 if (IsRetryRequired()) | 78 if (IsRetryRequired()) |
78 current_retry_time_ = base::TimeTicks(); | 79 current_retry_time_ = base::TimeTicks(); |
79 | 80 |
80 // A successful cycle while invalidations are enabled puts us back into sync. | 81 // A successful cycle while invalidations are enabled puts us back into sync. |
81 invalidations_out_of_sync_ = !invalidations_enabled_; | 82 invalidations_out_of_sync_ = !invalidations_enabled_; |
82 | 83 |
83 for (TypeTrackerMap::iterator it = type_trackers_.begin(); | 84 for (TypeTrackerMap::iterator it = type_trackers_.begin(); |
84 it != type_trackers_.end(); ++it) { | 85 it != type_trackers_.end(); ++it) { |
85 it->second.RecordSuccessfulSyncCycle(); | 86 it->second.RecordSuccessfulSyncCycle(); |
86 } | 87 } |
87 } | 88 } |
88 | 89 |
89 void NudgeTracker::RecordLocalChange(ModelTypeSet types) { | 90 void NudgeTracker::RecordLocalChange(ModelTypeSet types) { |
90 // Don't overwrite an NOTIFICATION or DATATYPE_REFRESH source. The server | |
91 // makes some assumptions about the source; overriding these sources with | |
92 // LOCAL could lead to incorrect behaviour. This is part of the reason why | |
93 // we're deprecating 'source' in favor of 'origin'. | |
94 if (updates_source_ != sync_pb::GetUpdatesCallerInfo::NOTIFICATION | |
95 && updates_source_ != sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH) { | |
96 updates_source_ = sync_pb::GetUpdatesCallerInfo::LOCAL; | |
97 } | |
98 | |
99 for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good(); | 91 for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good(); |
100 type_it.Inc()) { | 92 type_it.Inc()) { |
101 TypeTrackerMap::iterator tracker_it = type_trackers_.find(type_it.Get()); | 93 TypeTrackerMap::iterator tracker_it = type_trackers_.find(type_it.Get()); |
102 DCHECK(tracker_it != type_trackers_.end()); | 94 DCHECK(tracker_it != type_trackers_.end()); |
103 tracker_it->second.RecordLocalChange(); | 95 tracker_it->second.RecordLocalChange(); |
104 } | 96 } |
105 } | 97 } |
106 | 98 |
107 void NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) { | 99 void NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) { |
108 // Don't overwrite an NOTIFICATION source. The server makes some assumptions | |
109 // about the source. Overriding this source with LOCAL could lead to | |
110 // incorrect behaviour. This is part of the reason why we're deprecating | |
111 // 'source' in favor of 'origin'. | |
112 if (updates_source_ != sync_pb::GetUpdatesCallerInfo::NOTIFICATION) { | |
113 updates_source_ = sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH; | |
114 } | |
115 | |
116 for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { | 100 for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { |
117 TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get()); | 101 TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get()); |
118 DCHECK(tracker_it != type_trackers_.end()); | 102 DCHECK(tracker_it != type_trackers_.end()); |
119 tracker_it->second.RecordLocalRefreshRequest(); | 103 tracker_it->second.RecordLocalRefreshRequest(); |
120 } | 104 } |
121 } | 105 } |
122 | 106 |
123 void NudgeTracker::RecordRemoteInvalidation( | 107 void NudgeTracker::RecordRemoteInvalidation( |
124 const ObjectIdInvalidationMap& invalidation_map) { | 108 const ObjectIdInvalidationMap& invalidation_map) { |
125 updates_source_ = sync_pb::GetUpdatesCallerInfo::NOTIFICATION; | |
126 | |
127 // Be very careful here. The invalidations acknowledgement system requires a | 109 // Be very careful here. The invalidations acknowledgement system requires a |
128 // sort of manual memory management. We'll leak a small amount of memory if | 110 // sort of manual memory management. We'll leak a small amount of memory if |
129 // we fail to acknowledge or drop any of these incoming invalidations. | 111 // we fail to acknowledge or drop any of these incoming invalidations. |
130 | 112 |
131 ObjectIdSet id_set = invalidation_map.GetObjectIds(); | 113 ObjectIdSet id_set = invalidation_map.GetObjectIds(); |
132 for (ObjectIdSet::iterator it = id_set.begin(); it != id_set.end(); ++it) { | 114 for (ObjectIdSet::iterator it = id_set.begin(); it != id_set.end(); ++it) { |
133 ModelType type; | 115 ModelType type; |
134 | 116 |
135 // This should never happen. If it does, we'll start to leak memory. | 117 // This should never happen. If it does, we'll start to leak memory. |
136 if (!ObjectIdToRealModelType(*it, &type)) { | 118 if (!ObjectIdToRealModelType(*it, &type)) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 return result; | 203 return result; |
222 } | 204 } |
223 | 205 |
224 void NudgeTracker::SetLegacyNotificationHint( | 206 void NudgeTracker::SetLegacyNotificationHint( |
225 ModelType type, | 207 ModelType type, |
226 sync_pb::DataTypeProgressMarker* progress) const { | 208 sync_pb::DataTypeProgressMarker* progress) const { |
227 DCHECK(type_trackers_.find(type) != type_trackers_.end()); | 209 DCHECK(type_trackers_.find(type) != type_trackers_.end()); |
228 type_trackers_.find(type)->second.SetLegacyNotificationHint(progress); | 210 type_trackers_.find(type)->second.SetLegacyNotificationHint(progress); |
229 } | 211 } |
230 | 212 |
231 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::updates_source() | 213 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource() |
232 const { | 214 const { |
233 return updates_source_; | 215 // There's an order to these sources: NOTIFICATION, DATATYPE_REFRESH, LOCAL, |
| 216 // RETRY. The server makes optimization decisions based on this field, so |
| 217 // it's important to get this right. Setting it wrong could lead to missed |
| 218 // updates. |
| 219 // |
| 220 // This complexity is part of the reason why we're deprecating 'source' in |
| 221 // favor of 'origin'. |
| 222 bool has_invalidation_pending = false; |
| 223 bool has_refresh_request_pending = false; |
| 224 bool has_commit_pending = false; |
| 225 bool has_retry = IsRetryRequired(); |
| 226 |
| 227 for (TypeTrackerMap::const_iterator it = type_trackers_.begin(); |
| 228 it != type_trackers_.end(); ++it) { |
| 229 const DataTypeTracker& tracker = it->second; |
| 230 if (!tracker.IsThrottled() && tracker.HasPendingInvalidation()) { |
| 231 has_invalidation_pending = true; |
| 232 } |
| 233 if (!tracker.IsThrottled() && tracker.HasRefreshRequestPending()) { |
| 234 has_refresh_request_pending = true; |
| 235 } |
| 236 if (!tracker.IsThrottled() && tracker.HasLocalChangePending()) { |
| 237 has_commit_pending = true; |
| 238 } |
| 239 } |
| 240 |
| 241 if (has_invalidation_pending) { |
| 242 return sync_pb::GetUpdatesCallerInfo::NOTIFICATION; |
| 243 } else if (has_refresh_request_pending) { |
| 244 return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH; |
| 245 } else if (has_commit_pending) { |
| 246 return sync_pb::GetUpdatesCallerInfo::LOCAL; |
| 247 } else if (has_retry) { |
| 248 return sync_pb::GetUpdatesCallerInfo::RETRY; |
| 249 } else { |
| 250 return sync_pb::GetUpdatesCallerInfo::UNKNOWN; |
| 251 } |
234 } | 252 } |
235 | 253 |
236 void NudgeTracker::FillProtoMessage( | 254 void NudgeTracker::FillProtoMessage( |
237 ModelType type, | 255 ModelType type, |
238 sync_pb::GetUpdateTriggers* msg) const { | 256 sync_pb::GetUpdateTriggers* msg) const { |
239 DCHECK(type_trackers_.find(type) != type_trackers_.end()); | 257 DCHECK(type_trackers_.find(type) != type_trackers_.end()); |
240 | 258 |
241 // Fill what we can from the global data. | 259 // Fill what we can from the global data. |
242 msg->set_invalidations_out_of_sync(invalidations_out_of_sync_); | 260 msg->set_invalidations_out_of_sync(invalidations_out_of_sync_); |
243 | 261 |
(...skipping 30 matching lines...) Expand all Loading... |
274 it->second.UpdatePayloadBufferSize(size); | 292 it->second.UpdatePayloadBufferSize(size); |
275 } | 293 } |
276 } | 294 } |
277 | 295 |
278 void NudgeTracker::SetNextRetryTime(base::TimeTicks retry_time) { | 296 void NudgeTracker::SetNextRetryTime(base::TimeTicks retry_time) { |
279 next_retry_time_ = retry_time; | 297 next_retry_time_ = retry_time; |
280 } | 298 } |
281 | 299 |
282 } // namespace sessions | 300 } // namespace sessions |
283 } // namespace syncer | 301 } // namespace syncer |
OLD | NEW |