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

Side by Side Diff: chrome/common/net/url_fetcher.cc

Issue 4194001: Implement exponential back-off mechanism and enforce it at the URLRequestHttpJob level. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/common/net/url_fetcher.h" 5 #include "chrome/common/net/url_fetcher.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/lock.h" 11 #include "base/lock.h"
12 #include "base/message_loop_proxy.h" 12 #include "base/message_loop_proxy.h"
13 #include "base/scoped_ptr.h" 13 #include "base/scoped_ptr.h"
14 #include "base/stl_util-inl.h" 14 #include "base/stl_util-inl.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/thread.h" 16 #include "base/thread.h"
17 #include "chrome/common/net/url_fetcher_protect.h"
18 #include "chrome/common/net/url_request_context_getter.h" 17 #include "chrome/common/net/url_request_context_getter.h"
19 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
20 #include "net/base/load_flags.h" 19 #include "net/base/load_flags.h"
21 #include "net/base/io_buffer.h" 20 #include "net/base/io_buffer.h"
22 #include "net/http/http_request_headers.h" 21 #include "net/http/http_request_headers.h"
23 #include "net/http/http_response_headers.h" 22 #include "net/http/http_response_headers.h"
23 #include "net/request_throttler/request_throttler_manager.h"
24 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
26 26
27 static const int kBufferSize = 4096; 27 static const int kBufferSize = 4096;
28 28
29 bool URLFetcher::g_interception_enabled = false; 29 bool URLFetcher::g_interception_enabled = false;
30 30
31 class URLFetcher::Core 31 class URLFetcher::Core
32 : public base::RefCountedThreadSafe<URLFetcher::Core>, 32 : public base::RefCountedThreadSafe<URLFetcher::Core>,
33 public URLRequest::Delegate { 33 public URLRequest::Delegate {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // Read buffer 109 // Read buffer
110 scoped_refptr<URLRequestContextGetter> request_context_getter_; 110 scoped_refptr<URLRequestContextGetter> request_context_getter_;
111 // Cookie/cache info for the request 111 // Cookie/cache info for the request
112 ResponseCookies cookies_; // Response cookies 112 ResponseCookies cookies_; // Response cookies
113 net::HttpRequestHeaders extra_request_headers_; 113 net::HttpRequestHeaders extra_request_headers_;
114 scoped_refptr<net::HttpResponseHeaders> response_headers_; 114 scoped_refptr<net::HttpResponseHeaders> response_headers_;
115 115
116 std::string upload_content_; // HTTP POST payload 116 std::string upload_content_; // HTTP POST payload
117 std::string upload_content_type_; // MIME type of POST payload 117 std::string upload_content_type_; // MIME type of POST payload
118 118
119 // The overload protection entry for this URL. This is used to
120 // incrementally back off how rapidly we'll send requests to a particular
121 // URL, to avoid placing too much demand on the remote resource. We update
122 // this with the status of all requests as they return, and in turn use it
123 // to determine how long to wait before making another request.
124 URLFetcherProtectEntry* protect_entry_;
125 // |num_retries_| indicates how many times we've failed to successfully 119 // |num_retries_| indicates how many times we've failed to successfully
126 // fetch this URL. Once this value exceeds the maximum number of retries 120 // fetch this URL. Once this value exceeds the maximum number of retries
127 // specified by the protection manager, we'll give up. 121 // specified by the owner URLFetcher instance, we'll give up.
128 int num_retries_; 122 int num_retries_;
129 123
124 // Cache the pointer to the singleton object of RequestThrottlerManager.
125 // This is used to determine how long to wait before making a request or doing
126 // a retry.
127 RequestThrottlerManager* request_throttler_manager_;
128
130 // True if the URLFetcher has been cancelled. 129 // True if the URLFetcher has been cancelled.
131 bool was_cancelled_; 130 bool was_cancelled_;
132 131
133 static base::LazyInstance<Registry> g_registry; 132 static base::LazyInstance<Registry> g_registry;
134 133
135 friend class URLFetcher; 134 friend class URLFetcher;
136 DISALLOW_COPY_AND_ASSIGN(Core); 135 DISALLOW_COPY_AND_ASSIGN(Core);
137 }; 136 };
138 137
139 URLFetcher::Core::Registry::Registry() {} 138 URLFetcher::Core::Registry::Registry() {}
(...skipping 23 matching lines...) Expand all
163 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); 162 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED);
164 163
165 // static 164 // static
166 URLFetcher::Factory* URLFetcher::factory_ = NULL; 165 URLFetcher::Factory* URLFetcher::factory_ = NULL;
167 166
168 URLFetcher::URLFetcher(const GURL& url, 167 URLFetcher::URLFetcher(const GURL& url,
169 RequestType request_type, 168 RequestType request_type,
170 Delegate* d) 169 Delegate* d)
171 : ALLOW_THIS_IN_INITIALIZER_LIST( 170 : ALLOW_THIS_IN_INITIALIZER_LIST(
172 core_(new Core(this, url, request_type, d))), 171 core_(new Core(this, url, request_type, d))),
173 automatically_retry_on_5xx_(true) { 172 automatically_retry_on_5xx_(true),
173 max_retries_(0) {
174 } 174 }
175 175
176 URLFetcher::~URLFetcher() { 176 URLFetcher::~URLFetcher() {
177 core_->Stop(); 177 core_->Stop();
178 } 178 }
179 179
180 // static 180 // static
181 URLFetcher* URLFetcher::Create(int id, const GURL& url, 181 URLFetcher* URLFetcher::Create(int id, const GURL& url,
182 RequestType request_type, Delegate* d) { 182 RequestType request_type, Delegate* d) {
183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : 183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
184 new URLFetcher(url, request_type, d); 184 new URLFetcher(url, request_type, d);
185 } 185 }
186 186
187 URLFetcher::Core::Core(URLFetcher* fetcher, 187 URLFetcher::Core::Core(URLFetcher* fetcher,
188 const GURL& original_url, 188 const GURL& original_url,
189 RequestType request_type, 189 RequestType request_type,
190 URLFetcher::Delegate* d) 190 URLFetcher::Delegate* d)
191 : fetcher_(fetcher), 191 : fetcher_(fetcher),
192 original_url_(original_url), 192 original_url_(original_url),
193 request_type_(request_type), 193 request_type_(request_type),
194 delegate_(d), 194 delegate_(d),
195 delegate_loop_(MessageLoop::current()), 195 delegate_loop_(MessageLoop::current()),
196 request_(NULL), 196 request_(NULL),
197 load_flags_(net::LOAD_NORMAL), 197 load_flags_(net::LOAD_NORMAL),
198 response_code_(-1), 198 response_code_(-1),
199 buffer_(new net::IOBuffer(kBufferSize)), 199 buffer_(new net::IOBuffer(kBufferSize)),
200 protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
201 original_url_.host())),
202 num_retries_(0), 200 num_retries_(0),
201 request_throttler_manager_(Singleton<RequestThrottlerManager>::get()),
203 was_cancelled_(false) { 202 was_cancelled_(false) {
204 } 203 }
205 204
206 URLFetcher::Core::~Core() { 205 URLFetcher::Core::~Core() {
207 // |request_| should be NULL. If not, it's unsafe to delete it here since we 206 // |request_| should be NULL. If not, it's unsafe to delete it here since we
208 // may not be on the IO thread. 207 // may not be on the IO thread.
209 DCHECK(!request_.get()); 208 DCHECK(!request_.get());
210 } 209 }
211 210
212 void URLFetcher::Core::Start() { 211 void URLFetcher::Core::Start() {
213 DCHECK(delegate_loop_); 212 DCHECK(delegate_loop_);
214 CHECK(request_context_getter_) << "We need an URLRequestContext!"; 213 CHECK(request_context_getter_) << "We need an URLRequestContext!";
215 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); 214 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy();
216 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; 215 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy";
216
217 io_message_loop_proxy_->PostDelayedTask( 217 io_message_loop_proxy_->PostDelayedTask(
218 FROM_HERE, 218 FROM_HERE,
219 NewRunnableMethod(this, &Core::StartURLRequest), 219 NewRunnableMethod(this, &Core::StartURLRequest),
220 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); 220 request_throttler_manager_->GetBackoffDelayInMilliseconds(original_url_));
221 } 221 }
222 222
223 void URLFetcher::Core::Stop() { 223 void URLFetcher::Core::Stop() {
224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); 224 DCHECK_EQ(MessageLoop::current(), delegate_loop_);
225 delegate_ = NULL; 225 delegate_ = NULL;
226 fetcher_ = NULL; 226 fetcher_ = NULL;
227 if (io_message_loop_proxy_.get()) { 227 if (io_message_loop_proxy_.get()) {
228 io_message_loop_proxy_->PostTask( 228 io_message_loop_proxy_->PostTask(
229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); 229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest));
230 } 230 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 341 }
342 342
343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { 343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
344 DCHECK(MessageLoop::current() == delegate_loop_); 344 DCHECK(MessageLoop::current() == delegate_loop_);
345 345
346 // Checks the response from server. 346 // Checks the response from server.
347 if (response_code_ >= 500) { 347 if (response_code_ >= 500) {
348 // When encountering a server error, we will send the request again 348 // When encountering a server error, we will send the request again
349 // after backoff time. 349 // after backoff time.
350 int64 back_off_time = 350 int64 back_off_time =
351 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); 351 request_throttler_manager_->GetBackoffDelayInMilliseconds(url_);
352 if (delegate_) { 352 if (delegate_) {
353 fetcher_->backoff_delay_ = 353 fetcher_->backoff_delay_ =
354 base::TimeDelta::FromMilliseconds(back_off_time); 354 base::TimeDelta::FromMilliseconds(back_off_time);
355 } 355 }
356 ++num_retries_; 356 ++num_retries_;
357 // Restarts the request if we still need to notify the delegate. 357 // Restarts the request if we still need to notify the delegate.
358 if (delegate_) { 358 if (delegate_) {
359 if (fetcher_->automatically_retry_on_5xx_ && 359 if (fetcher_->automatically_retry_on_5xx_ &&
360 num_retries_ <= protect_entry_->max_retries()) { 360 num_retries_ <= fetcher_->max_retries()) {
361 io_message_loop_proxy_->PostDelayedTask( 361 io_message_loop_proxy_->PostDelayedTask(
362 FROM_HERE, 362 FROM_HERE,
363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); 363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time);
364 } else { 364 } else {
365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
366 cookies_, data_); 366 cookies_, data_);
367 } 367 }
368 } 368 }
369 } else { 369 } else {
370 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
371 if (delegate_) { 370 if (delegate_) {
372 fetcher_->backoff_delay_ = base::TimeDelta(); 371 fetcher_->backoff_delay_ = base::TimeDelta();
373 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 372 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
374 cookies_, data_); 373 cookies_, data_);
375 } 374 }
376 } 375 }
377 } 376 }
378 377
379 void URLFetcher::Core::ReleaseRequest() { 378 void URLFetcher::Core::ReleaseRequest() {
380 request_.reset(); 379 request_.reset();
381 g_registry.Get().RemoveURLFetcherCore(this); 380 g_registry.Get().RemoveURLFetcherCore(this);
382 } 381 }
383 382
384 void URLFetcher::set_upload_data(const std::string& upload_content_type, 383 void URLFetcher::set_upload_data(const std::string& upload_content_type,
385 const std::string& upload_content) { 384 const std::string& upload_content) {
386 core_->upload_content_type_ = upload_content_type; 385 core_->upload_content_type_ = upload_content_type;
387 core_->upload_content_ = upload_content; 386 core_->upload_content_ = upload_content;
388 } 387 }
389 388
390 const std::string& URLFetcher::upload_data() const { 389 const std::string& URLFetcher::upload_data() const {
391 return core_->upload_content_; 390 return core_->upload_content_;
392 } 391 }
393 392
394 void URLFetcher::set_load_flags(int load_flags) { 393 void URLFetcher::set_load_flags(int load_flags) {
395 core_->load_flags_ = load_flags; 394 core_->load_flags_ = load_flags;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 } 426 }
428 427
429 // static 428 // static
430 void URLFetcher::CancelAll() { 429 void URLFetcher::CancelAll() {
431 Core::CancelAll(); 430 Core::CancelAll();
432 } 431 }
433 432
434 URLFetcher::Delegate* URLFetcher::delegate() const { 433 URLFetcher::Delegate* URLFetcher::delegate() const {
435 return core_->delegate(); 434 return core_->delegate();
436 } 435 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698