| Index: sync/sessions/nudge_tracker.cc
|
| diff --git a/sync/sessions/nudge_tracker.cc b/sync/sessions/nudge_tracker.cc
|
| index 714b67d13f14582e427fdf544c40bc44a067dab8..7eae5eccb4620d88b2f3dda0a2f83efc9821dcb4 100644
|
| --- a/sync/sessions/nudge_tracker.cc
|
| +++ b/sync/sessions/nudge_tracker.cc
|
| @@ -3,47 +3,197 @@
|
| // found in the LICENSE file.
|
|
|
| #include "sync/sessions/nudge_tracker.h"
|
| +
|
| +#include "sync/internal_api/public/base/invalidation.h"
|
| +#include "sync/internal_api/public/sessions/sync_source_info.h"
|
| #include "sync/protocol/sync.pb.h"
|
|
|
| namespace syncer {
|
| namespace sessions {
|
|
|
| -NudgeTracker::NudgeTracker() { }
|
| +size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10;
|
| +
|
| +NudgeTracker::NudgeTracker()
|
| + : updates_source_(sync_pb::GetUpdatesCallerInfo::UNKNOWN),
|
| + invalidations_enabled_(false),
|
| + invalidations_out_of_sync_(true),
|
| + num_payloads_per_type_(kDefaultMaxPayloadsPerType) { }
|
|
|
| NudgeTracker::~NudgeTracker() { }
|
|
|
| -void NudgeTracker::CoalesceSources(const SyncSourceInfo& source) {
|
| - CoalesceStates(source.types, &source_info_.types);
|
| - source_info_.updates_source = source.updates_source;
|
| +bool NudgeTracker::IsSyncRequired() {
|
| + if (!local_nudge_counts_.empty()) {
|
| + return true;
|
| + } else if (!refresh_requested_counts_.empty()) {
|
| + return true;
|
| + } else if (!payload_list_map_.empty()) {
|
| + return true;
|
| + } else {
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +void NudgeTracker::RecordSuccessfulSyncCycle() {
|
| + updates_source_ = sync_pb::GetUpdatesCallerInfo::UNKNOWN;
|
| + local_nudge_counts_.clear();
|
| + refresh_requested_counts_.clear();
|
| + payload_list_map_.clear();
|
| + locally_dropped_payload_types_.Clear();
|
| + server_dropped_payload_types_.Clear();
|
| +
|
| + // A successful cycle while invalidations are enabled puts us back into sync.
|
| + invalidations_out_of_sync_ = !invalidations_enabled_;
|
| +}
|
| +
|
| +void NudgeTracker::RecordLocalChange(ModelTypeSet types) {
|
| + // Don't overwrite an NOTIFICATION or DATATYPE_REFRESH source. The server
|
| + // makes some assumptions about the source; overriding these sources with
|
| + // LOCAL could lead to incorrect behaviour. This is part of the reason why
|
| + // we're deprecating 'source' in favor of 'origin'.
|
| + if (updates_source_ != sync_pb::GetUpdatesCallerInfo::NOTIFICATION
|
| + && updates_source_ != sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH) {
|
| + updates_source_ = sync_pb::GetUpdatesCallerInfo::LOCAL;
|
| + }
|
| +
|
| + for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
|
| + local_nudge_counts_[it.Get()]++;
|
| + }
|
| +}
|
| +
|
| +void NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) {
|
| + // Don't overwrite an NOTIFICATION source. The server makes some assumptions
|
| + // about the source. Overriding this source with LOCAL could lead to
|
| + // incorrect behaviour. This is part of the reason why we're deprecating
|
| + // 'source' in favor of 'origin'.
|
| + if (updates_source_ != sync_pb::GetUpdatesCallerInfo::NOTIFICATION) {
|
| + updates_source_ = sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
|
| + }
|
| +
|
| + for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
|
| + refresh_requested_counts_[it.Get()]++;
|
| + }
|
| }
|
|
|
| -bool NudgeTracker::IsEmpty() {
|
| - return source_info_.types.empty();
|
| +void NudgeTracker::RecordRemoteInvalidation(
|
| + const ModelTypeInvalidationMap& invalidation_map) {
|
| + updates_source_ = sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
|
| +
|
| + for (ModelTypeInvalidationMap::const_iterator i = invalidation_map.begin();
|
| + i != invalidation_map.end(); ++i) {
|
| + const ModelType type = i->first;
|
| + const std::string& payload = i->second.payload;
|
| +
|
| + payload_list_map_[type].push_back(payload);
|
| +
|
| + // Respect the size limits on locally queued invalidation hints.
|
| + if (payload_list_map_[type].size() > num_payloads_per_type_) {
|
| + payload_list_map_[type].pop_front();
|
| + locally_dropped_payload_types_.Put(type);
|
| + }
|
| + }
|
| }
|
|
|
| -void NudgeTracker::Reset() {
|
| - source_info_ = SyncSourceInfo();
|
| +void NudgeTracker::OnInvalidationsEnabled() {
|
| + invalidations_enabled_ = true;
|
| +}
|
| +
|
| +void NudgeTracker::OnInvalidationsDisabled() {
|
| + invalidations_enabled_ = false;
|
| + invalidations_out_of_sync_ = true;
|
| +}
|
| +
|
| +SyncSourceInfo NudgeTracker::GetSourceInfo() const {
|
| + // The old-style source added an empty hint for all locally nudge types.
|
| + // This will be overwritten with the proper hint for any types that were both
|
| + // locally nudged and invalidated.
|
| + ModelTypeSet nudged_types;
|
| + for (NudgeMap::const_iterator it = local_nudge_counts_.begin();
|
| + it != local_nudge_counts_.end(); ++it) {
|
| + nudged_types.Put(it->first);
|
| + }
|
| + ModelTypeInvalidationMap invalidation_map =
|
| + ModelTypeSetToInvalidationMap(nudged_types, std::string());
|
| +
|
| + // The old-style source info can contain only one hint per type. We grab the
|
| + // most recent, to mimic the old coalescing behaviour.
|
| + for (PayloadListMap::const_iterator it = payload_list_map_.begin();
|
| + it != payload_list_map_.end(); ++it) {
|
| + ModelType type = it->first;
|
| + const PayloadList& list = it->second;
|
| +
|
| + if (!list.empty()) {
|
| + Invalidation invalidation;
|
| + invalidation.payload = list.back();
|
| + if (invalidation_map.find(type) != invalidation_map.end()) {
|
| + invalidation_map[type] = invalidation;
|
| + } else {
|
| + invalidation_map.insert(std::make_pair(type, invalidation));
|
| + }
|
| + }
|
| + }
|
| +
|
| + return SyncSourceInfo(updates_source_, invalidation_map);
|
| }
|
|
|
| -// TODO(rlarocque): This function often reports incorrect results. However, it
|
| -// is compatible with the "classic" behaviour. We would need to make the nudge
|
| -// tracker stop overwriting its own information (ie. fix crbug.com/231693)
|
| -// before we could even try to report correct results. The main issue is that
|
| -// an notifications and local modifications nudges may overlap with each other
|
| -// in sych a way that we lose track of which types were or were not locally
|
| -// modified.
|
| ModelTypeSet NudgeTracker::GetLocallyModifiedTypes() const {
|
| - ModelTypeSet locally_modified;
|
| + ModelTypeSet nudged_types;
|
| + for (NudgeMap::const_iterator it = local_nudge_counts_.begin();
|
| + it != local_nudge_counts_.end(); ++it) {
|
| + nudged_types.Put(it->first);
|
| + }
|
| + return nudged_types;
|
| +}
|
| +
|
| +sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::updates_source()
|
| + const {
|
| + return updates_source_;
|
| +}
|
|
|
| - if (source_info_.updates_source != sync_pb::GetUpdatesCallerInfo::LOCAL) {
|
| - return locally_modified;
|
| +void NudgeTracker::FillProtoMessage(
|
| + ModelType type,
|
| + sync_pb::GetUpdateTriggers* msg) const {
|
| + // Fill the list of payloads, if applicable. The payloads must be ordered
|
| + // oldest to newest, so we insert them in the same order as we've been storing
|
| + // them internally.
|
| + PayloadListMap::const_iterator type_it = payload_list_map_.find(type);
|
| + if (type_it != payload_list_map_.end()) {
|
| + const PayloadList& payload_list = type_it->second;
|
| + for (PayloadList::const_iterator payload_it = payload_list.begin();
|
| + payload_it != payload_list.end(); ++payload_it) {
|
| + msg->add_notification_hint(*payload_it);
|
| + }
|
| }
|
|
|
| - for (ModelTypeInvalidationMap::const_iterator i = source_info_.types.begin();
|
| - i != source_info().types.end(); ++i) {
|
| - locally_modified.Put(i->first);
|
| + // TODO(rlarocque): Support Tango trickles. See crbug.com/223437.
|
| + // msg->set_server_dropped_hints(server_dropped_payload_types_.Has(type));
|
| +
|
| + msg->set_client_dropped_hints(locally_dropped_payload_types_.Has(type));
|
| + msg->set_invalidations_out_of_sync(invalidations_out_of_sync_);
|
| +
|
| + {
|
| + NudgeMap::const_iterator it = local_nudge_counts_.find(type);
|
| + if (it == local_nudge_counts_.end()) {
|
| + msg->set_local_modification_nudges(0);
|
| + } else {
|
| + msg->set_local_modification_nudges(it->second);
|
| + }
|
| }
|
| - return locally_modified;
|
| +
|
| + {
|
| + NudgeMap::const_iterator it = refresh_requested_counts_.find(type);
|
| + if (it == refresh_requested_counts_.end()) {
|
| + msg->set_datatype_refresh_nudges(0);
|
| + } else {
|
| + msg->set_datatype_refresh_nudges(it->second);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void NudgeTracker::SetHintBufferSize(size_t size) {
|
| + // We could iterate through the list and trim it down to size here, but that
|
| + // seems unnecessary. This limit will take effect on all future invalidations
|
| + // received.
|
| + num_payloads_per_type_ = size;
|
| }
|
|
|
| } // namespace sessions
|
|
|