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