Index: net/base/backoff_entry.cc |
diff --git a/net/base/backoff_entry.cc b/net/base/backoff_entry.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa35579024feaa25734898e18d2575960cd5cb16 |
--- /dev/null |
+++ b/net/base/backoff_entry.cc |
@@ -0,0 +1,112 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/base/backoff_entry.h" |
+ |
+#include <algorithm> |
+#include <cmath> |
+ |
+#include "base/logging.h" |
+#include "base/rand_util.h" |
+ |
+namespace net { |
+ |
+BackoffEntry::BackoffEntry(const BackoffEntry::Policy* policy) |
+ : failure_count_(0), |
+ policy_(policy) { |
+ DCHECK(policy_); |
+ |
+ // Can't use GetTimeNow() as it's virtual. |
+ exponential_backoff_release_time_ = base::TimeTicks::Now(); |
+} |
+ |
+BackoffEntry::~BackoffEntry() { |
+ // TODO(joi): Remove this once our clients (e.g. URLRequestThrottlerManager) |
+ // are no longer singletons, destroyed from main thread AtExit. |
+ DetachFromThread(); |
+} |
+ |
+void BackoffEntry::InformOfRequest(bool succeeded) { |
+ if (!succeeded) { |
+ failure_count_++; |
+ exponential_backoff_release_time_ = CalculateReleaseTime(); |
+ } else { |
+ failure_count_ = 0; |
+ |
+ // The reason why we are not just cutting the release time to GetTimeNow() |
+ // is on the one hand, it would unset delay put by our custom retry-after |
+ // header and on the other we would like to push every request up to our |
+ // "horizon" when dealing with multiple in-flight requests. Ex: If we send |
+ // three requests and we receive 2 failures and 1 success. The success that |
+ // follows those failures will not reset the release time, further requests |
+ // will then need to wait the delay caused by the 2 failures. |
+ exponential_backoff_release_time_ = std::max( |
+ GetTimeNow(), exponential_backoff_release_time_); |
+ } |
+} |
+ |
+bool BackoffEntry::ShouldRejectRequest() const { |
+ return exponential_backoff_release_time_ > GetTimeNow(); |
+} |
+ |
+base::TimeTicks BackoffEntry::GetReleaseTime() const { |
+ return exponential_backoff_release_time_; |
+} |
+ |
+void BackoffEntry::SetCustomReleaseTime(const base::TimeTicks release_time) { |
+ exponential_backoff_release_time_ = release_time; |
+} |
+ |
+bool BackoffEntry::CanDiscard() const { |
+ if (policy_->entry_lifetime_ms_ == -1) |
+ return false; |
+ |
+ base::TimeTicks now = GetTimeNow(); |
+ |
+ int64 unused_since_ms = |
+ (now - exponential_backoff_release_time_).InMilliseconds(); |
+ |
+ // Release time is further than now, we are managing it. |
+ if (unused_since_ms < 0) |
+ return false; |
+ |
+ if (failure_count_ > 0) { |
+ // Need to keep track of failures until maximum back-off period |
+ // has passed (since further failures can add to back-off). |
+ return unused_since_ms >= std::max(policy_->maximum_backoff_ms_, |
+ policy_->entry_lifetime_ms_); |
+ } |
+ |
+ // Otherwise, consider the entry is outdated if it hasn't been used for the |
+ // specified lifetime period. |
+ return unused_since_ms >= policy_->entry_lifetime_ms_; |
+} |
+ |
+base::TimeTicks BackoffEntry::GetTimeNow() const { |
+ return base::TimeTicks::Now(); |
+} |
+ |
+base::TimeTicks BackoffEntry::CalculateReleaseTime() const { |
+ int effective_failure_count = |
+ std::max(0, failure_count_ - policy_->num_errors_to_ignore_); |
+ if (effective_failure_count == 0) { |
+ return GetTimeNow(); |
+ } |
+ |
+ double delay = policy_->initial_backoff_ms_; |
+ delay *= pow(policy_->multiply_factor_, effective_failure_count - 1); |
+ delay -= base::RandDouble() * policy_->jitter_factor_ * delay; |
+ |
+ // Ensure that we do not exceed maximum delay. |
+ int64 delay_int = static_cast<int64>(delay + 0.5); |
+ delay_int = std::min(delay_int, |
+ static_cast<int64>(policy_->maximum_backoff_ms_)); |
+ |
+ // Never reduce previously set release horizon, e.g. due to Retry-After |
+ // header. |
+ return std::max(GetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int), |
+ exponential_backoff_release_time_); |
+} |
+ |
+} // namespace net |