summaryrefslogtreecommitdiffstats
path: root/sync/sessions
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-14 19:45:30 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-14 19:45:30 +0000
commitd9d8f9f150646e0adcb2948097cea99f89db41c4 (patch)
tree77437a172d1a057e8c465b20ec8ef517187dddde /sync/sessions
parent3c6de13983e12c3506fd53502fc92075b2595136 (diff)
downloadchromium_src-d9d8f9f150646e0adcb2948097cea99f89db41c4.zip
chromium_src-d9d8f9f150646e0adcb2948097cea99f89db41c4.tar.gz
chromium_src-d9d8f9f150646e0adcb2948097cea99f89db41c4.tar.bz2
sync: Handle type throttling in NudgeTracker
This change removes the ThrottledDataTypeTracker and moves much of its functionality into the NudgeTracker. This allows us to better control throttling behavior and fix crbug.com/155296. This CL re-routes syncer_proto_util type throttling callbacks through the SyncSession::Delegate to the SyncScheduler. It adds a timer and some related functions to the SyncScheduler, so the scheduler can now wake up, unthrottle types, and attempt a sync cycle at the exact time when throttling expires. The information about which types are currently throttled has been moved to the NudgeTracker. This allows the NudgeTracker to take type throttling into account in functions like NudgeTracker::IsSyncRequired() and NudgeTracker::RecordSuccessfulSyncCycle(). The DownloadUpdatesCommand's special case for nudge-type syncs has been extended to take throttling into account. GetCommitIdsCommand has been updated to fetch its list of throttled types from the nudge tracker. Unfortunately, this meant that committing from poll-triggered sync sessions had to be disabled, since poll sync cycles do not have access to the nudge tracker. BUG=155296, 116184 Review URL: https://chromiumcodereview.appspot.com/16402013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206475 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/sessions')
-rw-r--r--sync/sessions/data_type_tracker.cc39
-rw-r--r--sync/sessions/data_type_tracker.h24
-rw-r--r--sync/sessions/nudge_tracker.cc92
-rw-r--r--sync/sessions/nudge_tracker.h30
-rw-r--r--sync/sessions/nudge_tracker_unittest.cc180
-rw-r--r--sync/sessions/sync_session.cc2
-rw-r--r--sync/sessions/sync_session.h9
-rw-r--r--sync/sessions/sync_session_context.cc3
-rw-r--r--sync/sessions/sync_session_context.h8
-rw-r--r--sync/sessions/sync_session_unittest.cc15
-rw-r--r--sync/sessions/test_util.cc18
11 files changed, 310 insertions, 110 deletions
diff --git a/sync/sessions/data_type_tracker.cc b/sync/sessions/data_type_tracker.cc
index 639ccc0..857b86a 100644
--- a/sync/sessions/data_type_tracker.cc
+++ b/sync/sessions/data_type_tracker.cc
@@ -37,6 +37,11 @@ void DataTypeTracker::RecordRemoteInvalidation(
}
void DataTypeTracker::RecordSuccessfulSyncCycle() {
+ // If we were throttled, then we would have been excluded from this cycle's
+ // GetUpdates and Commit actions. Our state remains unchanged.
+ if (IsThrottled())
+ return;
+
local_nudge_count_ = 0;
local_refresh_request_count_ = 0;
pending_payloads_.clear();
@@ -50,11 +55,10 @@ void DataTypeTracker::UpdatePayloadBufferSize(size_t new_size) {
}
bool DataTypeTracker::IsSyncRequired() const {
- return local_nudge_count_ > 0 || IsGetUpdatesRequired();
-}
-
-bool DataTypeTracker::IsGetUpdatesRequired() const {
- return local_refresh_request_count_ > 0 || !pending_payloads_.empty();
+ return !IsThrottled() &&
+ (local_nudge_count_ > 0 ||
+ local_refresh_request_count_ > 0 ||
+ !pending_payloads_.empty());
}
bool DataTypeTracker::HasLocalChangePending() const {
@@ -87,5 +91,30 @@ void DataTypeTracker::FillGetUpdatesTriggersMessage(
// msg->set_server_dropped_hints(server_payload_oveflow_);
}
+bool DataTypeTracker::IsThrottled() const {
+ return !unthrottle_time_.is_null();
+}
+
+base::TimeDelta DataTypeTracker::GetTimeUntilUnthrottle(
+ base::TimeTicks now) const {
+ if (!IsThrottled()) {
+ NOTREACHED();
+ return base::TimeDelta::FromSeconds(0);
+ }
+ return std::max(base::TimeDelta::FromSeconds(0),
+ unthrottle_time_ - now);
+}
+
+void DataTypeTracker::ThrottleType(base::TimeDelta duration,
+ base::TimeTicks now) {
+ unthrottle_time_ = std::max(unthrottle_time_, now + duration);
+}
+
+void DataTypeTracker::UpdateThrottleState(base::TimeTicks now) {
+ if (now >= unthrottle_time_) {
+ unthrottle_time_ = base::TimeTicks();
+ }
+}
+
} // namespace sessions
} // namespace syncer
diff --git a/sync/sessions/data_type_tracker.h b/sync/sessions/data_type_tracker.h
index 494c881..d6da946 100644
--- a/sync/sessions/data_type_tracker.h
+++ b/sync/sessions/data_type_tracker.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/time.h"
#include "sync/protocol/sync.pb.h"
namespace syncer {
@@ -48,11 +49,6 @@ class DataTypeTracker {
// cycle. That's for the scheduler to decide.
bool IsSyncRequired() const;
- // Returns true if one of the reasons behind the need for a sync cycle is to
- // fetch updates. If this is true, then IsSyncRequired() will also return
- // true.
- bool IsGetUpdatesRequired() const;
-
// Returns true if there is an uncommitted local change.
bool HasLocalChangePending() const;
@@ -68,6 +64,20 @@ class DataTypeTracker {
// handle a request.
void FillGetUpdatesTriggersMessage(sync_pb::GetUpdateTriggers* msg) const;
+ // Returns true if the type is currently throttled.
+ bool IsThrottled() const;
+
+ // Returns the time until this type's throttling interval expires. Should not
+ // be called unless IsThrottled() returns true. The returned value will be
+ // increased to zero if it would otherwise have been negative.
+ base::TimeDelta GetTimeUntilUnthrottle(base::TimeTicks now) const;
+
+ // Throttles the type from |now| until |now| + |duration|.
+ void ThrottleType(base::TimeDelta duration, base::TimeTicks now);
+
+ // Unthrottles the type if |now| >= the throttle expiry time.
+ void UpdateThrottleState(base::TimeTicks now);
+
private:
// Number of local change nudges received for this type since the last
// successful sync cycle.
@@ -91,6 +101,10 @@ class DataTypeTracker {
bool server_payload_overflow_;
size_t payload_buffer_size_;
+
+ // If !unthrottle_time_.is_null(), this type is throttled and may not download
+ // or commit data until the specified time.
+ base::TimeTicks unthrottle_time_;
};
} // namespace syncer
diff --git a/sync/sessions/nudge_tracker.cc b/sync/sessions/nudge_tracker.cc
index 9d4d3b2..97f211f 100644
--- a/sync/sessions/nudge_tracker.cc
+++ b/sync/sessions/nudge_tracker.cc
@@ -4,6 +4,7 @@
#include "sync/sessions/nudge_tracker.h"
+#include "base/basictypes.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"
@@ -27,16 +28,6 @@ NudgeTracker::NudgeTracker()
NudgeTracker::~NudgeTracker() { }
-bool NudgeTracker::IsGetUpdatesRequired() {
- for (TypeTrackerMap::iterator it = type_trackers_.begin();
- it != type_trackers_.end(); ++it) {
- if (it->second.IsGetUpdatesRequired()) {
- return true;
- }
- }
- return false;
-}
-
bool NudgeTracker::IsSyncRequired() {
for (TypeTrackerMap::iterator it = type_trackers_.begin();
it != type_trackers_.end(); ++it) {
@@ -112,6 +103,69 @@ void NudgeTracker::OnInvalidationsDisabled() {
invalidations_out_of_sync_ = true;
}
+void NudgeTracker::SetTypesThrottledUntil(
+ ModelTypeSet types,
+ base::TimeDelta length,
+ base::TimeTicks now) {
+ for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
+ type_trackers_[it.Get()].ThrottleType(length, now);
+ }
+}
+
+void NudgeTracker::UpdateTypeThrottlingState(base::TimeTicks now) {
+ for (TypeTrackerMap::iterator it = type_trackers_.begin();
+ it != type_trackers_.end(); ++it) {
+ it->second.UpdateThrottleState(now);
+ }
+}
+
+bool NudgeTracker::IsAnyTypeThrottled() const {
+ for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
+ it != type_trackers_.end(); ++it) {
+ if (it->second.IsThrottled()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool NudgeTracker::IsTypeThrottled(ModelType type) const {
+ DCHECK(type_trackers_.find(type) != type_trackers_.end());
+ return type_trackers_.find(type)->second.IsThrottled();
+}
+
+base::TimeDelta NudgeTracker::GetTimeUntilNextUnthrottle(
+ base::TimeTicks now) const {
+ DCHECK(IsAnyTypeThrottled()) << "This function requires a pending unthrottle";
+ const base::TimeDelta kMaxTimeDelta =
+ base::TimeDelta::FromInternalValue(kint64max);
+
+ // Return min of GetTimeUntilUnthrottle() values for all IsThrottled() types.
+ base::TimeDelta time_until_next_unthrottle = kMaxTimeDelta;
+ for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
+ it != type_trackers_.end(); ++it) {
+ if (it->second.IsThrottled()) {
+ time_until_next_unthrottle =
+ std::min(time_until_next_unthrottle,
+ it->second.GetTimeUntilUnthrottle(now));
+ }
+ }
+ DCHECK(kMaxTimeDelta != time_until_next_unthrottle);
+
+ return time_until_next_unthrottle;
+}
+
+ModelTypeSet NudgeTracker::GetThrottledTypes() const {
+ ModelTypeSet result;
+ for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
+ it != type_trackers_.end(); ++it) {
+ if (it->second.IsThrottled()) {
+ result.Put(it->first);
+ }
+ }
+ return result;
+}
+
// This function is intended to mimic the behavior of older clients. Newer
// clients and servers will not rely on SyncSourceInfo. See FillProtoMessage
// for the more modern equivalent.
@@ -119,7 +173,10 @@ SyncSourceInfo NudgeTracker::GetSourceInfo() const {
ModelTypeInvalidationMap invalidation_map;
for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
it != type_trackers_.end(); ++it) {
- if (it->second.HasPendingInvalidation()) {
+ if (it->second.IsThrottled()) {
+ // We pretend throttled types are not enabled by skipping them.
+ continue;
+ } else if (it->second.HasPendingInvalidation()) {
// The old-style source info can contain only one hint per type. We grab
// the most recent, to mimic the old coalescing behaviour.
Invalidation invalidation;
@@ -138,17 +195,6 @@ SyncSourceInfo NudgeTracker::GetSourceInfo() const {
return SyncSourceInfo(updates_source_, invalidation_map);
}
-ModelTypeSet NudgeTracker::GetLocallyModifiedTypes() const {
- ModelTypeSet nudged_types;
- for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
- it != type_trackers_.end(); ++it) {
- if (it->second.HasLocalChangePending()) {
- nudged_types.Put(it->first);
- }
- }
- return nudged_types;
-}
-
sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::updates_source()
const {
return updates_source_;
@@ -162,7 +208,7 @@ void NudgeTracker::FillProtoMessage(
// Fill what we can from the global data.
msg->set_invalidations_out_of_sync(invalidations_out_of_sync_);
- // Delegate the type-specific work to TypeSchedulingData class.
+ // Delegate the type-specific work to the DataTypeTracker class.
type_trackers_.find(type)->second.FillGetUpdatesTriggersMessage(msg);
}
diff --git a/sync/sessions/nudge_tracker.h b/sync/sessions/nudge_tracker.h
index c71fd00..3db3143 100644
--- a/sync/sessions/nudge_tracker.h
+++ b/sync/sessions/nudge_tracker.h
@@ -29,11 +29,6 @@ class SYNC_EXPORT_PRIVATE NudgeTracker {
NudgeTracker();
~NudgeTracker();
- // Returns true if one of the main reasons for performing the sync cycle is to
- // fetch updates. This is true when we have pending invalidations or refresh
- // requests.
- bool IsGetUpdatesRequired();
-
// Returns true if there is a good reason for performing a sync cycle.
// This does not take into account whether or not this is a good *time* to
// perform a sync cycle; that's the scheduler's job.
@@ -58,14 +53,31 @@ class SYNC_EXPORT_PRIVATE NudgeTracker {
void OnInvalidationsEnabled();
void OnInvalidationsDisabled();
+ // Marks |types| as being throttled from |now| until |now| + |length|.
+ void SetTypesThrottledUntil(ModelTypeSet types,
+ base::TimeDelta length,
+ base::TimeTicks now);
+
+ // Removes any throttling that have expired by time |now|.
+ void UpdateTypeThrottlingState(base::TimeTicks now);
+
+ // Returns the time of the next type unthrottling, relative to
+ // the input |now| value.
+ base::TimeDelta GetTimeUntilNextUnthrottle(base::TimeTicks now) const;
+
+ // Returns true if any type is currenlty throttled.
+ bool IsAnyTypeThrottled() const;
+
+ // Returns true if |type| is currently throttled.
+ bool IsTypeThrottled(ModelType type) const;
+
+ // Returns the set of currently throttled types.
+ ModelTypeSet GetThrottledTypes() const;
+
// A helper to return an old-style source info. Used only to maintain
// compatibility with some old code.
SyncSourceInfo GetSourceInfo() const;
- // Returns the set of locally modified types, according to the nudges received
- // since the last successful sync cycle.
- ModelTypeSet GetLocallyModifiedTypes() const;
-
// Returns the 'source' of the GetUpdate request.
//
// This flag is deprecated, but still used by the server. There can be more
diff --git a/sync/sessions/nudge_tracker_unittest.cc b/sync/sessions/nudge_tracker_unittest.cc
index f6031a3..9e6ce99 100644
--- a/sync/sessions/nudge_tracker_unittest.cc
+++ b/sync/sessions/nudge_tracker_unittest.cc
@@ -60,9 +60,9 @@ class NudgeTrackerTest : public ::testing::Test {
TEST_F(NudgeTrackerTest, EmptyNudgeTracker) {
NudgeTracker nudge_tracker;
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
nudge_tracker.updates_source());
- EXPECT_TRUE(nudge_tracker.GetLocallyModifiedTypes().Empty());
sync_pb::GetUpdateTriggers gu_trigger;
nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger);
@@ -109,44 +109,6 @@ TEST_F(NudgeTrackerTest, SourcePriorities) {
nudge_tracker.updates_source());
}
-// Verify locally modified type coalescing and independence from other nudges.
-TEST_F(NudgeTrackerTest, LocallyModifiedTypes) {
- NudgeTracker nudge_tracker;
-
- // Start with a notification. Verify it has no effect.
- ModelTypeInvalidationMap invalidation_map1 =
- ModelTypeSetToInvalidationMap(ModelTypeSet(PREFERENCES),
- std::string("hint"));
- nudge_tracker.RecordRemoteInvalidation(invalidation_map1);
- EXPECT_TRUE(nudge_tracker.GetLocallyModifiedTypes().Empty());
-
- // Record a local bookmark change. Verify it was registered correctly.
- nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
- EXPECT_TRUE(ModelTypeSetEquals(
- ModelTypeSet(BOOKMARKS),
- nudge_tracker.GetLocallyModifiedTypes()));
-
- // Record a notification and a refresh request. Verify they have no effect.
- ModelTypeInvalidationMap invalidation_map2 =
- ModelTypeSetToInvalidationMap(ModelTypeSet(PASSWORDS),
- std::string("hint"));
- nudge_tracker.RecordRemoteInvalidation(invalidation_map2);
- EXPECT_TRUE(ModelTypeSetEquals(
- ModelTypeSet(BOOKMARKS),
- nudge_tracker.GetLocallyModifiedTypes()));
-
- nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(AUTOFILL));
- EXPECT_TRUE(ModelTypeSetEquals(
- ModelTypeSet(BOOKMARKS),
- nudge_tracker.GetLocallyModifiedTypes()));
-
- // Record another local nudge. Verify it was coalesced correctly.
- nudge_tracker.RecordLocalChange(ModelTypeSet(THEMES));
- EXPECT_TRUE(ModelTypeSetEquals(
- ModelTypeSet(THEMES, BOOKMARKS),
- nudge_tracker.GetLocallyModifiedTypes()));
-}
-
TEST_F(NudgeTrackerTest, HintCoalescing) {
NudgeTracker nudge_tracker;
@@ -311,5 +273,145 @@ TEST_F(NudgeTrackerTest, WriteRefreshRequestedTypesToProto) {
EXPECT_EQ(0, ProtoRefreshRequestedCount(nudge_tracker, SESSIONS));
}
+// Basic tests for the IsSyncRequired() flag.
+TEST_F(NudgeTrackerTest, IsSyncRequired) {
+ NudgeTracker nudge_tracker;
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // Local changes.
+ nudge_tracker.RecordLocalChange(ModelTypeSet(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+ nudge_tracker.RecordSuccessfulSyncCycle();
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // Refresh requests.
+ nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+ nudge_tracker.RecordSuccessfulSyncCycle();
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // Invalidations.
+ ModelTypeInvalidationMap invalidation_map =
+ ModelTypeSetToInvalidationMap(ModelTypeSet(PREFERENCES),
+ std::string("hint"));
+ nudge_tracker.RecordRemoteInvalidation(invalidation_map);
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+ nudge_tracker.RecordSuccessfulSyncCycle();
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+}
+
+// Test IsSyncRequired() responds correctly to data type throttling.
+TEST_F(NudgeTrackerTest, IsSyncRequired_Throttling) {
+ NudgeTracker nudge_tracker;
+ const base::TimeTicks t0 = base::TimeTicks::FromInternalValue(1234);
+ const base::TimeDelta throttle_length = base::TimeDelta::FromMinutes(10);
+ const base::TimeTicks t1 = t0 + throttle_length;
+
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // A local change to sessions enables the flag.
+ nudge_tracker.RecordLocalChange(ModelTypeSet(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+
+ // But the throttling of sessions unsets it.
+ nudge_tracker.SetTypesThrottledUntil(ModelTypeSet(SESSIONS),
+ throttle_length,
+ t0);
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // A refresh request for bookmarks means we have reason to sync again.
+ nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+
+ // A successful sync cycle means we took care of bookmarks.
+ nudge_tracker.RecordSuccessfulSyncCycle();
+ EXPECT_FALSE(nudge_tracker.IsSyncRequired());
+
+ // But we still haven't dealt with sessions. We'll need to remember
+ // that sessions are out of sync and re-enable the flag when their
+ // throttling interval expires.
+ nudge_tracker.UpdateTypeThrottlingState(t1);
+ EXPECT_FALSE(nudge_tracker.IsTypeThrottled(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.IsSyncRequired());
+}
+
+// Tests throttling-related getter functions when no types are throttled.
+TEST_F(NudgeTrackerTest, NoTypesThrottled) {
+ NudgeTracker nudge_tracker;
+
+ EXPECT_FALSE(nudge_tracker.IsAnyTypeThrottled());
+ EXPECT_FALSE(nudge_tracker.IsTypeThrottled(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.GetThrottledTypes().Empty());
+}
+
+// Tests throttling-related getter functions when some types are throttled.
+TEST_F(NudgeTrackerTest, ThrottleAndUnthrottle) {
+ NudgeTracker nudge_tracker;
+ const base::TimeTicks t0 = base::TimeTicks::FromInternalValue(1234);
+ const base::TimeDelta throttle_length = base::TimeDelta::FromMinutes(10);
+ const base::TimeTicks t1 = t0 + throttle_length;
+
+ nudge_tracker.SetTypesThrottledUntil(ModelTypeSet(SESSIONS, PREFERENCES),
+ throttle_length,
+ t0);
+
+ EXPECT_TRUE(nudge_tracker.IsAnyTypeThrottled());
+ EXPECT_TRUE(nudge_tracker.IsTypeThrottled(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.IsTypeThrottled(PREFERENCES));
+ EXPECT_FALSE(nudge_tracker.GetThrottledTypes().Empty());
+ EXPECT_EQ(throttle_length, nudge_tracker.GetTimeUntilNextUnthrottle(t0));
+
+ nudge_tracker.UpdateTypeThrottlingState(t1);
+
+ EXPECT_FALSE(nudge_tracker.IsAnyTypeThrottled());
+ EXPECT_FALSE(nudge_tracker.IsTypeThrottled(SESSIONS));
+ EXPECT_TRUE(nudge_tracker.GetThrottledTypes().Empty());
+}
+
+TEST_F(NudgeTrackerTest, OverlappingThrottleIntervals) {
+ NudgeTracker nudge_tracker;
+ const base::TimeTicks t0 = base::TimeTicks::FromInternalValue(1234);
+ const base::TimeDelta throttle1_length = base::TimeDelta::FromMinutes(10);
+ const base::TimeDelta throttle2_length = base::TimeDelta::FromMinutes(20);
+ const base::TimeTicks t1 = t0 + throttle1_length;
+ const base::TimeTicks t2 = t0 + throttle2_length;
+
+ // Setup the longer of two intervals.
+ nudge_tracker.SetTypesThrottledUntil(ModelTypeSet(SESSIONS, PREFERENCES),
+ throttle2_length,
+ t0);
+ EXPECT_TRUE(ModelTypeSetEquals(
+ ModelTypeSet(SESSIONS, PREFERENCES),
+ nudge_tracker.GetThrottledTypes()));
+ EXPECT_EQ(throttle2_length,
+ nudge_tracker.GetTimeUntilNextUnthrottle(t0));
+
+ // Setup the shorter interval.
+ nudge_tracker.SetTypesThrottledUntil(ModelTypeSet(SESSIONS, BOOKMARKS),
+ throttle1_length,
+ t0);
+ EXPECT_TRUE(ModelTypeSetEquals(
+ ModelTypeSet(SESSIONS, PREFERENCES, BOOKMARKS),
+ nudge_tracker.GetThrottledTypes()));
+ EXPECT_EQ(throttle1_length,
+ nudge_tracker.GetTimeUntilNextUnthrottle(t0));
+
+ // Expire the first interval.
+ nudge_tracker.UpdateTypeThrottlingState(t1);
+
+ // SESSIONS appeared in both intervals. We expect it will be throttled for
+ // the longer of the two, so it's still throttled at time t1.
+ EXPECT_TRUE(ModelTypeSetEquals(
+ ModelTypeSet(SESSIONS, PREFERENCES),
+ nudge_tracker.GetThrottledTypes()));
+ EXPECT_EQ(throttle2_length - throttle1_length,
+ nudge_tracker.GetTimeUntilNextUnthrottle(t1));
+
+ // Expire the second interval.
+ nudge_tracker.UpdateTypeThrottlingState(t2);
+ EXPECT_TRUE(nudge_tracker.GetThrottledTypes().Empty());
+}
+
+
} // namespace sessions
} // namespace syncer
diff --git a/sync/sessions/sync_session.cc b/sync/sessions/sync_session.cc
index c2214e5..e526954 100644
--- a/sync/sessions/sync_session.cc
+++ b/sync/sessions/sync_session.cc
@@ -61,7 +61,7 @@ SyncSessionSnapshot SyncSession::TakeSnapshot() const {
SyncSessionSnapshot snapshot(
status_controller_->model_neutral_state(),
download_progress_markers,
- delegate_->IsSyncingCurrentlySilenced(),
+ delegate_->IsCurrentlyThrottled(),
status_controller_->num_encryption_conflicts(),
status_controller_->num_hierarchy_conflicts(),
status_controller_->num_server_conflicts(),
diff --git a/sync/sessions/sync_session.h b/sync/sessions/sync_session.h
index a8bfb4d..dcb0220 100644
--- a/sync/sessions/sync_session.h
+++ b/sync/sessions/sync_session.h
@@ -47,7 +47,12 @@ class SYNC_EXPORT_PRIVATE SyncSession {
public:
// The client was throttled and should cease-and-desist syncing activity
// until the specified time.
- virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) = 0;
+ virtual void OnThrottled(const base::TimeDelta& throttle_duration) = 0;
+
+ // Some of the client's types were throttled.
+ virtual void OnTypesThrottled(
+ ModelTypeSet types,
+ const base::TimeDelta& throttle_duration) = 0;
// Silenced intervals can be out of phase with individual sessions, so the
// delegate is the only thing that can give an authoritative answer for
@@ -58,7 +63,7 @@ class SYNC_EXPORT_PRIVATE SyncSession {
// solely based on absolute time values. So, this cannot be used to infer
// that any given session _instance_ is silenced. An example of reasonable
// use is for UI reporting.
- virtual bool IsSyncingCurrentlySilenced() = 0;
+ virtual bool IsCurrentlyThrottled() = 0;
// The client has been instructed to change its short poll interval.
virtual void OnReceivedShortPollIntervalUpdate(
diff --git a/sync/sessions/sync_session_context.cc b/sync/sessions/sync_session_context.cc
index 41ed246..9043db3 100644
--- a/sync/sessions/sync_session_context.cc
+++ b/sync/sessions/sync_session_context.cc
@@ -4,7 +4,6 @@
#include "sync/sessions/sync_session_context.h"
-#include "sync/engine/throttled_data_type_tracker.h"
#include "sync/sessions/debug_info_getter.h"
#include "sync/util/extensions_activity_monitor.h"
@@ -19,7 +18,6 @@ SyncSessionContext::SyncSessionContext(
syncable::Directory* directory,
const std::vector<ModelSafeWorker*>& workers,
ExtensionsActivityMonitor* extensions_activity_monitor,
- ThrottledDataTypeTracker* throttled_data_type_tracker,
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
TrafficRecorder* traffic_recorder,
@@ -30,7 +28,6 @@ SyncSessionContext::SyncSessionContext(
extensions_activity_monitor_(extensions_activity_monitor),
notifications_enabled_(false),
max_commit_batch_size_(kDefaultMaxCommitBatchSize),
- throttled_data_type_tracker_(throttled_data_type_tracker),
debug_info_getter_(debug_info_getter),
traffic_recorder_(traffic_recorder),
keystore_encryption_enabled_(keystore_encryption_enabled),
diff --git a/sync/sessions/sync_session_context.h b/sync/sessions/sync_session_context.h
index a6f693a..b694162 100644
--- a/sync/sessions/sync_session_context.h
+++ b/sync/sessions/sync_session_context.h
@@ -34,7 +34,6 @@ namespace syncer {
class ExtensionsActivityMonitor;
class ServerConnectionManager;
-class ThrottledDataTypeTracker;
namespace syncable {
class Directory;
@@ -52,7 +51,6 @@ class SYNC_EXPORT_PRIVATE SyncSessionContext {
syncable::Directory* directory,
const std::vector<ModelSafeWorker*>& workers,
ExtensionsActivityMonitor* extensions_activity_monitor,
- ThrottledDataTypeTracker* throttled_data_type_tracker,
const std::vector<SyncEngineEventListener*>& listeners,
DebugInfoGetter* debug_info_getter,
TrafficRecorder* traffic_recorder,
@@ -84,10 +82,6 @@ class SYNC_EXPORT_PRIVATE SyncSessionContext {
return extensions_activity_monitor_;
}
- ThrottledDataTypeTracker* throttled_data_type_tracker() {
- return throttled_data_type_tracker_;
- }
-
DebugInfoGetter* debug_info_getter() {
return debug_info_getter_;
}
@@ -167,8 +161,6 @@ class SYNC_EXPORT_PRIVATE SyncSessionContext {
// The server limits the number of items a client can commit in one batch.
int max_commit_batch_size_;
- ThrottledDataTypeTracker* throttled_data_type_tracker_;
-
// We use this to get debug info to send to the server for debugging
// client behavior on server side.
DebugInfoGetter* const debug_info_getter_;
diff --git a/sync/sessions/sync_session_unittest.cc b/sync/sessions/sync_session_unittest.cc
index 861abbe..5de32e2 100644
--- a/sync/sessions/sync_session_unittest.cc
+++ b/sync/sessions/sync_session_unittest.cc
@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "sync/engine/syncer_types.h"
-#include "sync/engine/throttled_data_type_tracker.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/base/model_type_invalidation_map_test_util.h"
#include "sync/sessions/status_controller.h"
@@ -62,7 +61,6 @@ class SyncSessionTest : public testing::Test,
NULL,
workers,
&extensions_activity_monitor_,
- throttled_data_type_tracker_.get(),
std::vector<SyncEngineEventListener*>(),
NULL,
NULL,
@@ -71,17 +69,21 @@ class SyncSessionTest : public testing::Test,
context_->set_routing_info(routes_);
session_.reset(MakeSession());
- throttled_data_type_tracker_.reset(new ThrottledDataTypeTracker(NULL));
}
virtual void TearDown() {
session_.reset();
context_.reset();
}
- virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) OVERRIDE {
- FailControllerInvocationIfDisabled("OnSilencedUntil");
+ virtual void OnThrottled(const base::TimeDelta& throttle_duration) OVERRIDE {
+ FailControllerInvocationIfDisabled("OnThrottled");
}
- virtual bool IsSyncingCurrentlySilenced() OVERRIDE {
+ virtual void OnTypesThrottled(
+ ModelTypeSet types,
+ const base::TimeDelta& throttle_duration) OVERRIDE {
+ FailControllerInvocationIfDisabled("OnTypesThrottled");
+ }
+ virtual bool IsCurrentlyThrottled() OVERRIDE {
FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced");
return false;
}
@@ -144,7 +146,6 @@ class SyncSessionTest : public testing::Test,
std::vector<scoped_refptr<ModelSafeWorker> > workers_;
ModelSafeRoutingInfo routes_;
FakeExtensionsActivityMonitor extensions_activity_monitor_;
- scoped_ptr<ThrottledDataTypeTracker> throttled_data_type_tracker_;
};
TEST_F(SyncSessionTest, MoreToDownloadIfDownloadFailed) {
diff --git a/sync/sessions/test_util.cc b/sync/sessions/test_util.cc
index 03f6de2..24caa7b 100644
--- a/sync/sessions/test_util.cc
+++ b/sync/sessions/test_util.cc
@@ -4,8 +4,6 @@
#include "sync/sessions/test_util.h"
-#include "sync/engine/throttled_data_type_tracker.h"
-
namespace syncer {
namespace sessions {
namespace test_util {
@@ -42,14 +40,19 @@ void SimulateConnectionFailure(sessions::SyncSession* session,
void SimulateSuccess(sessions::SyncSession* session,
SyncerStep begin, SyncerStep end) {
+ const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source =
+ session->source().updates_source;
ASSERT_EQ(0U, session->status_controller().num_server_changes_remaining());
switch(end) {
case SYNCER_END:
session->mutable_status_controller()->set_commit_result(SYNCER_OK);
- // Fall through.
+ session->mutable_status_controller()->set_last_get_key_result(SYNCER_OK);
+ session->mutable_status_controller()->set_last_download_updates_result(
+ SYNCER_OK);
+ break;
case APPLY_UPDATES:
- DCHECK_EQ(end == APPLY_UPDATES, session->source().updates_source ==
- sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
+ DCHECK(source == sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
+ || source == sync_pb::GetUpdatesCallerInfo::PERIODIC);
session->mutable_status_controller()->set_last_get_key_result(SYNCER_OK);
session->mutable_status_controller()->set_last_download_updates_result(
SYNCER_OK);
@@ -63,7 +66,7 @@ void SimulateThrottledImpl(sessions::SyncSession* session,
const base::TimeDelta& delta) {
session->mutable_status_controller()->set_last_download_updates_result(
SERVER_RETURN_THROTTLED);
- session->delegate()->OnSilencedUntil(base::TimeTicks::Now() + delta);
+ session->delegate()->OnThrottled(delta);
}
void SimulateTypesThrottledImpl(
@@ -72,8 +75,7 @@ void SimulateTypesThrottledImpl(
const base::TimeDelta& delta) {
session->mutable_status_controller()->set_last_download_updates_result(
SERVER_RETURN_THROTTLED);
- session->context()->throttled_data_type_tracker()->
- SetUnthrottleTime(types, base::TimeTicks::Now() + delta);
+ session->delegate()->OnTypesThrottled(types, delta);
}
void SimulatePollIntervalUpdateImpl(sessions::SyncSession* session,