Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: net/base/backoff_entry.cc

Issue 6966038: Anti-DDoS enhancements: Log to net log, UMA stats, improved policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to review comments. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/backoff_entry.h" 5 #include "net/base/backoff_entry.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/rand_util.h" 11 #include "base/rand_util.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy) 15 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy)
16 : failure_count_(0), 16 : failure_count_(0),
17 policy_(policy) { 17 policy_(policy) {
18 DCHECK(policy_); 18 DCHECK(policy_);
19 19
20 // Can't use GetTimeNow() as it's virtual. 20 // Can't use ImplGetTimeNow() as it's virtual.
wtc 2011/05/25 23:12:06 IMPORTANT: I wonder if the constructor should just
Jói 2011/05/26 14:53:42 Good point, I fixed this so that the constructor c
21 exponential_backoff_release_time_ = base::TimeTicks::Now(); 21 exponential_backoff_release_time_ = base::TimeTicks::Now();
22 } 22 }
23 23
24 BackoffEntry::~BackoffEntry() { 24 BackoffEntry::~BackoffEntry() {
25 // TODO(joi): Remove this once our clients (e.g. URLRequestThrottlerManager) 25 // TODO(joi): Remove this once our clients (e.g. URLRequestThrottlerManager)
26 // always destroy from the I/O thread. 26 // always destroy from the I/O thread.
27 DetachFromThread(); 27 DetachFromThread();
28 } 28 }
29 29
30 void BackoffEntry::InformOfRequest(bool succeeded) { 30 void BackoffEntry::InformOfRequest(bool succeeded) {
31 if (!succeeded) { 31 if (!succeeded) {
32 ++failure_count_; 32 ++failure_count_;
33 exponential_backoff_release_time_ = CalculateReleaseTime(); 33 exponential_backoff_release_time_ = CalculateReleaseTime();
34 } else { 34 } else {
35 // We slowly decay the number of times delayed instead of resetting it to 0 35 // We slowly decay the number of times delayed instead of resetting it to 0
36 // in order to stay stable if we receive successes interleaved between lots 36 // in order to stay stable if we receive successes interleaved between lots
37 // of failures. 37 // of failures.
38 // 38 //
39 // TODO(joi): Revisit this; it might be most correct to go to zero 39 // TODO(joi): Revisit this; it might be most correct to go to zero
40 // but have a way to go back to "old error count +1" if there is 40 // but have a way to go back to "old error count +1" if there is
41 // another error soon after. 41 // another error soon after.
42 if (failure_count_ > 0) 42 if (failure_count_ > 0)
43 --failure_count_; 43 --failure_count_;
44 44
45 // The reason why we are not just cutting the release time to GetTimeNow() 45 // The reason why we are not just cutting the release time to
46 // is on the one hand, it would unset a release time set by 46 // ImplGetTimeNow() is on the one hand, it would unset a release
47 // SetCustomReleaseTime and on the other we would like to push every 47 // time set by SetCustomReleaseTime and on the other we would like
48 // request up to our "horizon" when dealing with multiple in-flight 48 // to push every request up to our "horizon" when dealing with
49 // requests. Ex: If we send three requests and we receive 2 failures and 49 // multiple in-flight requests. Ex: If we send three requests and
50 // 1 success. The success that follows those failures will not reset the 50 // we receive 2 failures and 1 success. The success that follows
51 // release time, further requests will then need to wait the delay caused 51 // those failures will not reset the release time, further
52 // by the 2 failures. 52 // requests will then need to wait the delay caused by the 2
53 // failures.
53 exponential_backoff_release_time_ = std::max( 54 exponential_backoff_release_time_ = std::max(
54 GetTimeNow(), exponential_backoff_release_time_); 55 ImplGetTimeNow(), exponential_backoff_release_time_);
55 } 56 }
56 } 57 }
57 58
58 bool BackoffEntry::ShouldRejectRequest() const { 59 bool BackoffEntry::ShouldRejectRequest() const {
59 return exponential_backoff_release_time_ > GetTimeNow(); 60 return exponential_backoff_release_time_ > ImplGetTimeNow();
60 } 61 }
61 62
62 base::TimeTicks BackoffEntry::GetReleaseTime() const { 63 base::TimeTicks BackoffEntry::GetReleaseTime() const {
63 return exponential_backoff_release_time_; 64 return exponential_backoff_release_time_;
64 } 65 }
65 66
66 void BackoffEntry::SetCustomReleaseTime(const base::TimeTicks& release_time) { 67 void BackoffEntry::SetCustomReleaseTime(const base::TimeTicks& release_time) {
67 exponential_backoff_release_time_ = release_time; 68 exponential_backoff_release_time_ = release_time;
68 } 69 }
69 70
70 bool BackoffEntry::CanDiscard() const { 71 bool BackoffEntry::CanDiscard() const {
71 if (policy_->entry_lifetime_ms == -1) 72 if (policy_->entry_lifetime_ms == -1)
72 return false; 73 return false;
73 74
74 base::TimeTicks now = GetTimeNow(); 75 base::TimeTicks now = ImplGetTimeNow();
75 76
76 int64 unused_since_ms = 77 int64 unused_since_ms =
77 (now - exponential_backoff_release_time_).InMilliseconds(); 78 (now - exponential_backoff_release_time_).InMilliseconds();
78 79
79 // Release time is further than now, we are managing it. 80 // Release time is further than now, we are managing it.
80 if (unused_since_ms < 0) 81 if (unused_since_ms < 0)
81 return false; 82 return false;
82 83
83 if (failure_count_ > 0) { 84 if (failure_count_ > 0) {
84 // Need to keep track of failures until maximum back-off period 85 // Need to keep track of failures until maximum back-off period
85 // has passed (since further failures can add to back-off). 86 // has passed (since further failures can add to back-off).
86 return unused_since_ms >= std::max(policy_->maximum_backoff_ms, 87 return unused_since_ms >= std::max(policy_->maximum_backoff_ms,
87 policy_->entry_lifetime_ms); 88 policy_->entry_lifetime_ms);
88 } 89 }
89 90
90 // Otherwise, consider the entry is outdated if it hasn't been used for the 91 // Otherwise, consider the entry is outdated if it hasn't been used for the
91 // specified lifetime period. 92 // specified lifetime period.
92 return unused_since_ms >= policy_->entry_lifetime_ms; 93 return unused_since_ms >= policy_->entry_lifetime_ms;
93 } 94 }
94 95
95 base::TimeTicks BackoffEntry::GetTimeNow() const { 96 void BackoffEntry::Reset() {
97 failure_count_ = 0;
98 exponential_backoff_release_time_ = ImplGetTimeNow();
99 }
100
101 int BackoffEntry::failure_count() const {
102 return failure_count_;
103 }
104
105 base::TimeTicks BackoffEntry::ImplGetTimeNow() const {
96 return base::TimeTicks::Now(); 106 return base::TimeTicks::Now();
97 } 107 }
98 108
99 base::TimeTicks BackoffEntry::CalculateReleaseTime() const { 109 base::TimeTicks BackoffEntry::CalculateReleaseTime() const {
100 int effective_failure_count = 110 int effective_failure_count =
101 std::max(0, failure_count_ - policy_->num_errors_to_ignore); 111 std::max(0, failure_count_ - policy_->num_errors_to_ignore);
102 if (effective_failure_count == 0) { 112 if (effective_failure_count == 0) {
103 // Never reduce previously set release horizon, e.g. due to Retry-After 113 // Never reduce previously set release horizon, e.g. due to Retry-After
104 // header. 114 // header.
105 return std::max(GetTimeNow(), exponential_backoff_release_time_); 115 return std::max(ImplGetTimeNow(), exponential_backoff_release_time_);
106 } 116 }
107 117
108 // The delay is calculated with this formula: 118 // The delay is calculated with this formula:
109 // delay = initial_backoff * multiply_factor^( 119 // delay = initial_backoff * multiply_factor^(
110 // effective_failure_count - 1) * Uniform(1 - jitter_factor, 1] 120 // effective_failure_count - 1) * Uniform(1 - jitter_factor, 1]
111 double delay = policy_->initial_backoff_ms; 121 double delay = policy_->initial_backoff_ms;
112 delay *= pow(policy_->multiply_factor, effective_failure_count - 1); 122 delay *= pow(policy_->multiply_factor, effective_failure_count - 1);
113 delay -= base::RandDouble() * policy_->jitter_factor * delay; 123 delay -= base::RandDouble() * policy_->jitter_factor * delay;
114 124
115 // Ensure that we do not exceed maximum delay. 125 // Ensure that we do not exceed maximum delay.
116 int64 delay_int = static_cast<int64>(delay + 0.5); 126 int64 delay_int = static_cast<int64>(delay + 0.5);
117 delay_int = std::min(delay_int, 127 delay_int = std::min(delay_int,
118 static_cast<int64>(policy_->maximum_backoff_ms)); 128 static_cast<int64>(policy_->maximum_backoff_ms));
119 129
120 // Never reduce previously set release horizon, e.g. due to Retry-After 130 // Never reduce previously set release horizon, e.g. due to Retry-After
121 // header. 131 // header.
122 return std::max(GetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int), 132 return std::max(
123 exponential_backoff_release_time_); 133 ImplGetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int),
134 exponential_backoff_release_time_);
124 } 135 }
125 136
126 } // namespace net 137 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698