• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "sync/sessions/data_type_tracker.h"
6 
7 #include "base/logging.h"
8 #include "sync/internal_api/public/base/invalidation.h"
9 #include "sync/notifier/single_object_invalidation_set.h"
10 #include "sync/sessions/nudge_tracker.h"
11 
12 namespace syncer {
13 namespace sessions {
14 
DataTypeTracker()15 DataTypeTracker::DataTypeTracker()
16   : local_nudge_count_(0),
17     local_refresh_request_count_(0),
18     local_payload_overflow_(false),
19     server_payload_overflow_(false),
20     payload_buffer_size_(NudgeTracker::kDefaultMaxPayloadsPerType) { }
21 
~DataTypeTracker()22 DataTypeTracker::~DataTypeTracker() { }
23 
RecordLocalChange()24 void DataTypeTracker::RecordLocalChange() {
25   local_nudge_count_++;
26 }
27 
RecordLocalRefreshRequest()28 void DataTypeTracker::RecordLocalRefreshRequest() {
29   local_refresh_request_count_++;
30 }
31 
RecordRemoteInvalidations(const SingleObjectInvalidationSet & invalidations)32 void DataTypeTracker::RecordRemoteInvalidations(
33     const SingleObjectInvalidationSet& invalidations) {
34   for (SingleObjectInvalidationSet::const_iterator it =
35        invalidations.begin(); it != invalidations.end(); ++it) {
36     if (it->is_unknown_version()) {
37       server_payload_overflow_ = true;
38     } else {
39       pending_payloads_.push_back(it->payload());
40       if (pending_payloads_.size() > payload_buffer_size_) {
41         // Drop the oldest payload if we've overflowed.
42         pending_payloads_.pop_front();
43         local_payload_overflow_ = true;
44       }
45     }
46   }
47 }
48 
RecordSuccessfulSyncCycle()49 void DataTypeTracker::RecordSuccessfulSyncCycle() {
50   // If we were throttled, then we would have been excluded from this cycle's
51   // GetUpdates and Commit actions.  Our state remains unchanged.
52   if (IsThrottled())
53     return;
54 
55   local_nudge_count_ = 0;
56   local_refresh_request_count_ = 0;
57   pending_payloads_.clear();
58   local_payload_overflow_ = false;
59   server_payload_overflow_ = false;
60 }
61 
62 // This limit will take effect on all future invalidations received.
UpdatePayloadBufferSize(size_t new_size)63 void DataTypeTracker::UpdatePayloadBufferSize(size_t new_size) {
64   payload_buffer_size_ = new_size;
65 }
66 
IsSyncRequired() const67 bool DataTypeTracker::IsSyncRequired() const {
68   return !IsThrottled() &&
69       (local_nudge_count_ > 0 ||
70        local_refresh_request_count_ > 0 ||
71        HasPendingInvalidation() ||
72        local_payload_overflow_ ||
73        server_payload_overflow_);
74 }
75 
IsGetUpdatesRequired() const76 bool DataTypeTracker::IsGetUpdatesRequired() const {
77   return !IsThrottled() &&
78       (local_refresh_request_count_ > 0 ||
79        HasPendingInvalidation() ||
80        local_payload_overflow_ ||
81        server_payload_overflow_);
82 }
83 
HasLocalChangePending() const84 bool DataTypeTracker::HasLocalChangePending() const {
85   return local_nudge_count_ > 0;
86 }
87 
HasPendingInvalidation() const88 bool DataTypeTracker::HasPendingInvalidation() const {
89   return !pending_payloads_.empty();
90 }
91 
GetMostRecentInvalidationPayload() const92 std::string DataTypeTracker::GetMostRecentInvalidationPayload() const {
93   return pending_payloads_.back();
94 }
95 
SetLegacyNotificationHint(sync_pb::DataTypeProgressMarker * progress) const96 void DataTypeTracker::SetLegacyNotificationHint(
97     sync_pb::DataTypeProgressMarker* progress) const {
98   DCHECK(!IsThrottled())
99       << "We should not make requests if the type is throttled.";
100 
101   if (HasPendingInvalidation()) {
102     // The old-style source info can contain only one hint per type.  We grab
103     // the most recent, to mimic the old coalescing behaviour.
104     progress->set_notification_hint(GetMostRecentInvalidationPayload());
105   } else if (HasLocalChangePending()) {
106     // The old-style source info sent up an empty string (as opposed to
107     // nothing at all) when the type was locally nudged, but had not received
108     // any invalidations.
109     progress->set_notification_hint("");
110   }
111 }
112 
FillGetUpdatesTriggersMessage(sync_pb::GetUpdateTriggers * msg) const113 void DataTypeTracker::FillGetUpdatesTriggersMessage(
114     sync_pb::GetUpdateTriggers* msg) const {
115   // Fill the list of payloads, if applicable.  The payloads must be ordered
116   // oldest to newest, so we insert them in the same order as we've been storing
117   // them internally.
118   for (PayloadList::const_iterator payload_it = pending_payloads_.begin();
119        payload_it != pending_payloads_.end(); ++payload_it) {
120     msg->add_notification_hint(*payload_it);
121   }
122 
123   msg->set_client_dropped_hints(local_payload_overflow_);
124   msg->set_local_modification_nudges(local_nudge_count_);
125   msg->set_datatype_refresh_nudges(local_refresh_request_count_);
126 
127   // TODO(rlarocque): Support Tango trickles.  See crbug.com/223437.
128   // msg->set_server_dropped_hints(server_payload_oveflow_);
129 }
130 
IsThrottled() const131 bool DataTypeTracker::IsThrottled() const {
132   return !unthrottle_time_.is_null();
133 }
134 
GetTimeUntilUnthrottle(base::TimeTicks now) const135 base::TimeDelta DataTypeTracker::GetTimeUntilUnthrottle(
136     base::TimeTicks now) const {
137   if (!IsThrottled()) {
138     NOTREACHED();
139     return base::TimeDelta::FromSeconds(0);
140   }
141   return std::max(base::TimeDelta::FromSeconds(0),
142                   unthrottle_time_ - now);
143 }
144 
ThrottleType(base::TimeDelta duration,base::TimeTicks now)145 void DataTypeTracker::ThrottleType(base::TimeDelta duration,
146                                       base::TimeTicks now) {
147   unthrottle_time_ = std::max(unthrottle_time_, now + duration);
148 }
149 
UpdateThrottleState(base::TimeTicks now)150 void DataTypeTracker::UpdateThrottleState(base::TimeTicks now) {
151   if (now >= unthrottle_time_) {
152     unthrottle_time_ = base::TimeTicks();
153   }
154 }
155 
156 }  // namespace sessions
157 }  // namespace syncer
158