1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/sessions/nudge_tracker.h"
6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/basictypes.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "sync/internal_api/public/base/invalidation.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sync/notifier/invalidation_util.h"
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sync/notifier/object_id_invalidation_map.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/protocol/sync.pb.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace syncer {
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace sessions {
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)size_t NudgeTracker::kDefaultMaxPayloadsPerType = 10;
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)NudgeTracker::NudgeTracker()
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : invalidations_enabled_(false),
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      invalidations_out_of_sync_(true) {
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ModelTypeSet protocol_types = ProtocolTypes();
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Default initialize all the type trackers.
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good();
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it.Inc()) {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    invalidation::ObjectId id;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!RealModelTypeToObjectId(it.Get(), &id)) {
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      type_trackers_.insert(std::make_pair(it.Get(), DataTypeTracker(id)));
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NudgeTracker::~NudgeTracker() { }
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool NudgeTracker::IsSyncRequired() const {
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (IsRetryRequired())
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (it->second.IsSyncRequired()) {
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return true;
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return false;
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool NudgeTracker::IsGetUpdatesRequired() const {
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (invalidations_out_of_sync_)
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsRetryRequired())
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       it != type_trackers_.end(); ++it) {
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (it->second.IsGetUpdatesRequired()) {
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return true;
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return false;
64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NudgeTracker::IsRetryRequired() const {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (sync_cycle_start_time_.is_null())
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (current_retry_time_.is_null())
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return current_retry_time_ < sync_cycle_start_time_;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::RecordSuccessfulSyncCycle() {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If a retry was required, we've just serviced it.  Unset the flag.
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsRetryRequired())
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    current_retry_time_ = base::TimeTicks();
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // A successful cycle while invalidations are enabled puts us back into sync.
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  invalidations_out_of_sync_ = !invalidations_enabled_;
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (TypeTrackerMap::iterator it = type_trackers_.begin();
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    it->second.RecordSuccessfulSyncCycle();
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::RecordLocalChange(ModelTypeSet types) {
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       type_it.Inc()) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TypeTrackerMap::iterator tracker_it = type_trackers_.find(type_it.Get());
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(tracker_it != type_trackers_.end());
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracker_it->second.RecordLocalChange();
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) {
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get());
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(tracker_it != type_trackers_.end());
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracker_it->second.RecordLocalRefreshRequest();
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::RecordRemoteInvalidation(
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const ObjectIdInvalidationMap& invalidation_map) {
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Be very careful here.  The invalidations acknowledgement system requires a
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // sort of manual memory management.  We'll leak a small amount of memory if
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we fail to acknowledge or drop any of these incoming invalidations.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ObjectIdSet id_set = invalidation_map.GetObjectIds();
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ObjectIdSet::iterator it = id_set.begin(); it != id_set.end(); ++it) {
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ModelType type;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This should never happen.  If it does, we'll start to leak memory.
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!ObjectIdToRealModelType(*it, &type)) {
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      NOTREACHED()
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          << "Object ID " << ObjectIdToString(*it)
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          << " does not map to valid model type";
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Forward the invalidations to the proper recipient.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TypeTrackerMap::iterator tracker_it = type_trackers_.find(type);
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(tracker_it != type_trackers_.end());
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracker_it->second.RecordRemoteInvalidations(
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        invalidation_map.ForObject(*it));
130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::OnInvalidationsEnabled() {
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  invalidations_enabled_ = true;
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::OnInvalidationsDisabled() {
138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  invalidations_enabled_ = false;
139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  invalidations_out_of_sync_ = true;
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void NudgeTracker::SetTypesThrottledUntil(
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ModelTypeSet types,
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::TimeDelta length,
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::TimeTicks now) {
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TypeTrackerMap::iterator tracker_it = type_trackers_.find(it.Get());
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracker_it->second.ThrottleType(length, now);
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void NudgeTracker::UpdateTypeThrottlingState(base::TimeTicks now) {
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (TypeTrackerMap::iterator it = type_trackers_.begin();
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    it->second.UpdateThrottleState(now);
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool NudgeTracker::IsAnyTypeThrottled() const {
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (it->second.IsThrottled()) {
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return true;
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return false;
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool NudgeTracker::IsTypeThrottled(ModelType type) const {
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(type_trackers_.find(type) != type_trackers_.end());
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return type_trackers_.find(type)->second.IsThrottled();
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::TimeDelta NudgeTracker::GetTimeUntilNextUnthrottle(
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::TimeTicks now) const {
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(IsAnyTypeThrottled()) << "This function requires a pending unthrottle";
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Return min of GetTimeUntilUnthrottle() values for all IsThrottled() types.
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TimeDelta time_until_next_unthrottle = base::TimeDelta::Max();
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (it->second.IsThrottled()) {
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      time_until_next_unthrottle =
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          std::min(time_until_next_unthrottle,
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   it->second.GetTimeUntilUnthrottle(now));
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!time_until_next_unthrottle.is_max());
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return time_until_next_unthrottle;
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ModelTypeSet NudgeTracker::GetThrottledTypes() const {
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ModelTypeSet result;
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (it->second.IsThrottled()) {
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      result.Put(it->first);
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return result;
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ModelTypeSet NudgeTracker::GetNudgedTypes() const {
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ModelTypeSet result;
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       it != type_trackers_.end(); ++it) {
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (it->second.HasLocalChangePending()) {
20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      result.Put(it->first);
21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return result;
21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ModelTypeSet NudgeTracker::GetNotifiedTypes() const {
21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ModelTypeSet result;
21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       it != type_trackers_.end(); ++it) {
21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (it->second.HasPendingInvalidation()) {
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      result.Put(it->first);
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return result;
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ModelTypeSet NudgeTracker::GetRefreshRequestedTypes() const {
22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ModelTypeSet result;
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       it != type_trackers_.end(); ++it) {
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (it->second.HasRefreshRequestPending()) {
23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      result.Put(it->first);
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return result;
23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NudgeTracker::SetLegacyNotificationHint(
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ModelType type,
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    sync_pb::DataTypeProgressMarker* progress) const {
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(type_trackers_.find(type) != type_trackers_.end());
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  type_trackers_.find(type)->second.SetLegacyNotificationHint(progress);
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource()
245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // There's an order to these sources: NOTIFICATION, DATATYPE_REFRESH, LOCAL,
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // RETRY.  The server makes optimization decisions based on this field, so
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // it's important to get this right.  Setting it wrong could lead to missed
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // updates.
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This complexity is part of the reason why we're deprecating 'source' in
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // favor of 'origin'.
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_invalidation_pending = false;
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_refresh_request_pending = false;
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_commit_pending = false;
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_retry = IsRetryRequired();
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const DataTypeTracker& tracker = it->second;
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!tracker.IsThrottled() && tracker.HasPendingInvalidation()) {
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      has_invalidation_pending = true;
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!tracker.IsThrottled() && tracker.HasRefreshRequestPending()) {
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      has_refresh_request_pending = true;
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!tracker.IsThrottled() && tracker.HasLocalChangePending()) {
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      has_commit_pending = true;
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (has_invalidation_pending) {
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (has_refresh_request_pending) {
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (has_commit_pending) {
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sync_pb::GetUpdatesCallerInfo::LOCAL;
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (has_retry) {
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sync_pb::GetUpdatesCallerInfo::RETRY;
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sync_pb::GetUpdatesCallerInfo::UNKNOWN;
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::FillProtoMessage(
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ModelType type,
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    sync_pb::GetUpdateTriggers* msg) const {
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(type_trackers_.find(type) != type_trackers_.end());
289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Fill what we can from the global data.
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  msg->set_invalidations_out_of_sync(invalidations_out_of_sync_);
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Delegate the type-specific work to the DataTypeTracker class.
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  type_trackers_.find(type)->second.FillGetUpdatesTriggersMessage(msg);
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NudgeTracker::SetSyncCycleStartTime(base::TimeTicks now) {
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_cycle_start_time_ = now;
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If current_retry_time_ is still set, that means we have an old retry time
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // left over from a previous cycle.  For example, maybe we tried to perform
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this retry, hit a network connection error, and now we're in exponential
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // backoff.  In that case, we want this sync cycle to include the GU retry
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // flag so we leave this variable set regardless of whether or not there is an
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // overwrite pending.
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!current_retry_time_.is_null()) {
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If do not have a current_retry_time_, but we do have a next_retry_time_ and
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // it is ready to go, then we set it as the current_retry_time_.  It will stay
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // there until a GU retry has succeeded.
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!next_retry_time_.is_null() &&
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_retry_time_ < sync_cycle_start_time_) {
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    current_retry_time_ = next_retry_time_;
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    next_retry_time_ = base::TimeTicks();
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void NudgeTracker::SetHintBufferSize(size_t size) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (TypeTrackerMap::iterator it = type_trackers_.begin();
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != type_trackers_.end(); ++it) {
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    it->second.UpdatePayloadBufferSize(size);
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NudgeTracker::SetNextRetryTime(base::TimeTicks retry_time) {
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  next_retry_time_ = retry_time;
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace sessions
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace syncer
333