Chromium Code Reviews| Index: components/sync/engine_impl/cycle/data_type_tracker.cc |
| diff --git a/components/sync/engine_impl/cycle/data_type_tracker.cc b/components/sync/engine_impl/cycle/data_type_tracker.cc |
| index 732bcdc172defb5868e7119ef21562d1018b11f0..72b851ff4892f55bf33c266d94ad4aa614b28081 100644 |
| --- a/components/sync/engine_impl/cycle/data_type_tracker.cc |
| +++ b/components/sync/engine_impl/cycle/data_type_tracker.cc |
| @@ -7,10 +7,38 @@ |
| #include <algorithm> |
| #include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| #include "components/sync/engine_impl/cycle/nudge_tracker.h" |
| namespace syncer { |
| +namespace { |
| + |
| +#define ENUM_CASE(x) \ |
| + case x: \ |
| + return #x; \ |
| + break; |
| + |
| +} // namespace |
| + |
| +WaitInterval::WaitInterval() : mode(UNKNOWN) {} |
| + |
| +WaitInterval::WaitInterval(BlockingMode mode, base::TimeDelta length) |
| + : mode(mode), length(length) {} |
| + |
| +WaitInterval::~WaitInterval() {} |
| + |
| +const char* WaitInterval::GetModeString(BlockingMode mode) { |
| + switch (mode) { |
| + ENUM_CASE(UNKNOWN); |
| + ENUM_CASE(EXPONENTIAL_BACKOFF); |
| + ENUM_CASE(THROTTLED); |
| + ENUM_CASE(EXPONENTIAL_BACKOFF_RETRYING); |
| + } |
| + NOTREACHED(); |
| + return ""; |
| +} |
| + |
| DataTypeTracker::DataTypeTracker() |
| : local_nudge_count_(0), |
| local_refresh_request_count_(0), |
| @@ -99,9 +127,14 @@ void DataTypeTracker::RecordCommitConflict() { |
| 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()) |
| + if (IsBlocked()) |
| return; |
| + // reset throtling and backoff state if state is EXPONENTIAL_BACKOFF_RETRYING |
|
Nicolas Zea
2016/11/14 21:57:15
nit: reset throtling -> Reset throttling. Also, yo
Gang Wu
2016/11/15 01:59:32
Done.
|
| + // or unset. |
| + unblock_time_ = base::TimeTicks(); |
| + wait_interval_.reset(); |
| + |
| local_nudge_count_ = 0; |
| local_refresh_request_count_ = 0; |
| @@ -131,11 +164,11 @@ void DataTypeTracker::UpdatePayloadBufferSize(size_t new_size) { |
| } |
| bool DataTypeTracker::IsSyncRequired() const { |
| - return !IsThrottled() && (HasLocalChangePending() || IsGetUpdatesRequired()); |
| + return !IsBlocked() && (HasLocalChangePending() || IsGetUpdatesRequired()); |
| } |
| bool DataTypeTracker::IsGetUpdatesRequired() const { |
| - return !IsThrottled() && |
| + return !IsBlocked() && |
| (HasRefreshRequestPending() || HasPendingInvalidation() || |
| IsInitialSyncRequired() || IsSyncRequiredToResolveConflict()); |
| } |
| @@ -162,8 +195,8 @@ bool DataTypeTracker::IsSyncRequiredToResolveConflict() const { |
| void DataTypeTracker::SetLegacyNotificationHint( |
| sync_pb::DataTypeProgressMarker* progress) const { |
| - DCHECK(!IsThrottled()) |
| - << "We should not make requests if the type is throttled."; |
| + DCHECK(!IsBlocked()) |
| + << "We should not make requests if the type is throttled or backed off."; |
| if (!pending_invalidations_.empty() && |
| !pending_invalidations_.back()->IsUnknownVersion()) { |
| @@ -203,27 +236,50 @@ void DataTypeTracker::FillGetUpdatesTriggersMessage( |
| sync_required_to_resolve_conflict_); |
| } |
| -bool DataTypeTracker::IsThrottled() const { |
| - return !unthrottle_time_.is_null(); |
| +bool DataTypeTracker::IsBlocked() const { |
| + return wait_interval_.get() && |
| + (wait_interval_->mode == WaitInterval::THROTTLED || |
| + wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF); |
| +} |
| + |
| +base::TimeDelta DataTypeTracker::GetTimeUntilUnblock() const { |
| + DCHECK(IsBlocked()); |
| + return std::max(base::TimeDelta::FromSeconds(0), |
| + unblock_time_ - base::TimeTicks::Now()); |
| } |
| -base::TimeDelta DataTypeTracker::GetTimeUntilUnthrottle( |
| - base::TimeTicks now) const { |
| - if (!IsThrottled()) { |
| +base::TimeDelta DataTypeTracker::GetLastBackoffInterval() const { |
| + if (GetBlockingMode() != WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) { |
| NOTREACHED(); |
| return base::TimeDelta::FromSeconds(0); |
| } |
| - return std::max(base::TimeDelta::FromSeconds(0), unthrottle_time_ - now); |
| + return wait_interval_->length; |
| } |
| void DataTypeTracker::ThrottleType(base::TimeDelta duration, |
| base::TimeTicks now) { |
| - unthrottle_time_ = std::max(unthrottle_time_, now + duration); |
| + unblock_time_ = std::max(unblock_time_, now + duration); |
| + wait_interval_ = |
| + base::MakeUnique<WaitInterval>(WaitInterval::THROTTLED, duration); |
| +} |
| + |
| +void DataTypeTracker::BackOffType(base::TimeDelta duration, |
| + base::TimeTicks now) { |
| + unblock_time_ = std::max(unblock_time_, now + duration); |
| + wait_interval_ = base::MakeUnique<WaitInterval>( |
| + WaitInterval::EXPONENTIAL_BACKOFF, duration); |
| } |
| -void DataTypeTracker::UpdateThrottleState(base::TimeTicks now) { |
| - if (now >= unthrottle_time_) { |
| - unthrottle_time_ = base::TimeTicks(); |
| +void DataTypeTracker::UpdateThrottleOrBackoffState() { |
| + if (base::TimeTicks::Now() >= unblock_time_) { |
| + if (wait_interval_.get() && |
| + (wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF || |
| + wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF_RETRYING)) { |
| + wait_interval_->mode = WaitInterval::EXPONENTIAL_BACKOFF_RETRYING; |
| + } else { |
| + unblock_time_ = base::TimeTicks(); |
| + wait_interval_.reset(); |
| + } |
| } |
| } |
| @@ -231,4 +287,11 @@ void DataTypeTracker::UpdateLocalNudgeDelay(base::TimeDelta delay) { |
| nudge_delay_ = delay; |
| } |
| +WaitInterval::BlockingMode DataTypeTracker::GetBlockingMode() const { |
| + if (!wait_interval_.get()) { |
| + return WaitInterval::UNKNOWN; |
| + } |
| + return wait_interval_->mode; |
| +} |
| + |
| } // namespace syncer |