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

Side by Side Diff: sync/sessions/data_type_tracker.cc

Issue 322333004: sync: Inject sync/'s dependency on invalidations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « sync/sessions/data_type_tracker.h ('k') | sync/sessions/nudge_tracker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/data_type_tracker.h" 5 #include "sync/sessions/data_type_tracker.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "sync/internal_api/public/base/invalidation.h" 8 #include "sync/internal_api/public/base/invalidation_interface.h"
9 #include "sync/notifier/invalidation_util.h"
10 #include "sync/notifier/single_object_invalidation_set.h"
11 #include "sync/sessions/nudge_tracker.h" 9 #include "sync/sessions/nudge_tracker.h"
12 10
13 namespace syncer { 11 namespace syncer {
14 namespace sessions { 12 namespace sessions {
15 13
16 DataTypeTracker::DataTypeTracker(const invalidation::ObjectId& object_id) 14 DataTypeTracker::DataTypeTracker()
17 : local_nudge_count_(0), 15 : local_nudge_count_(0),
18 local_refresh_request_count_(0), 16 local_refresh_request_count_(0),
19 payload_buffer_size_(NudgeTracker::kDefaultMaxPayloadsPerType), 17 payload_buffer_size_(NudgeTracker::kDefaultMaxPayloadsPerType) {
20 drop_tracker_(object_id) { } 18 }
21 19
22 DataTypeTracker::~DataTypeTracker() { } 20 DataTypeTracker::~DataTypeTracker() { }
23 21
24 void DataTypeTracker::RecordLocalChange() { 22 void DataTypeTracker::RecordLocalChange() {
25 local_nudge_count_++; 23 local_nudge_count_++;
26 } 24 }
27 25
28 void DataTypeTracker::RecordLocalRefreshRequest() { 26 void DataTypeTracker::RecordLocalRefreshRequest() {
29 local_refresh_request_count_++; 27 local_refresh_request_count_++;
30 } 28 }
31 29
32 namespace { 30 void DataTypeTracker::RecordRemoteInvalidation(
31 scoped_ptr<InvalidationInterface> incoming) {
32 DCHECK(incoming);
33 33
34 bool IsInvalidationVersionLessThan( 34 // Merge the incoming invalidation into our list of pending invalidations.
35 const Invalidation& a,
36 const Invalidation& b) {
37 InvalidationVersionLessThan comparator;
38 return comparator(a, b);
39 }
40
41 } // namespace
42
43 void DataTypeTracker::RecordRemoteInvalidations(
44 const SingleObjectInvalidationSet& invalidations) {
45 // Merge the incoming invalidations into our list of pending invalidations.
46 // 35 //
47 // We won't use STL algorithms here because our concept of equality doesn't 36 // We won't use STL algorithms here because our concept of equality doesn't
48 // quite fit the expectations of set_intersection. In particular, two 37 // quite fit the expectations of set_intersection. In particular, two
49 // invalidations can be equal according to the SingleObjectInvalidationSet's 38 // invalidations can be equal according to the SingleObjectInvalidationSet's
50 // rules (ie. have equal versions), but still have different AckHandle values 39 // rules (ie. have equal versions), but still have different AckHandle values
51 // and need to be acknowledged separately. 40 // and need to be acknowledged separately.
52 // 41 //
53 // The invalidaitons service can only track one outsanding invalidation per 42 // The invalidations service can only track one outsanding invalidation per
54 // type and version, so the acknowledgement here should be redundant. We'll 43 // type and version, so the acknowledgement here should be redundant. We'll
55 // acknowledge them anyway since it should do no harm, and makes this code a 44 // acknowledge them anyway since it should do no harm, and makes this code a
56 // bit easier to test. 45 // bit easier to test.
57 // 46 //
58 // Overlaps should be extremely rare for most invalidations. They can happen 47 // Overlaps should be extremely rare for most invalidations. They can happen
59 // for unknown version invalidations, though. 48 // for unknown version invalidations, though.
60 SingleObjectInvalidationSet::const_iterator incoming_it = 49
61 invalidations.begin(); 50 ScopedVector<InvalidationInterface>::iterator it =
62 SingleObjectInvalidationSet::const_iterator existing_it =
63 pending_invalidations_.begin(); 51 pending_invalidations_.begin();
64 52
65 while (incoming_it != invalidations.end()) { 53 // Find the lower bound.
66 // Keep existing_it ahead of incoming_it. 54 while (it != pending_invalidations_.end() &&
67 while (existing_it != pending_invalidations_.end() 55 InvalidationInterface::LessThanByVersion(**it, *incoming)) {
68 && IsInvalidationVersionLessThan(*existing_it, *incoming_it)) { 56 it++;
69 existing_it++;
70 }
71
72 if (existing_it != pending_invalidations_.end()
73 && !IsInvalidationVersionLessThan(*incoming_it, *existing_it)
74 && !IsInvalidationVersionLessThan(*existing_it, *incoming_it)) {
75 // Incoming overlaps with existing. Either both are unknown versions
76 // (likely) or these two have the same version number (very unlikely).
77 // Acknowledge and overwrite existing.
78 SingleObjectInvalidationSet::const_iterator old_inv = existing_it;
79 existing_it++;
80 old_inv->Acknowledge();
81 pending_invalidations_.Erase(old_inv);
82 pending_invalidations_.Insert(*incoming_it);
83 incoming_it++;
84 } else {
85 DCHECK(existing_it == pending_invalidations_.end()
86 || IsInvalidationVersionLessThan(*incoming_it, *existing_it));
87 // The incoming_it points at a version not in the pending_invalidations_
88 // list. Add it to the list then increment past it.
89 pending_invalidations_.Insert(*incoming_it);
90 incoming_it++;
91 }
92 } 57 }
93 58
94 // Those incoming invalidations may have caused us to exceed our buffer size. 59 if (it != pending_invalidations_.end() &&
60 !InvalidationInterface::LessThanByVersion(*incoming, **it) &&
61 !InvalidationInterface::LessThanByVersion(**it, *incoming)) {
62 // Incoming overlaps with existing. Either both are unknown versions
63 // (likely) or these two have the same version number (very unlikely).
64 // Acknowledge and overwrite existing.
65
66 // Insert before the existing and get iterator to inserted.
67 ScopedVector<InvalidationInterface>::iterator it2 =
68 pending_invalidations_.insert(it, incoming.release());
69
70 // Increment that iterator to the old one, then acknowledge and remove it.
71 ++it2;
72 (*it2)->Acknowledge();
73 pending_invalidations_.erase(it2);
74 } else {
75 // The incoming has a version not in the pending_invalidations_ list.
76 // Add it to the list at the proper position.
77 pending_invalidations_.insert(it, incoming.release());
78 }
79
80 // The incoming invalidation may have caused us to exceed our buffer size.
95 // Trim some items from our list, if necessary. 81 // Trim some items from our list, if necessary.
96 while (pending_invalidations_.GetSize() > payload_buffer_size_) { 82 while (pending_invalidations_.size() > payload_buffer_size_) {
97 pending_invalidations_.begin()->Drop(&drop_tracker_); 83 last_dropped_invalidation_.reset(pending_invalidations_.front());
98 pending_invalidations_.Erase(pending_invalidations_.begin()); 84 last_dropped_invalidation_->Drop();
85 pending_invalidations_.weak_erase(pending_invalidations_.begin());
99 } 86 }
100 } 87 }
101 88
102 void DataTypeTracker::RecordSuccessfulSyncCycle() { 89 void DataTypeTracker::RecordSuccessfulSyncCycle() {
103 // If we were throttled, then we would have been excluded from this cycle's 90 // If we were throttled, then we would have been excluded from this cycle's
104 // GetUpdates and Commit actions. Our state remains unchanged. 91 // GetUpdates and Commit actions. Our state remains unchanged.
105 if (IsThrottled()) 92 if (IsThrottled())
106 return; 93 return;
107 94
108 local_nudge_count_ = 0; 95 local_nudge_count_ = 0;
109 local_refresh_request_count_ = 0; 96 local_refresh_request_count_ = 0;
110 97
111 // TODO(rlarocque): If we want this to be correct even if we should happen to 98 // TODO(rlarocque): If we want this to be correct even if we should happen to
112 // crash before writing all our state, we should wait until the results of 99 // crash before writing all our state, we should wait until the results of
113 // this sync cycle have been written to disk before updating the invalidations 100 // this sync cycle have been written to disk before updating the invalidations
114 // state. See crbug.com/324996. 101 // state. See crbug.com/324996.
115 for (SingleObjectInvalidationSet::const_iterator it = 102 for (ScopedVector<InvalidationInterface>::const_iterator it =
116 pending_invalidations_.begin(); 103 pending_invalidations_.begin();
117 it != pending_invalidations_.end(); ++it) { 104 it != pending_invalidations_.end();
118 it->Acknowledge(); 105 ++it) {
106 (*it)->Acknowledge();
119 } 107 }
120 pending_invalidations_.Clear(); 108 pending_invalidations_.clear();
121 109
122 if (drop_tracker_.IsRecoveringFromDropEvent()) { 110 if (last_dropped_invalidation_) {
123 drop_tracker_.RecordRecoveryFromDropEvent(); 111 last_dropped_invalidation_->Acknowledge();
112 last_dropped_invalidation_.reset();
124 } 113 }
125 } 114 }
126 115
127 // This limit will take effect on all future invalidations received. 116 // This limit will take effect on all future invalidations received.
128 void DataTypeTracker::UpdatePayloadBufferSize(size_t new_size) { 117 void DataTypeTracker::UpdatePayloadBufferSize(size_t new_size) {
129 payload_buffer_size_ = new_size; 118 payload_buffer_size_ = new_size;
130 } 119 }
131 120
132 bool DataTypeTracker::IsSyncRequired() const { 121 bool DataTypeTracker::IsSyncRequired() const {
133 return !IsThrottled() && (HasLocalChangePending() || IsGetUpdatesRequired()); 122 return !IsThrottled() && (HasLocalChangePending() || IsGetUpdatesRequired());
134 } 123 }
135 124
136 bool DataTypeTracker::IsGetUpdatesRequired() const { 125 bool DataTypeTracker::IsGetUpdatesRequired() const {
137 return !IsThrottled() && 126 return !IsThrottled() &&
138 (HasRefreshRequestPending() || HasPendingInvalidation()); 127 (HasRefreshRequestPending() || HasPendingInvalidation());
139 } 128 }
140 129
141 bool DataTypeTracker::HasLocalChangePending() const { 130 bool DataTypeTracker::HasLocalChangePending() const {
142 return local_nudge_count_ > 0; 131 return local_nudge_count_ > 0;
143 } 132 }
144 133
145 bool DataTypeTracker::HasRefreshRequestPending() const { 134 bool DataTypeTracker::HasRefreshRequestPending() const {
146 return local_refresh_request_count_ > 0; 135 return local_refresh_request_count_ > 0;
147 } 136 }
148 137
149 bool DataTypeTracker::HasPendingInvalidation() const { 138 bool DataTypeTracker::HasPendingInvalidation() const {
150 return !pending_invalidations_.IsEmpty() 139 return !pending_invalidations_.empty() || last_dropped_invalidation_;
151 || drop_tracker_.IsRecoveringFromDropEvent();
152 } 140 }
153 141
154 void DataTypeTracker::SetLegacyNotificationHint( 142 void DataTypeTracker::SetLegacyNotificationHint(
155 sync_pb::DataTypeProgressMarker* progress) const { 143 sync_pb::DataTypeProgressMarker* progress) const {
156 DCHECK(!IsThrottled()) 144 DCHECK(!IsThrottled())
157 << "We should not make requests if the type is throttled."; 145 << "We should not make requests if the type is throttled.";
158 146
159 if (!pending_invalidations_.IsEmpty() && 147 if (!pending_invalidations_.empty() &&
160 !pending_invalidations_.back().is_unknown_version()) { 148 !pending_invalidations_.back()->IsUnknownVersion()) {
161 // The old-style source info can contain only one hint per type. We grab 149 // The old-style source info can contain only one hint per type. We grab
162 // the most recent, to mimic the old coalescing behaviour. 150 // the most recent, to mimic the old coalescing behaviour.
163 progress->set_notification_hint(pending_invalidations_.back().payload()); 151 progress->set_notification_hint(
152 pending_invalidations_.back()->GetPayload());
164 } else if (HasLocalChangePending()) { 153 } else if (HasLocalChangePending()) {
165 // The old-style source info sent up an empty string (as opposed to 154 // The old-style source info sent up an empty string (as opposed to
166 // nothing at all) when the type was locally nudged, but had not received 155 // nothing at all) when the type was locally nudged, but had not received
167 // any invalidations. 156 // any invalidations.
168 progress->set_notification_hint(""); 157 progress->set_notification_hint(std::string());
169 } 158 }
170 } 159 }
171 160
172 void DataTypeTracker::FillGetUpdatesTriggersMessage( 161 void DataTypeTracker::FillGetUpdatesTriggersMessage(
173 sync_pb::GetUpdateTriggers* msg) const { 162 sync_pb::GetUpdateTriggers* msg) const {
174 // Fill the list of payloads, if applicable. The payloads must be ordered 163 // Fill the list of payloads, if applicable. The payloads must be ordered
175 // oldest to newest, so we insert them in the same order as we've been storing 164 // oldest to newest, so we insert them in the same order as we've been storing
176 // them internally. 165 // them internally.
177 for (SingleObjectInvalidationSet::const_iterator it = 166 for (ScopedVector<InvalidationInterface>::const_iterator it =
178 pending_invalidations_.begin(); 167 pending_invalidations_.begin();
179 it != pending_invalidations_.end(); ++it) { 168 it != pending_invalidations_.end();
180 if (!it->is_unknown_version()) { 169 ++it) {
181 msg->add_notification_hint(it->payload()); 170 if (!(*it)->IsUnknownVersion()) {
171 msg->add_notification_hint((*it)->GetPayload());
182 } 172 }
183 } 173 }
184 174
185 msg->set_server_dropped_hints( 175 msg->set_server_dropped_hints(
186 pending_invalidations_.StartsWithUnknownVersion()); 176 !pending_invalidations_.empty() &&
187 msg->set_client_dropped_hints(drop_tracker_.IsRecoveringFromDropEvent()); 177 (*pending_invalidations_.begin())->IsUnknownVersion());
178 msg->set_client_dropped_hints(last_dropped_invalidation_);
188 msg->set_local_modification_nudges(local_nudge_count_); 179 msg->set_local_modification_nudges(local_nudge_count_);
189 msg->set_datatype_refresh_nudges(local_refresh_request_count_); 180 msg->set_datatype_refresh_nudges(local_refresh_request_count_);
190 } 181 }
191 182
192 bool DataTypeTracker::IsThrottled() const { 183 bool DataTypeTracker::IsThrottled() const {
193 return !unthrottle_time_.is_null(); 184 return !unthrottle_time_.is_null();
194 } 185 }
195 186
196 base::TimeDelta DataTypeTracker::GetTimeUntilUnthrottle( 187 base::TimeDelta DataTypeTracker::GetTimeUntilUnthrottle(
197 base::TimeTicks now) const { 188 base::TimeTicks now) const {
(...skipping 11 matching lines...) Expand all
209 } 200 }
210 201
211 void DataTypeTracker::UpdateThrottleState(base::TimeTicks now) { 202 void DataTypeTracker::UpdateThrottleState(base::TimeTicks now) {
212 if (now >= unthrottle_time_) { 203 if (now >= unthrottle_time_) {
213 unthrottle_time_ = base::TimeTicks(); 204 unthrottle_time_ = base::TimeTicks();
214 } 205 }
215 } 206 }
216 207
217 } // namespace sessions 208 } // namespace sessions
218 } // namespace syncer 209 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/sessions/data_type_tracker.h ('k') | sync/sessions/nudge_tracker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698