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

Side by Side Diff: net/url_request/url_request_throttler_entry.cc

Issue 10440119: Introduce a delegate to avoid hardcoding "chrome-extension" in net/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to review requests. Created 8 years, 6 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/url_request/url_request_throttler_entry.h" 5 #include "net/url_request/url_request_throttler_entry.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/rand_util.h" 12 #include "base/rand_util.h"
13 #include "base/string_number_conversions.h" 13 #include "base/string_number_conversions.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "net/base/load_flags.h" 15 #include "net/base/load_flags.h"
16 #include "net/base/net_log.h" 16 #include "net/base/net_log.h"
17 #include "net/url_request/url_request.h"
17 #include "net/url_request/url_request_throttler_header_interface.h" 18 #include "net/url_request/url_request_throttler_header_interface.h"
18 #include "net/url_request/url_request_throttler_manager.h" 19 #include "net/url_request/url_request_throttler_manager.h"
19 20
20 namespace net { 21 namespace net {
21 22
22 const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000; 23 const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000;
23 const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20; 24 const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20;
24 25
25 // This set of back-off parameters will (at maximum values, i.e. without 26 // This set of back-off parameters will (at maximum values, i.e. without
26 // the reduction caused by jitter) add 0-41% (distributed uniformly 27 // the reduction caused by jitter) add 0-41% (distributed uniformly
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 bool URLRequestThrottlerEntry::IsEntryOutdated() const { 132 bool URLRequestThrottlerEntry::IsEntryOutdated() const {
132 // This function is called by the URLRequestThrottlerManager to determine 133 // This function is called by the URLRequestThrottlerManager to determine
133 // whether entries should be discarded from its url_entries_ map. We 134 // whether entries should be discarded from its url_entries_ map. We
134 // want to ensure that it does not remove entries from the map while there 135 // want to ensure that it does not remove entries from the map while there
135 // are clients (objects other than the manager) holding references to 136 // are clients (objects other than the manager) holding references to
136 // the entry, otherwise separate clients could end up holding separate 137 // the entry, otherwise separate clients could end up holding separate
137 // entries for a request to the same URL, which is undesirable. Therefore, 138 // entries for a request to the same URL, which is undesirable. Therefore,
138 // if an entry has more than one reference (the map will always hold one), 139 // if an entry has more than one reference (the map will always hold one),
139 // it should not be considered outdated. 140 // it should not be considered outdated.
140 // 141 //
141 // TODO(joi): Once the manager is not a Singleton, revisit whether 142 // We considered whether to make URLRequestThrottlerEntry objects
142 // refcounting is needed at all. 143 // non-refcounted, but since any means of knowing whether they are
144 // currently in use by others than the manager would be more or less
145 // equivalent to a refcount, we kept them refcounted.
143 if (!HasOneRef()) 146 if (!HasOneRef())
144 return false; 147 return false;
145 148
146 // If there are send events in the sliding window period, we still need this 149 // If there are send events in the sliding window period, we still need this
147 // entry. 150 // entry.
148 if (!send_log_.empty() && 151 if (!send_log_.empty() &&
149 send_log_.back() + sliding_window_period_ > ImplGetTimeNow()) { 152 send_log_.back() + sliding_window_period_ > ImplGetTimeNow()) {
150 return false; 153 return false;
151 } 154 }
152 155
153 return GetBackoffEntry()->CanDiscard(); 156 return GetBackoffEntry()->CanDiscard();
154 } 157 }
155 158
156 void URLRequestThrottlerEntry::DisableBackoffThrottling() { 159 void URLRequestThrottlerEntry::DisableBackoffThrottling() {
157 is_backoff_disabled_ = true; 160 is_backoff_disabled_ = true;
eroman 2012/06/06 04:52:11 Is this still used?
Jói 2012/06/06 13:38:55 Yes, this is separate from the global flag; it's a
158 } 161 }
159 162
160 void URLRequestThrottlerEntry::DetachManager() { 163 void URLRequestThrottlerEntry::DetachManager() {
161 manager_ = NULL; 164 manager_ = NULL;
162 } 165 }
163 166
164 bool URLRequestThrottlerEntry::ShouldRejectRequest(int load_flags) const { 167 bool URLRequestThrottlerEntry::ShouldRejectRequest(const URLRequest* request,
168 int load_flags) const {
165 bool reject_request = false; 169 bool reject_request = false;
166 if (!is_backoff_disabled_ && !ExplicitUserRequest(load_flags) && 170 if (!is_backoff_disabled_ && !ExplicitUserRequest(load_flags) &&
171 (!request || !request->context() ||
172 request->context()->network_delegate()->CanRejectRequest(*request)) &&
eroman 2012/06/06 04:52:11 Is it possible for network_delegate() to be NULL (
Jói 2012/06/06 13:38:55 So say the trybots :) Added that to the check.
167 GetBackoffEntry()->ShouldRejectRequest()) { 173 GetBackoffEntry()->ShouldRejectRequest()) {
168 int num_failures = GetBackoffEntry()->failure_count(); 174 int num_failures = GetBackoffEntry()->failure_count();
169 int release_after_ms = 175 int release_after_ms =
170 GetBackoffEntry()->GetTimeUntilRelease().InMilliseconds(); 176 GetBackoffEntry()->GetTimeUntilRelease().InMilliseconds();
171 177
172 net_log_.AddEvent( 178 net_log_.AddEvent(
173 NetLog::TYPE_THROTTLING_REJECTED_REQUEST, 179 NetLog::TYPE_THROTTLING_REJECTED_REQUEST,
174 make_scoped_refptr( 180 make_scoped_refptr(
175 new RejectedRequestParameters(url_id_, 181 new RejectedRequestParameters(url_id_,
176 num_failures, 182 num_failures,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 // return "now" so that retries are not delayed. 236 // return "now" so that retries are not delayed.
231 if (is_backoff_disabled_) 237 if (is_backoff_disabled_)
232 return ImplGetTimeNow(); 238 return ImplGetTimeNow();
233 239
234 return GetBackoffEntry()->GetReleaseTime(); 240 return GetBackoffEntry()->GetReleaseTime();
235 } 241 }
236 242
237 void URLRequestThrottlerEntry::UpdateWithResponse( 243 void URLRequestThrottlerEntry::UpdateWithResponse(
238 const std::string& host, 244 const std::string& host,
239 const URLRequestThrottlerHeaderInterface* response) { 245 const URLRequestThrottlerHeaderInterface* response) {
240 int response_code = response->GetResponseCode(); 246 if (IsConsideredError(response->GetResponseCode())) {
241 HandleMetricsTracking(response_code);
242
243 if (IsConsideredError(response_code)) {
244 GetBackoffEntry()->InformOfRequest(false); 247 GetBackoffEntry()->InformOfRequest(false);
245 } else { 248 } else {
246 GetBackoffEntry()->InformOfRequest(true); 249 GetBackoffEntry()->InformOfRequest(true);
247 250
248 std::string throttling_header = response->GetNormalizedValue( 251 std::string throttling_header = response->GetNormalizedValue(
249 kExponentialThrottlingHeader); 252 kExponentialThrottlingHeader);
250 if (!throttling_header.empty()) 253 if (!throttling_header.empty())
251 HandleThrottlingHeader(throttling_header, host); 254 HandleThrottlingHeader(throttling_header, host);
252 } 255 }
253 } 256 }
(...skipping 19 matching lines...) Expand all
273 276
274 void URLRequestThrottlerEntry::Initialize() { 277 void URLRequestThrottlerEntry::Initialize() {
275 sliding_window_release_time_ = base::TimeTicks::Now(); 278 sliding_window_release_time_ = base::TimeTicks::Now();
276 backoff_policy_.num_errors_to_ignore = kDefaultNumErrorsToIgnore; 279 backoff_policy_.num_errors_to_ignore = kDefaultNumErrorsToIgnore;
277 backoff_policy_.initial_delay_ms = kDefaultInitialDelayMs; 280 backoff_policy_.initial_delay_ms = kDefaultInitialDelayMs;
278 backoff_policy_.multiply_factor = kDefaultMultiplyFactor; 281 backoff_policy_.multiply_factor = kDefaultMultiplyFactor;
279 backoff_policy_.jitter_factor = kDefaultJitterFactor; 282 backoff_policy_.jitter_factor = kDefaultJitterFactor;
280 backoff_policy_.maximum_backoff_ms = kDefaultMaximumBackoffMs; 283 backoff_policy_.maximum_backoff_ms = kDefaultMaximumBackoffMs;
281 backoff_policy_.entry_lifetime_ms = kDefaultEntryLifetimeMs; 284 backoff_policy_.entry_lifetime_ms = kDefaultEntryLifetimeMs;
282 backoff_policy_.always_use_initial_delay = false; 285 backoff_policy_.always_use_initial_delay = false;
283
284 // We pretend we just had a successful response so that we have a
285 // starting point to our tracking. This is called from the
286 // constructor so we do not use the virtual ImplGetTimeNow().
287 last_successful_response_time_ = base::TimeTicks::Now();
288 last_response_was_success_ = true;
289 } 286 }
290 287
291 bool URLRequestThrottlerEntry::IsConsideredError(int response_code) { 288 bool URLRequestThrottlerEntry::IsConsideredError(int response_code) {
292 // We throttle only for the status codes most likely to indicate the server 289 // We throttle only for the status codes most likely to indicate the server
293 // is failing because it is too busy or otherwise are likely to be 290 // is failing because it is too busy or otherwise are likely to be
294 // because of DDoS. 291 // because of DDoS.
295 // 292 //
296 // 500 is the generic error when no better message is suitable, and 293 // 500 is the generic error when no better message is suitable, and
297 // as such does not necessarily indicate a temporary state, but 294 // as such does not necessarily indicate a temporary state, but
298 // other status codes cover most of the permanent error states. 295 // other status codes cover most of the permanent error states.
(...skipping 16 matching lines...) Expand all
315 return base::TimeTicks::Now(); 312 return base::TimeTicks::Now();
316 } 313 }
317 314
318 void URLRequestThrottlerEntry::HandleThrottlingHeader( 315 void URLRequestThrottlerEntry::HandleThrottlingHeader(
319 const std::string& header_value, 316 const std::string& header_value,
320 const std::string& host) { 317 const std::string& host) {
321 if (header_value == kExponentialThrottlingDisableValue) { 318 if (header_value == kExponentialThrottlingDisableValue) {
322 DisableBackoffThrottling(); 319 DisableBackoffThrottling();
323 if (manager_) 320 if (manager_)
324 manager_->AddToOptOutList(host); 321 manager_->AddToOptOutList(host);
325 } else {
326 // TODO(joi): Log this.
327 } 322 }
328 } 323 }
329 324
330 void URLRequestThrottlerEntry::HandleMetricsTracking(int response_code) {
331 // Note that we are not interested in whether the code is considered
332 // an error for the backoff logic, but whether it is a 5xx error in
333 // general. This is because here, we are tracking the apparent total
334 // downtime of a server.
335 if (response_code >= 500) {
336 last_response_was_success_ = false;
337 } else {
338 base::TimeTicks now = ImplGetTimeNow();
339 if (!last_response_was_success_) {
340 // We are transitioning from failure to success, so generate our stats.
341 base::TimeDelta down_time = now - last_successful_response_time_;
342 int failure_count = GetBackoffEntry()->failure_count();
343
344 UMA_HISTOGRAM_COUNTS("Throttling.FailureCountAtSuccess", failure_count);
345 UMA_HISTOGRAM_CUSTOM_TIMES(
346 "Throttling.PerceivedDowntime", down_time,
347 base::TimeDelta::FromMilliseconds(10),
348 base::TimeDelta::FromHours(6), 50);
349 }
350
351 last_successful_response_time_ = now;
352 last_response_was_success_ = true;
353 }
354 }
355
356 const BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() const { 325 const BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() const {
357 return &backoff_entry_; 326 return &backoff_entry_;
358 } 327 }
359 328
360 BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() { 329 BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() {
361 return &backoff_entry_; 330 return &backoff_entry_;
362 } 331 }
363 332
364 // static 333 // static
365 bool URLRequestThrottlerEntry::ExplicitUserRequest(const int load_flags) { 334 bool URLRequestThrottlerEntry::ExplicitUserRequest(const int load_flags) {
366 return (load_flags & LOAD_MAYBE_USER_GESTURE) != 0; 335 return (load_flags & LOAD_MAYBE_USER_GESTURE) != 0;
367 } 336 }
368 337
369 } // namespace net 338 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698