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

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

Issue 9369045: [net] HostResolverImpl + DnsTransaction + DnsConfigService = Asynchronous DNS ready for experiments. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased to master. Created 8 years, 10 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/base/host_resolver_impl.h" 5 #include "net/base/host_resolver_impl.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <Winsock2.h> 8 #include <Winsock2.h>
9 #elif defined(OS_POSIX) 9 #elif defined(OS_POSIX)
10 #include <netdb.h> 10 #include <netdb.h>
11 #endif 11 #endif
12 12
13 #include <cmath> 13 #include <cmath>
14 #include <utility> 14 #include <utility>
15 #include <vector> 15 #include <vector>
16 16
17 #include "base/basictypes.h" 17 #include "base/basictypes.h"
18 #include "base/bind.h" 18 #include "base/bind.h"
19 #include "base/bind_helpers.h" 19 #include "base/bind_helpers.h"
20 #include "base/callback.h" 20 #include "base/callback.h"
21 #include "base/compiler_specific.h" 21 #include "base/compiler_specific.h"
22 #include "base/debug/debugger.h" 22 #include "base/debug/debugger.h"
23 #include "base/debug/stack_trace.h" 23 #include "base/debug/stack_trace.h"
24 #include "base/message_loop_proxy.h" 24 #include "base/message_loop_proxy.h"
25 #include "base/metrics/field_trial.h" 25 #include "base/metrics/field_trial.h"
26 #include "base/metrics/histogram.h" 26 #include "base/metrics/histogram.h"
27 #include "base/rand_util.h"
27 #include "base/stl_util.h" 28 #include "base/stl_util.h"
28 #include "base/string_util.h" 29 #include "base/string_util.h"
29 #include "base/threading/worker_pool.h" 30 #include "base/threading/worker_pool.h"
30 #include "base/time.h" 31 #include "base/time.h"
31 #include "base/utf_string_conversions.h" 32 #include "base/utf_string_conversions.h"
32 #include "base/values.h" 33 #include "base/values.h"
34 #include "net/base/address_family.h"
33 #include "net/base/address_list.h" 35 #include "net/base/address_list.h"
34 #include "net/base/address_list_net_log_param.h" 36 #include "net/base/address_list_net_log_param.h"
35 #include "net/base/dns_reloader.h" 37 #include "net/base/dns_reloader.h"
36 #include "net/base/host_port_pair.h" 38 #include "net/base/host_port_pair.h"
37 #include "net/base/host_resolver_proc.h" 39 #include "net/base/host_resolver_proc.h"
38 #include "net/base/net_errors.h" 40 #include "net/base/net_errors.h"
39 #include "net/base/net_log.h" 41 #include "net/base/net_log.h"
40 #include "net/base/net_util.h" 42 #include "net/base/net_util.h"
43 #include "net/dns/dns_config_service.h"
44 #include "net/dns/dns_protocol.h"
45 #include "net/dns/dns_response.h"
46 #include "net/dns/dns_session.h"
47 #include "net/dns/dns_transaction.h"
48 #include "net/socket/client_socket_factory.h"
41 49
42 #if defined(OS_WIN) 50 #if defined(OS_WIN)
43 #include "net/base/winsock_init.h" 51 #include "net/base/winsock_init.h"
44 #endif 52 #endif
45 53
46 namespace net { 54 namespace net {
47 55
48 namespace { 56 namespace {
49 57
50 // Limit the size of hostnames that will be resolved to combat issues in 58 // Limit the size of hostnames that will be resolved to combat issues in
51 // some platform's resolvers. 59 // some platform's resolvers.
52 const size_t kMaxHostLength = 4096; 60 const size_t kMaxHostLength = 4096;
53 61
54 // Default TTL for successful resolutions with ProcTask. 62 // Default TTL for successful resolutions with ProcTask.
55 const unsigned kCacheEntryTTLSeconds = 60; 63 const unsigned kCacheEntryTTLSeconds = 60;
56 64
65 // Default TTL for unsuccessful resolutions with ProcTask.
66 const unsigned kNegativeCacheEntryTTLSeconds = 0;
67
57 // Maximum of 8 concurrent resolver threads (excluding retries). 68 // Maximum of 8 concurrent resolver threads (excluding retries).
58 // Some routers (or resolvers) appear to start to provide host-not-found if 69 // Some routers (or resolvers) appear to start to provide host-not-found if
59 // too many simultaneous resolutions are pending. This number needs to be 70 // too many simultaneous resolutions are pending. This number needs to be
60 // further optimized, but 8 is what FF currently does. 71 // further optimized, but 8 is what FF currently does.
61 static const size_t kDefaultMaxProcTasks = 8u; 72 static const size_t kDefaultMaxProcTasks = 8u;
62 73
63 // Helper to mutate the linked list contained by AddressList to the given 74 // Helper to mutate the linked list contained by AddressList to the given
64 // port. Note that in general this is dangerous since the AddressList's 75 // port. Note that in general this is dangerous since the AddressList's
65 // data might be shared (and you should use AddressList::SetPort). 76 // data might be shared (and you should use AddressList::SetPort).
66 // 77 //
67 // However since we allocated the AddressList ourselves we can safely 78 // However since we allocated the AddressList ourselves we can safely
68 // do this optimization and avoid reallocating the list. 79 // do this optimization and avoid reallocating the list.
69 void MutableSetPort(int port, AddressList* addrlist) { 80 void MutableSetPort(int port, AddressList* addr_list) {
70 struct addrinfo* mutable_head = 81 struct addrinfo* mutable_head =
71 const_cast<struct addrinfo*>(addrlist->head()); 82 const_cast<struct addrinfo*>(addr_list->head());
72 SetPortForAllAddrinfos(mutable_head, port); 83 SetPortForAllAddrinfos(mutable_head, port);
73 } 84 }
74 85
75 // We use a separate histogram name for each platform to facilitate the 86 // We use a separate histogram name for each platform to facilitate the
76 // display of error codes by their symbolic name (since each platform has 87 // display of error codes by their symbolic name (since each platform has
77 // different mappings). 88 // different mappings).
78 const char kOSErrorsForGetAddrinfoHistogramName[] = 89 const char kOSErrorsForGetAddrinfoHistogramName[] =
79 #if defined(OS_WIN) 90 #if defined(OS_WIN)
80 "Net.OSErrorsForGetAddrinfo_Win"; 91 "Net.OSErrorsForGetAddrinfo_Win";
81 #elif defined(OS_MACOSX) 92 #elif defined(OS_MACOSX)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 148 }
138 149
139 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. 150 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc.
140 // TODO(szym): This should probably be declared in host_resolver_proc.h. 151 // TODO(szym): This should probably be declared in host_resolver_proc.h.
141 class CallSystemHostResolverProc : public HostResolverProc { 152 class CallSystemHostResolverProc : public HostResolverProc {
142 public: 153 public:
143 CallSystemHostResolverProc() : HostResolverProc(NULL) {} 154 CallSystemHostResolverProc() : HostResolverProc(NULL) {}
144 virtual int Resolve(const std::string& hostname, 155 virtual int Resolve(const std::string& hostname,
145 AddressFamily address_family, 156 AddressFamily address_family,
146 HostResolverFlags host_resolver_flags, 157 HostResolverFlags host_resolver_flags,
147 AddressList* addrlist, 158 AddressList* addr_list,
148 int* os_error) OVERRIDE { 159 int* os_error) OVERRIDE {
149 return SystemHostResolverProc(hostname, 160 return SystemHostResolverProc(hostname,
150 address_family, 161 address_family,
151 host_resolver_flags, 162 host_resolver_flags,
152 addrlist, 163 addr_list,
153 os_error); 164 os_error);
154 } 165 }
155 }; 166 };
156 167
157 // Extra parameters to attach to the NetLog when the resolve failed. 168 // Extra parameters to attach to the NetLog when the resolve failed.
158 class HostResolveFailedParams : public NetLog::EventParameters { 169 class ProcTaskFailedParams : public NetLog::EventParameters {
159 public: 170 public:
160 HostResolveFailedParams(uint32 attempt_number, 171 ProcTaskFailedParams(uint32 attempt_number, int net_error, int os_error)
161 int net_error,
162 int os_error)
163 : attempt_number_(attempt_number), 172 : attempt_number_(attempt_number),
164 net_error_(net_error), 173 net_error_(net_error),
165 os_error_(os_error) { 174 os_error_(os_error) {
166 } 175 }
167 176
168 virtual Value* ToValue() const OVERRIDE { 177 virtual Value* ToValue() const OVERRIDE {
169 DictionaryValue* dict = new DictionaryValue(); 178 DictionaryValue* dict = new DictionaryValue();
170 if (attempt_number_) 179 if (attempt_number_)
171 dict->SetInteger("attempt_number", attempt_number_); 180 dict->SetInteger("attempt_number", attempt_number_);
172 181
(...skipping 21 matching lines...) Expand all
194 203
195 return dict; 204 return dict;
196 } 205 }
197 206
198 private: 207 private:
199 const uint32 attempt_number_; 208 const uint32 attempt_number_;
200 const int net_error_; 209 const int net_error_;
201 const int os_error_; 210 const int os_error_;
202 }; 211 };
203 212
213 // Extra parameters to attach to the NetLog when the DnsTask failed.
214 class DnsTaskFailedParams : public NetLog::EventParameters {
215 public:
216 DnsTaskFailedParams(int net_error, int dns_error)
217 : net_error_(net_error), dns_error_(dns_error) {
218 }
219
220 virtual Value* ToValue() const OVERRIDE {
221 DictionaryValue* dict = new DictionaryValue();
222 dict->SetInteger("net_error", net_error_);
223 if (dns_error_)
224 dict->SetInteger("dns_error", dns_error_);
225 return dict;
226 }
227
228 private:
229 const int net_error_;
230 const int dns_error_;
231 };
232
204 // Parameters representing the information in a RequestInfo object, along with 233 // Parameters representing the information in a RequestInfo object, along with
205 // the associated NetLog::Source. 234 // the associated NetLog::Source.
206 class RequestInfoParameters : public NetLog::EventParameters { 235 class RequestInfoParameters : public NetLog::EventParameters {
207 public: 236 public:
208 RequestInfoParameters(const HostResolver::RequestInfo& info, 237 RequestInfoParameters(const HostResolver::RequestInfo& info,
209 const NetLog::Source& source) 238 const NetLog::Source& source)
210 : info_(info), source_(source) {} 239 : info_(info), source_(source) {}
211 240
212 virtual Value* ToValue() const OVERRIDE { 241 virtual Value* ToValue() const OVERRIDE {
213 DictionaryValue* dict = new DictionaryValue(); 242 DictionaryValue* dict = new DictionaryValue();
214 dict->SetString("host", info_.host_port_pair().ToString()); 243 dict->SetString("host", info_.host_port_pair().ToString());
215 dict->SetInteger("address_family", 244 dict->SetInteger("address_family",
216 static_cast<int>(info_.address_family())); 245 static_cast<int>(info_.address_family()));
217 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); 246 dict->SetBoolean("allow_cached_response", info_.allow_cached_response());
218 dict->SetBoolean("is_speculative", info_.is_speculative()); 247 dict->SetBoolean("is_speculative", info_.is_speculative());
219 dict->SetInteger("priority", info_.priority()); 248 dict->SetInteger("priority", info_.priority());
220 249
221 if (source_.is_valid()) 250 if (source_.is_valid())
222 dict->Set("source_dependency", source_.ToValue()); 251 dict->Set("source_dependency", source_.ToValue());
223 252
224 return dict; 253 return dict;
225 } 254 }
226 255
227 private: 256 private:
228 const HostResolver::RequestInfo info_; 257 const HostResolver::RequestInfo info_;
229 const NetLog::Source source_; 258 const NetLog::Source source_;
230 }; 259 };
231 260
232 // Parameters associated with the creation of a HostResolverImpl::Job 261 // Parameters associated with the creation of a HostResolverImpl::Job.
233 // or a HostResolverImpl::ProcTask.
234 class JobCreationParameters : public NetLog::EventParameters { 262 class JobCreationParameters : public NetLog::EventParameters {
235 public: 263 public:
236 JobCreationParameters(const std::string& host, 264 JobCreationParameters(const std::string& host,
237 const NetLog::Source& source) 265 const NetLog::Source& source)
238 : host_(host), source_(source) {} 266 : host_(host), source_(source) {}
239 267
240 virtual Value* ToValue() const OVERRIDE { 268 virtual Value* ToValue() const OVERRIDE {
241 DictionaryValue* dict = new DictionaryValue(); 269 DictionaryValue* dict = new DictionaryValue();
242 dict->SetString("host", host_); 270 dict->SetString("host", host_);
243 dict->Set("source_dependency", source_.ToValue()); 271 dict->Set("source_dependency", source_.ToValue());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 request_net_log.BeginEvent( 311 request_net_log.BeginEvent(
284 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, 312 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
285 make_scoped_refptr(new RequestInfoParameters( 313 make_scoped_refptr(new RequestInfoParameters(
286 info, source_net_log.source()))); 314 info, source_net_log.source())));
287 } 315 }
288 316
289 // Logs when a request has just completed (before its callback is run). 317 // Logs when a request has just completed (before its callback is run).
290 void LogFinishRequest(const BoundNetLog& source_net_log, 318 void LogFinishRequest(const BoundNetLog& source_net_log,
291 const BoundNetLog& request_net_log, 319 const BoundNetLog& request_net_log,
292 const HostResolver::RequestInfo& info, 320 const HostResolver::RequestInfo& info,
293 int net_error, 321 int net_error) {
294 int os_error) { 322 request_net_log.EndEventWithNetErrorCode(
295 scoped_refptr<NetLog::EventParameters> params; 323 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, net_error);
296 if (net_error != OK) {
297 params = new HostResolveFailedParams(0, net_error, os_error);
298 }
299
300 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params);
301 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); 324 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
302 } 325 }
303 326
304 // Logs when a request has been cancelled. 327 // Logs when a request has been cancelled.
305 void LogCancelRequest(const BoundNetLog& source_net_log, 328 void LogCancelRequest(const BoundNetLog& source_net_log,
306 const BoundNetLog& request_net_log, 329 const BoundNetLog& request_net_log,
307 const HostResolverImpl::RequestInfo& info) { 330 const HostResolverImpl::RequestInfo& info) {
308 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); 331 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL);
309 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); 332 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL);
310 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); 333 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
311 } 334 }
312 335
313 //----------------------------------------------------------------------------- 336 //-----------------------------------------------------------------------------
314 337
315 // Keeps track of the highest priority. 338 // Keeps track of the highest priority.
316 class PriorityTracker { 339 class PriorityTracker {
317 public: 340 public:
318 PriorityTracker() 341 explicit PriorityTracker(RequestPriority priority)
319 : highest_priority_(IDLE), total_count_(0) { 342 : highest_priority_(priority), total_count_(0) {
320 memset(counts_, 0, sizeof(counts_)); 343 memset(counts_, 0, sizeof(counts_));
321 } 344 }
322 345
323 RequestPriority highest_priority() const { 346 RequestPriority highest_priority() const {
324 return highest_priority_; 347 return highest_priority_;
325 } 348 }
326 349
327 size_t total_count() const { 350 size_t total_count() const {
328 return total_count_; 351 return total_count_;
329 } 352 }
(...skipping 24 matching lines...) Expand all
354 private: 377 private:
355 RequestPriority highest_priority_; 378 RequestPriority highest_priority_;
356 size_t total_count_; 379 size_t total_count_;
357 size_t counts_[NUM_PRIORITIES]; 380 size_t counts_[NUM_PRIORITIES];
358 }; 381 };
359 382
360 //----------------------------------------------------------------------------- 383 //-----------------------------------------------------------------------------
361 384
362 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, 385 HostResolver* CreateHostResolver(size_t max_concurrent_resolves,
363 size_t max_retry_attempts, 386 size_t max_retry_attempts,
364 bool use_cache, 387 HostCache* cache,
388 scoped_ptr<DnsConfigService> config_service,
365 NetLog* net_log) { 389 NetLog* net_log) {
366 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) 390 if (max_concurrent_resolves == HostResolver::kDefaultParallelism)
367 max_concurrent_resolves = kDefaultMaxProcTasks; 391 max_concurrent_resolves = kDefaultMaxProcTasks;
368 392
369 // TODO(szym): Add experiments with reserved slots for higher priority 393 // TODO(szym): Add experiments with reserved slots for higher priority
370 // requests. 394 // requests.
371 395
372 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); 396 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves);
373 397
374 HostResolverImpl* resolver = new HostResolverImpl( 398 HostResolverImpl* resolver = new HostResolverImpl(
375 use_cache ? HostCache::CreateDefaultCache() : NULL, 399 cache,
376 limits, 400 limits,
377 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), 401 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts),
402 config_service.Pass(),
378 net_log); 403 net_log);
379 404
380 return resolver; 405 return resolver;
381 } 406 }
382 407
383 } // anonymous namespace 408 } // anonymous namespace
384 409
385 //----------------------------------------------------------------------------- 410 //-----------------------------------------------------------------------------
386 411
387 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, 412 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
388 size_t max_retry_attempts, 413 size_t max_retry_attempts,
389 NetLog* net_log) { 414 NetLog* net_log) {
390 return CreateHostResolver(max_concurrent_resolves, 415 return CreateHostResolver(max_concurrent_resolves,
391 max_retry_attempts, 416 max_retry_attempts,
392 true /* use_cache */, 417 HostCache::CreateDefaultCache(),
418 scoped_ptr<DnsConfigService>(NULL),
393 net_log); 419 net_log);
394 } 420 }
395 421
396 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, 422 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves,
397 size_t max_retry_attempts, 423 size_t max_retry_attempts,
398 NetLog* net_log) { 424 NetLog* net_log) {
399 return CreateHostResolver(max_concurrent_resolves, 425 return CreateHostResolver(max_concurrent_resolves,
400 max_retry_attempts, 426 max_retry_attempts,
401 false /* use_cache */, 427 NULL,
428 scoped_ptr<DnsConfigService>(NULL),
402 net_log); 429 net_log);
403 } 430 }
404 431
432 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves,
433 size_t max_retry_attempts,
434 NetLog* net_log) {
435 scoped_ptr<DnsConfigService> config_service =
436 DnsConfigService::CreateSystemService();
437 config_service->Watch();
mmenke 2012/02/21 16:34:24 This was going to be moved to HostResolverImpl, ri
szym 2012/02/21 17:18:20 The order of AddObserver and Watch doesn't matter.
438 return CreateHostResolver(max_concurrent_resolves,
439 max_retry_attempts,
440 HostCache::CreateDefaultCache(),
441 config_service.Pass(),
442 net_log);
443 }
444
405 //----------------------------------------------------------------------------- 445 //-----------------------------------------------------------------------------
406 446
407 // Holds the data for a request that could not be completed synchronously. 447 // Holds the data for a request that could not be completed synchronously.
408 // It is owned by a Job. Canceled Requests are only marked as canceled rather 448 // It is owned by a Job. Canceled Requests are only marked as canceled rather
409 // than removed from the Job's |requests_| list. 449 // than removed from the Job's |requests_| list.
410 class HostResolverImpl::Request { 450 class HostResolverImpl::Request {
411 public: 451 public:
412 Request(const BoundNetLog& source_net_log, 452 Request(const BoundNetLog& source_net_log,
413 const BoundNetLog& request_net_log, 453 const BoundNetLog& request_net_log,
414 const RequestInfo& info, 454 const RequestInfo& info,
(...skipping 18 matching lines...) Expand all
433 return callback_.is_null(); 473 return callback_.is_null();
434 } 474 }
435 475
436 void set_job(Job* job) { 476 void set_job(Job* job) {
437 DCHECK(job); 477 DCHECK(job);
438 // Identify which job the request is waiting on. 478 // Identify which job the request is waiting on.
439 job_ = job; 479 job_ = job;
440 } 480 }
441 481
442 // Prepare final AddressList and call completion callback. 482 // Prepare final AddressList and call completion callback.
443 void OnComplete(int error, const AddressList& addrlist) { 483 void OnComplete(int error, const AddressList& addr_list) {
444 if (error == OK) 484 if (error == OK)
445 *addresses_ = CreateAddressListUsingPort(addrlist, info_.port()); 485 *addresses_ = CreateAddressListUsingPort(addr_list, info_.port());
446 CompletionCallback callback = callback_; 486 CompletionCallback callback = callback_;
447 MarkAsCanceled(); 487 MarkAsCanceled();
448 callback.Run(error); 488 callback.Run(error);
449 } 489 }
450 490
451 Job* job() const { 491 Job* job() const {
452 return job_; 492 return job_;
453 } 493 }
454 494
455 // NetLog for the source, passed in HostResolver::Resolve. 495 // NetLog for the source, passed in HostResolver::Resolve.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 // resolution (OnLookupComplete) is completed or not. If the original attempt 538 // resolution (OnLookupComplete) is completed or not. If the original attempt
499 // hasn't completed, then we start another attempt for host resolution. We take 539 // hasn't completed, then we start another attempt for host resolution. We take
500 // the results from the first attempt that finishes and ignore the results from 540 // the results from the first attempt that finishes and ignore the results from
501 // all other attempts. 541 // all other attempts.
502 // 542 //
503 // TODO(szym): Move to separate source file for testing and mocking. 543 // TODO(szym): Move to separate source file for testing and mocking.
504 // 544 //
505 class HostResolverImpl::ProcTask 545 class HostResolverImpl::ProcTask
506 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { 546 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> {
507 public: 547 public:
508 typedef base::Callback<void(int, int, const AddressList&)> Callback; 548 typedef base::Callback<void(int net_error,
549 const AddressList& addr_list)> Callback;
509 550
510 ProcTask(const Key& key, 551 ProcTask(const Key& key,
511 const ProcTaskParams& params, 552 const ProcTaskParams& params,
512 const Callback& callback, 553 const Callback& callback,
513 const BoundNetLog& job_net_log) 554 const BoundNetLog& job_net_log)
514 : key_(key), 555 : key_(key),
515 params_(params), 556 params_(params),
516 callback_(callback), 557 callback_(callback),
517 origin_loop_(base::MessageLoopProxy::current()), 558 origin_loop_(base::MessageLoopProxy::current()),
518 attempt_number_(0), 559 attempt_number_(0),
519 completed_attempt_number_(0), 560 completed_attempt_number_(0),
520 completed_attempt_error_(ERR_UNEXPECTED), 561 completed_attempt_error_(ERR_UNEXPECTED),
521 had_non_speculative_request_(false), 562 had_non_speculative_request_(false),
522 net_log_(BoundNetLog::Make( 563 net_log_(job_net_log) {
523 job_net_log.net_log(),
524 NetLog::SOURCE_HOST_RESOLVER_IMPL_PROC_TASK)) {
525 if (!params_.resolver_proc) 564 if (!params_.resolver_proc)
526 params_.resolver_proc = HostResolverProc::GetDefault(); 565 params_.resolver_proc = HostResolverProc::GetDefault();
527 // If default is unset, use the system proc. 566 // If default is unset, use the system proc.
528 if (!params_.resolver_proc) 567 if (!params_.resolver_proc)
529 params_.resolver_proc = new CallSystemHostResolverProc(); 568 params_.resolver_proc = new CallSystemHostResolverProc();
530 569
531 job_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_PROC_TASK, 570 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL);
532 new NetLogSourceParameter("source_dependency",
533 net_log_.source()));
534
535 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK,
536 new JobCreationParameters(key_.hostname,
537 job_net_log.source()));
538 } 571 }
539 572
540 void Start() { 573 void Start() {
541 DCHECK(origin_loop_->BelongsToCurrentThread()); 574 DCHECK(origin_loop_->BelongsToCurrentThread());
542 StartLookupAttempt(); 575 StartLookupAttempt();
543 } 576 }
544 577
545 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve 578 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve
546 // attempts running on worker threads will continue running. Only once all the 579 // attempts running on worker threads will continue running. Only once all the
547 // attempts complete will the final reference to this ProcTask be released. 580 // attempts complete will the final reference to this ProcTask be released.
548 void Cancel() { 581 void Cancel() {
549 DCHECK(origin_loop_->BelongsToCurrentThread()); 582 DCHECK(origin_loop_->BelongsToCurrentThread());
550 583
551 if (was_canceled()) 584 if (was_canceled())
552 return; 585 return;
553 586
554 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
555
556 callback_.Reset(); 587 callback_.Reset();
557 588
558 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); 589 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL);
559 } 590 }
560 591
561 void set_had_non_speculative_request() { 592 void set_had_non_speculative_request() {
562 DCHECK(origin_loop_->BelongsToCurrentThread()); 593 DCHECK(origin_loop_->BelongsToCurrentThread());
563 had_non_speculative_request_ = true; 594 had_non_speculative_request_ = true;
564 } 595 }
565 596
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 // WARNING: This code runs inside a worker pool. The shutdown code cannot 645 // WARNING: This code runs inside a worker pool. The shutdown code cannot
615 // wait for it to finish, so we must be very careful here about using other 646 // wait for it to finish, so we must be very careful here about using other
616 // objects (like MessageLoops, Singletons, etc). During shutdown these objects 647 // objects (like MessageLoops, Singletons, etc). During shutdown these objects
617 // may no longer exist. Multiple DoLookups() could be running in parallel, so 648 // may no longer exist. Multiple DoLookups() could be running in parallel, so
618 // any state inside of |this| must not mutate . 649 // any state inside of |this| must not mutate .
619 void DoLookup(const base::TimeTicks& start_time, 650 void DoLookup(const base::TimeTicks& start_time,
620 const uint32 attempt_number) { 651 const uint32 attempt_number) {
621 AddressList results; 652 AddressList results;
622 int os_error = 0; 653 int os_error = 0;
623 // Running on the worker thread 654 // Running on the worker thread
624
625 int error = params_.resolver_proc->Resolve(key_.hostname, 655 int error = params_.resolver_proc->Resolve(key_.hostname,
626 key_.address_family, 656 key_.address_family,
627 key_.host_resolver_flags, 657 key_.host_resolver_flags,
628 &results, 658 &results,
629 &os_error); 659 &os_error);
630 660
631 origin_loop_->PostTask( 661 origin_loop_->PostTask(
632 FROM_HERE, 662 FROM_HERE,
633 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, 663 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time,
634 attempt_number, error, os_error)); 664 attempt_number, error, os_error));
(...skipping 15 matching lines...) Expand all
650 const base::TimeTicks& start_time, 680 const base::TimeTicks& start_time,
651 const uint32 attempt_number, 681 const uint32 attempt_number,
652 int error, 682 int error,
653 const int os_error) { 683 const int os_error) {
654 DCHECK(origin_loop_->BelongsToCurrentThread()); 684 DCHECK(origin_loop_->BelongsToCurrentThread());
655 DCHECK(error || results.head()); 685 DCHECK(error || results.head());
656 686
657 bool was_retry_attempt = attempt_number > 1; 687 bool was_retry_attempt = attempt_number > 1;
658 688
659 // Ideally the following code would be part of host_resolver_proc.cc, 689 // Ideally the following code would be part of host_resolver_proc.cc,
660 // however it isn't safe to call NetworkChangeNotifier from worker 690 // however it isn't safe to call NetworkChangeNotifier from worker threads.
661 // threads. So we do it here on the IO thread instead. 691 // So we do it here on the IO thread instead.
662 if (error != OK && NetworkChangeNotifier::IsOffline()) 692 if (error != OK && NetworkChangeNotifier::IsOffline())
663 error = ERR_INTERNET_DISCONNECTED; 693 error = ERR_INTERNET_DISCONNECTED;
664 694
665 // If this is the first attempt that is finishing later, then record 695 // If this is the first attempt that is finishing later, then record data
666 // data for the first attempt. Won't contaminate with retry attempt's 696 // for the first attempt. Won't contaminate with retry attempt's data.
667 // data.
668 if (!was_retry_attempt) 697 if (!was_retry_attempt)
669 RecordPerformanceHistograms(start_time, error, os_error); 698 RecordPerformanceHistograms(start_time, error, os_error);
670 699
671 RecordAttemptHistograms(start_time, attempt_number, error, os_error); 700 RecordAttemptHistograms(start_time, attempt_number, error, os_error);
672 701
673 if (was_canceled()) 702 if (was_canceled())
674 return; 703 return;
675 704
676 scoped_refptr<NetLog::EventParameters> params; 705 scoped_refptr<NetLog::EventParameters> params;
677 if (error != OK) { 706 if (error != OK) {
678 params = new HostResolveFailedParams(attempt_number, error, os_error); 707 params = new ProcTaskFailedParams(attempt_number, error, os_error);
679 } else { 708 } else {
680 params = new NetLogIntegerParameter("attempt_number", attempt_number); 709 params = new NetLogIntegerParameter("attempt_number", attempt_number);
681 } 710 }
682 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params); 711 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params);
683 712
684 if (was_completed()) 713 if (was_completed())
685 return; 714 return;
686 715
687 // Copy the results from the first worker thread that resolves the host. 716 // Copy the results from the first worker thread that resolves the host.
688 results_ = results; 717 results_ = results;
689 completed_attempt_number_ = attempt_number; 718 completed_attempt_number_ = attempt_number;
690 completed_attempt_error_ = error; 719 completed_attempt_error_ = error;
691 720
692 if (was_retry_attempt) { 721 if (was_retry_attempt) {
693 // If retry attempt finishes before 1st attempt, then get stats on how 722 // If retry attempt finishes before 1st attempt, then get stats on how
694 // much time is saved by having spawned an extra attempt. 723 // much time is saved by having spawned an extra attempt.
695 retry_attempt_finished_time_ = base::TimeTicks::Now(); 724 retry_attempt_finished_time_ = base::TimeTicks::Now();
696 } 725 }
697 726
698 if (error != OK) { 727 if (error != OK) {
699 params = new HostResolveFailedParams(0, error, os_error); 728 params = new ProcTaskFailedParams(0, error, os_error);
700 } else { 729 } else {
701 params = new AddressListNetLogParam(results_); 730 params = new AddressListNetLogParam(results_);
702 } 731 }
703 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); 732 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params);
704 733
705 callback_.Run(error, os_error, results_); 734 callback_.Run(error, results_);
706 } 735 }
707 736
708 void RecordPerformanceHistograms(const base::TimeTicks& start_time, 737 void RecordPerformanceHistograms(const base::TimeTicks& start_time,
709 const int error, 738 const int error,
710 const int os_error) const { 739 const int os_error) const {
711 DCHECK(origin_loop_->BelongsToCurrentThread()); 740 DCHECK(origin_loop_->BelongsToCurrentThread());
712 enum Category { // Used in HISTOGRAM_ENUMERATION. 741 enum Category { // Used in HISTOGRAM_ENUMERATION.
713 RESOLVE_SUCCESS, 742 RESOLVE_SUCCESS,
714 RESOLVE_FAIL, 743 RESOLVE_FAIL,
715 RESOLVE_SPECULATIVE_SUCCESS, 744 RESOLVE_SPECULATIVE_SUCCESS,
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 AddressList results_; 913 AddressList results_;
885 914
886 BoundNetLog net_log_; 915 BoundNetLog net_log_;
887 916
888 DISALLOW_COPY_AND_ASSIGN(ProcTask); 917 DISALLOW_COPY_AND_ASSIGN(ProcTask);
889 }; 918 };
890 919
891 //----------------------------------------------------------------------------- 920 //-----------------------------------------------------------------------------
892 921
893 // Represents a request to the worker pool for a "probe for IPv6 support" call. 922 // Represents a request to the worker pool for a "probe for IPv6 support" call.
923 //
924 // TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks.
894 class HostResolverImpl::IPv6ProbeJob 925 class HostResolverImpl::IPv6ProbeJob
895 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { 926 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> {
896 public: 927 public:
897 explicit IPv6ProbeJob(HostResolverImpl* resolver) 928 explicit IPv6ProbeJob(HostResolverImpl* resolver)
898 : resolver_(resolver), 929 : resolver_(resolver),
899 origin_loop_(base::MessageLoopProxy::current()) { 930 origin_loop_(base::MessageLoopProxy::current()) {
900 DCHECK(resolver); 931 DCHECK(resolver);
901 } 932 }
902 933
903 void Start() { 934 void Start() {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 HostResolverImpl* resolver_; 982 HostResolverImpl* resolver_;
952 983
953 // Used to post ourselves onto the origin thread. 984 // Used to post ourselves onto the origin thread.
954 scoped_refptr<base::MessageLoopProxy> origin_loop_; 985 scoped_refptr<base::MessageLoopProxy> origin_loop_;
955 986
956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); 987 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob);
957 }; 988 };
958 989
959 //----------------------------------------------------------------------------- 990 //-----------------------------------------------------------------------------
960 991
992 // Resolves the hostname using DnsTransaction.
993 // TODO(szym): This could be moved to separate source file as well.
994 class HostResolverImpl::DnsTask {
995 public:
996 typedef base::Callback<void(int net_error,
997 const AddressList& addr_list,
998 base::TimeDelta ttl)> Callback;
999
1000 DnsTask(DnsTransactionFactory* factory,
1001 const Key& key,
1002 const Callback& callback,
1003 const BoundNetLog& job_net_log)
1004 : callback_(callback), net_log_(job_net_log) {
1005 DCHECK(factory);
1006 DCHECK(!callback.is_null());
1007
1008 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4.
1009 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6)
1010 ? dns_protocol::kTypeAAAA
1011 : dns_protocol::kTypeA;
1012 // TODO(szym): Implement "happy eyeballs".
1013 transaction_ = factory->CreateTransaction(
1014 key.hostname,
1015 qtype,
1016 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)),
1017 net_log_);
1018 DCHECK(transaction_.get());
1019 }
1020
1021 int Start() {
1022 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, NULL);
1023 return transaction_->Start();
1024 }
1025
1026 void OnTransactionComplete(DnsTransaction* transaction,
1027 int net_error,
1028 const DnsResponse* response) {
1029 // TODO(szym): Record performance histograms.
1030 // Run |callback_| last since the owning Job will then delete this DnsTask.
1031 DnsResponse::Result result = DnsResponse::DNS_SUCCESS;
1032 if (net_error == OK) {
1033 AddressList addr_list;
1034 base::TimeDelta ttl;
1035 result = response->ParseToAddressList(&addr_list, &ttl);
1036 if (result == DnsResponse::DNS_SUCCESS) {
1037 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1038 new AddressListNetLogParam(addr_list));
1039 callback_.Run(net_error, addr_list, ttl);
1040 return;
1041 }
1042 net_error = ERR_DNS_MALFORMED_RESPONSE;
1043 }
1044 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1045 new DnsTaskFailedParams(net_error, result));
1046 callback_.Run(net_error, AddressList(), base::TimeDelta());
1047 }
1048
1049 private:
1050 // The listener to the results of this DnsTask.
1051 Callback callback_;
1052
1053 const BoundNetLog net_log_;
1054
1055 scoped_ptr<DnsTransaction> transaction_;
1056 };
1057
1058 //-----------------------------------------------------------------------------
1059
961 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. 1060 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch.
962 // Spawns ProcTask when started.
963 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { 1061 class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
964 public: 1062 public:
965 // Creates new job for |key| where |request_net_log| is bound to the 1063 // Creates new job for |key| where |request_net_log| is bound to the
966 // request that spawned it. 1064 // request that spawned it and |priority| is the initial priority.
967 Job(HostResolverImpl* resolver, 1065 Job(HostResolverImpl* resolver,
968 const Key& key, 1066 const Key& key,
969 const BoundNetLog& request_net_log) 1067 const BoundNetLog& request_net_log,
1068 RequestPriority priority)
970 : resolver_(resolver->AsWeakPtr()), 1069 : resolver_(resolver->AsWeakPtr()),
971 key_(key), 1070 key_(key),
1071 priority_tracker_(priority),
972 had_non_speculative_request_(false), 1072 had_non_speculative_request_(false),
973 net_log_(BoundNetLog::Make(request_net_log.net_log(), 1073 net_log_(BoundNetLog::Make(request_net_log.net_log(),
974 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), 1074 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) {
975 net_error_(ERR_IO_PENDING),
976 os_error_(0) {
977 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); 1075 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL);
978 1076
979 net_log_.BeginEvent( 1077 net_log_.BeginEvent(
980 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
981 make_scoped_refptr(new JobCreationParameters( 1079 make_scoped_refptr(new JobCreationParameters(
982 key_.hostname, request_net_log.source()))); 1080 key_.hostname, request_net_log.source())));
1081
1082 handle_ = resolver_->dispatcher_.Add(this, priority);
983 } 1083 }
984 1084
985 virtual ~Job() { 1085 virtual ~Job() {
986 if (net_error_ == ERR_IO_PENDING) { 1086 if (is_running()) {
987 if (is_running()) { 1087 // |resolver_| was destroyed with this Job still in flight.
988 DCHECK_EQ(ERR_IO_PENDING, net_error_); 1088 // Clean-up, record in the log, but don't run any callbacks.
1089 if (is_proc_running()) {
989 proc_task_->Cancel(); 1090 proc_task_->Cancel();
990 proc_task_ = NULL; 1091 proc_task_ = NULL;
991 net_error_ = ERR_ABORTED;
992 } else {
993 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
994 net_error_ = OK; // For NetLog.
995 } 1092 }
1093 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
1094 ERR_ABORTED);
1095 } else if (is_queued()) {
1096 // This Job was cancelled without running.
1097 // TODO(szym): is there's any benefit in having this distinction?
mmenke 2012/02/21 16:34:24 I'd say no, but think it's fine as-is for now.
1098 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
1099 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL);
1100 }
1101 // else CompleteRequests logged EndEvent.
996 1102
997 for (RequestsList::const_iterator it = requests_.begin(); 1103 // Log any remaining Requests as cancelled.
998 it != requests_.end(); ++it) { 1104 for (RequestsList::const_iterator it = requests_.begin();
999 Request* req = *it; 1105 it != requests_.end(); ++it) {
1000 if (req->was_canceled()) 1106 Request* req = *it;
1001 continue; 1107 if (req->was_canceled())
1002 DCHECK_EQ(this, req->job()); 1108 continue;
1003 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1109 DCHECK_EQ(this, req->job());
1004 req->info()); 1110 LogCancelRequest(req->source_net_log(), req->request_net_log(),
1005 } 1111 req->info());
1006 } 1112 }
1007 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
1008 net_error_);
1009 STLDeleteElements(&requests_); 1113 STLDeleteElements(&requests_);
1010 } 1114 }
1011 1115
1012 HostResolverImpl* resolver() const {
1013 return resolver_;
1014 }
1015
1016 RequestPriority priority() const { 1116 RequestPriority priority() const {
1017 return priority_tracker_.highest_priority(); 1117 return priority_tracker_.highest_priority();
1018 } 1118 }
1019 1119
1020 // Number of non-canceled requests in |requests_|. 1120 // Number of non-canceled requests in |requests_|.
1021 size_t num_active_requests() const { 1121 size_t num_active_requests() const {
1022 return priority_tracker_.total_count(); 1122 return priority_tracker_.total_count();
1023 } 1123 }
1024 1124
1025 const Key& key() const { 1125 const Key& key() const {
1026 return key_; 1126 return key_;
1027 } 1127 }
1028 1128
1029 int net_error() const { 1129 bool is_queued() const {
1030 return net_error_; 1130 return !handle_.is_null();
1031 } 1131 }
1032 1132
1033 // Used by HostResolverImpl with |dispatcher_|. 1133 void AddRequest(scoped_ptr<Request> req) {
1034 const PrioritizedDispatcher::Handle& handle() const {
1035 return handle_;
1036 }
1037
1038 void set_handle(const PrioritizedDispatcher::Handle& handle) {
1039 handle_ = handle;
1040 }
1041
1042 // The Job will own |req| and destroy it in ~Job.
1043 void AddRequest(Request* req) {
1044 DCHECK_EQ(key_.hostname, req->info().hostname()); 1134 DCHECK_EQ(key_.hostname, req->info().hostname());
1045 1135
1046 req->set_job(this); 1136 req->set_job(this);
1047 requests_.push_back(req);
1048
1049 priority_tracker_.Add(req->info().priority()); 1137 priority_tracker_.Add(req->info().priority());
1050 1138
1051 req->request_net_log().AddEvent( 1139 req->request_net_log().AddEvent(
1052 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, 1140 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH,
1053 make_scoped_refptr(new NetLogSourceParameter( 1141 make_scoped_refptr(new NetLogSourceParameter(
1054 "source_dependency", net_log_.source()))); 1142 "source_dependency", net_log_.source())));
1055 1143
1056 net_log_.AddEvent( 1144 net_log_.AddEvent(
1057 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, 1145 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH,
1058 make_scoped_refptr(new JobAttachParameters( 1146 make_scoped_refptr(new JobAttachParameters(
1059 req->request_net_log().source(), priority()))); 1147 req->request_net_log().source(), priority())));
1060 1148
1061 // TODO(szym): Check if this is still needed. 1149 // TODO(szym): Check if this is still needed.
1062 if (!req->info().is_speculative()) { 1150 if (!req->info().is_speculative()) {
1063 had_non_speculative_request_ = true; 1151 had_non_speculative_request_ = true;
1064 if (proc_task_) 1152 if (proc_task_)
1065 proc_task_->set_had_non_speculative_request(); 1153 proc_task_->set_had_non_speculative_request();
1066 } 1154 }
1155
1156 requests_.push_back(req.release());
1157
1158 if (!handle_.is_null())
1159 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority());
1067 } 1160 }
1068 1161
1069 void CancelRequest(Request* req) { 1162 void CancelRequest(Request* req) {
1070 DCHECK_EQ(key_.hostname, req->info().hostname()); 1163 DCHECK_EQ(key_.hostname, req->info().hostname());
1071 DCHECK(!req->was_canceled()); 1164 DCHECK(!req->was_canceled());
1072 // Don't remove it from |requests_| just mark it canceled. 1165 // Don't remove it from |requests_| just mark it canceled.
1073 req->MarkAsCanceled(); 1166 req->MarkAsCanceled();
1074 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1167 LogCancelRequest(req->source_net_log(), req->request_net_log(),
1075 req->info()); 1168 req->info());
1076 priority_tracker_.Remove(req->info().priority()); 1169 priority_tracker_.Remove(req->info().priority());
1077 net_log_.AddEvent( 1170 net_log_.AddEvent(
1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, 1171 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH,
1079 make_scoped_refptr(new JobAttachParameters( 1172 make_scoped_refptr(new JobAttachParameters(
1080 req->request_net_log().source(), priority()))); 1173 req->request_net_log().source(), priority())));
1174
1175 if (!handle_.is_null()) {
1176 if (num_active_requests() > 0) {
1177 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority());
1178 } else {
1179 resolver_->dispatcher_.Cancel(handle_);
1180 handle_.Reset();
1181 }
1182 }
1081 } 1183 }
1082 1184
1083 // Aborts and destroys the job, completes all requests as aborted. 1185 // Aborts and destroys the job, completes all requests as aborted.
1186 // The caller should clean up.
1084 void Abort() { 1187 void Abort() {
1085 // Job should only be aborted if it's running. 1188 // Job should only be aborted if it's running.
1086 DCHECK(is_running()); 1189 DCHECK(is_running());
1087 proc_task_->Cancel(); 1190 if (is_proc_running()) {
1088 proc_task_ = NULL; 1191 proc_task_->Cancel();
1089 net_error_ = ERR_ABORTED; 1192 proc_task_ = NULL;
1090 os_error_ = 0; 1193 }
1091 CompleteRequests(AddressList()); 1194 dns_task_.reset();
1195 CompleteRequests(ERR_ABORTED, AddressList(), base::TimeDelta());
1196 }
1197
1198 bool is_dns_running() const {
1199 return dns_task_.get() != NULL;
1200 }
1201
1202 bool is_proc_running() const {
1203 return proc_task_.get() != NULL;
1092 } 1204 }
1093 1205
1094 bool is_running() const { 1206 bool is_running() const {
1095 return proc_task_.get() != NULL; 1207 return is_dns_running() || is_proc_running();
1096 } 1208 }
1097 1209
1098 // Called by HostResolverImpl when this job is evicted due to queue overflow. 1210 // Called by HostResolverImpl when this job is evicted due to queue overflow.
1099 void OnEvicted() { 1211 void OnEvicted() {
1100 // Must not be running. 1212 // Must not be running.
1101 DCHECK(!is_running()); 1213 DCHECK(!is_running());
1102 handle_ = PrioritizedDispatcher::Handle(); 1214 handle_.Reset();
1103 1215
1104 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); 1216 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL);
1105 1217
1218 scoped_ptr<Job> self_deleter(this);
1219 resolver_->RemoveJob(this);
1220
1106 // This signals to CompleteRequests that this job never ran. 1221 // This signals to CompleteRequests that this job never ran.
1107 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 1222 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE,
1108 os_error_ = 0; 1223 AddressList(),
1109 CompleteRequests(AddressList()); 1224 base::TimeDelta());
1110 } 1225 }
1111 1226
1112 // PriorityDispatch::Job interface. 1227 // PriorityDispatch::Job interface.
1113 virtual void Start() OVERRIDE { 1228 virtual void Start() OVERRIDE {
1114 DCHECK(!is_running()); 1229 DCHECK(!is_running());
1115 handle_ = PrioritizedDispatcher::Handle(); 1230 handle_.Reset();
1116 1231
1117 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); 1232 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL);
1118 1233
1234 if (resolver_->dns_transaction_factory_.get()) {
1235 StartDnsTask();
1236 } else {
1237 StartProcTask();
1238 }
1239 }
1240
1241 private:
1242 // TODO(szym): Since DnsTransaction does not consume threads, we can increase
1243 // the limits on |dispatcher_|. But in order to keep the number of WorkerPool
1244 // threads low, we will need to use an "inner" PrioritizedDispatcher with
1245 // tighter limits.
1246 void StartProcTask() {
1247 DCHECK(!dns_task_.get());
1119 proc_task_ = new ProcTask( 1248 proc_task_ = new ProcTask(
1120 key_, 1249 key_,
1121 resolver_->proc_params_, 1250 resolver_->proc_params_,
1122 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), 1251 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)),
1123 net_log_); 1252 net_log_);
1124 1253
1125 if (had_non_speculative_request_) 1254 if (had_non_speculative_request_)
1126 proc_task_->set_had_non_speculative_request(); 1255 proc_task_->set_had_non_speculative_request();
1127 // Start() could be called from within Resolve(), hence it must NOT directly 1256 // Start() could be called from within Resolve(), hence it must NOT directly
1128 // call OnProcTaskComplete, for example, on synchronous failure. 1257 // call OnProcTaskComplete, for example, on synchronous failure.
1129 proc_task_->Start(); 1258 proc_task_->Start();
1130 } 1259 }
1131 1260
1132 private:
1133 // Called by ProcTask when it completes. 1261 // Called by ProcTask when it completes.
1134 void OnProcTaskComplete(int net_error, int os_error, 1262 void OnProcTaskComplete(int net_error, const AddressList& addr_list) {
1135 const AddressList& addrlist) { 1263 DCHECK(is_proc_running());
1136 DCHECK(is_running()); 1264 // |addr_list| will be destroyed once we destroy |proc_task_|.
1265 AddressList list = addr_list;
1137 proc_task_ = NULL; 1266 proc_task_ = NULL;
1138 net_error_ = net_error;
1139 os_error_ = os_error;
1140 1267
1141 // We are the only consumer of |addrlist|, so we can safely change the port 1268 base::TimeDelta ttl = base::TimeDelta::FromSeconds(
1142 // without copy-on-write. This pays off, when job has only one request. 1269 kNegativeCacheEntryTTLSeconds);
1143 AddressList list = addrlist; 1270 if (net_error == OK)
1144 if (net_error == OK && !requests_.empty()) 1271 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
1145 MutableSetPort(requests_.front()->info().port(), &list);
1146 CompleteRequests(list);
1147 }
1148
1149 // Completes all Requests. Calls OnJobFinished and deletes self.
1150 void CompleteRequests(const AddressList& addrlist) {
1151 CHECK(resolver_);
1152 1272
1153 // This job must be removed from resolver's |jobs_| now to make room for a 1273 // This job must be removed from resolver's |jobs_| now to make room for a
1154 // new job with the same key in case one of the OnComplete callbacks decides 1274 // new job with the same key in case one of the OnComplete callbacks decides
1155 // to spawn one. Consequently, the job deletes itself when CompleteRequests 1275 // to spawn one. Consequently, the job deletes itself when CompleteRequests
1156 // is done. 1276 // is done.
1157 scoped_ptr<Job> self_deleter(this); 1277 scoped_ptr<Job> self_deleter(this);
1158 resolver_->OnJobFinished(this, addrlist); 1278 resolver_->OnJobFinished(this, net_error, list, ttl);
1279
1280 CompleteRequests(net_error, list, ttl);
1281 }
1282
1283 void StartDnsTask() {
1284 dns_task_.reset(new DnsTask(
1285 resolver_->dns_transaction_factory_.get(),
1286 key_,
1287 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)),
1288 net_log_));
1289
1290 int rv = dns_task_->Start();
1291 if (rv != ERR_IO_PENDING) {
1292 DCHECK_NE(OK, rv);
1293 dns_task_.reset();
1294 StartProcTask();
1295 }
1296 }
1297
1298 // Called by DnsTask when it completes.
1299 void OnDnsTaskComplete(int net_error,
1300 const AddressList& addr_list,
1301 base::TimeDelta ttl) {
1302 DCHECK(is_dns_running());
1303 // |addr_list| will be destroyed once we destroy |dns_task_|.
1304 AddressList list = addr_list;
1305 dns_task_.reset();
1306
1307 if (net_error != OK) {
1308 // TODO(szym): Some net errors indicate lack of connectivity. Starting
1309 // ProcTask in that case is a waste of time.
1310 StartProcTask();
1311 return;
1312 }
1313
1314 // As in OnProcTaskComplete
1315 scoped_ptr<Job> self_deleter(this);
1316 resolver_->OnJobFinished(this, net_error, list, ttl);
1317
1318 CompleteRequests(net_error, list, ttl);
1319 }
1320
1321 // Completes all Requests. Calls OnJobFinished and deletes self.
1322 void CompleteRequests(int net_error,
1323 const AddressList& addr_list,
1324 base::TimeDelta ttl) {
1325 CHECK(resolver_);
1326 DCHECK(!is_running());
1327 DCHECK(!is_queued());
1328
1329 // We are the only consumer of |addr_list|, so we can safely change the port
1330 // without copy-on-write. This pays off, when job has only one request.
1331 AddressList list = addr_list;
1332 if (net_error == OK && !requests_.empty())
1333 MutableSetPort(requests_.front()->info().port(), &list);
1334
1335 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
1336 net_error);
1159 1337
1160 // Complete all of the requests that were attached to the job. 1338 // Complete all of the requests that were attached to the job.
1161 for (RequestsList::const_iterator it = requests_.begin(); 1339 for (RequestsList::const_iterator it = requests_.begin();
1162 it != requests_.end(); ++it) { 1340 it != requests_.end(); ++it) {
1163 Request* req = *it; 1341 Request* req = *it;
1164 1342
1165 if (req->was_canceled()) 1343 if (req->was_canceled())
1166 continue; 1344 continue;
1167 1345
1168 DCHECK_EQ(this, req->job()); 1346 DCHECK_EQ(this, req->job());
1169 // Update the net log and notify registered observers. 1347 // Update the net log and notify registered observers.
1170 LogFinishRequest(req->source_net_log(), req->request_net_log(), 1348 LogFinishRequest(req->source_net_log(), req->request_net_log(),
1171 req->info(), net_error_, os_error_); 1349 req->info(), net_error);
1172 1350
1173 req->OnComplete(net_error_, addrlist); 1351 req->OnComplete(net_error, list);
1174 1352
1175 // Check if the resolver was destroyed as a result of running the 1353 // Check if the resolver was destroyed as a result of running the
1176 // callback. If it was, we could continue, but we choose to bail. 1354 // callback. If it was, we could continue, but we choose to bail.
1177 if (!resolver_) 1355 if (!resolver_)
1178 return; 1356 return;
1179 } 1357 }
1180 } 1358 }
1181 1359
1182 // Used to call OnJobFinished and RemoveJob. 1360 // Used to call OnJobFinished.
1183 base::WeakPtr<HostResolverImpl> resolver_; 1361 base::WeakPtr<HostResolverImpl> resolver_;
1184 1362
1185 Key key_; 1363 Key key_;
1186 1364
1187 // Tracks the highest priority across |requests_|. 1365 // Tracks the highest priority across |requests_|.
1188 PriorityTracker priority_tracker_; 1366 PriorityTracker priority_tracker_;
1189 1367
1190 bool had_non_speculative_request_; 1368 bool had_non_speculative_request_;
1191 1369
1192 BoundNetLog net_log_; 1370 BoundNetLog net_log_;
1193 1371
1194 // Store result here in case the job fails fast in Resolve(). 1372 // Resolves the host using a HostResolverProc.
1195 int net_error_; 1373 scoped_refptr<ProcTask> proc_task_;
1196 int os_error_;
1197 1374
1198 // A ProcTask created and started when this Job is dispatched.. 1375 // Resolves the host using a DnsTransaction.
1199 scoped_refptr<ProcTask> proc_task_; 1376 scoped_ptr<DnsTask> dns_task_;
1200 1377
1201 // All Requests waiting for the result of this Job. Some can be canceled. 1378 // All Requests waiting for the result of this Job. Some can be canceled.
1202 RequestsList requests_; 1379 RequestsList requests_;
1203 1380
1204 // A handle used by HostResolverImpl in |dispatcher_|. 1381 // A handle used |HostResolverImpl::dispatcher_|.
cbentzel 2012/02/21 18:41:59 Nit: used by
1205 PrioritizedDispatcher::Handle handle_; 1382 PrioritizedDispatcher::Handle handle_;
1206 }; 1383 };
1207 1384
1208 //----------------------------------------------------------------------------- 1385 //-----------------------------------------------------------------------------
1209 1386
1210 HostResolverImpl::ProcTaskParams::ProcTaskParams( 1387 HostResolverImpl::ProcTaskParams::ProcTaskParams(
1211 HostResolverProc* resolver_proc, 1388 HostResolverProc* resolver_proc,
1212 size_t max_retry_attempts) 1389 size_t max_retry_attempts)
1213 : resolver_proc(resolver_proc), 1390 : resolver_proc(resolver_proc),
1214 max_retry_attempts(max_retry_attempts), 1391 max_retry_attempts(max_retry_attempts),
1215 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), 1392 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)),
1216 retry_factor(2) { 1393 retry_factor(2) {
1217 } 1394 }
1218 1395
1219 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} 1396 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {}
1220 1397
1221 HostResolverImpl::HostResolverImpl( 1398 HostResolverImpl::HostResolverImpl(
1222 HostCache* cache, 1399 HostCache* cache,
1223 const PrioritizedDispatcher::Limits& job_limits, 1400 const PrioritizedDispatcher::Limits& job_limits,
1224 const ProcTaskParams& proc_params, 1401 const ProcTaskParams& proc_params,
1402 scoped_ptr<DnsConfigService> dns_config_service,
1225 NetLog* net_log) 1403 NetLog* net_log)
1226 : cache_(cache), 1404 : cache_(cache),
1227 dispatcher_(job_limits), 1405 dispatcher_(job_limits),
1228 max_queued_jobs_(job_limits.total_jobs * 100u), 1406 max_queued_jobs_(job_limits.total_jobs * 100u),
1229 proc_params_(proc_params), 1407 proc_params_(proc_params),
1230 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), 1408 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
1409 dns_config_service_(dns_config_service.Pass()),
1231 ipv6_probe_monitoring_(false), 1410 ipv6_probe_monitoring_(false),
1232 additional_resolver_flags_(0), 1411 additional_resolver_flags_(0),
1233 net_log_(net_log) { 1412 net_log_(net_log) {
1234 1413
1235 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); 1414 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES));
1236 1415
1237 // Maximum of 4 retry attempts for host resolution. 1416 // Maximum of 4 retry attempts for host resolution.
1238 static const size_t kDefaultMaxRetryAttempts = 4u; 1417 static const size_t kDefaultMaxRetryAttempts = 4u;
1239 1418
1240 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) 1419 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts)
1241 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; 1420 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts;
1242 1421
1243 #if defined(OS_WIN) 1422 #if defined(OS_WIN)
1244 EnsureWinsockInit(); 1423 EnsureWinsockInit();
1245 #endif 1424 #endif
1246 #if defined(OS_POSIX) && !defined(OS_MACOSX) 1425 #if defined(OS_POSIX) && !defined(OS_MACOSX)
1247 if (HaveOnlyLoopbackAddresses()) 1426 if (HaveOnlyLoopbackAddresses())
1248 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; 1427 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
1249 #endif 1428 #endif
1250 NetworkChangeNotifier::AddIPAddressObserver(this); 1429 NetworkChangeNotifier::AddIPAddressObserver(this);
1251 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) 1430 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
1252 #if !defined(OS_ANDROID) 1431 #if !defined(OS_ANDROID)
1253 EnsureDnsReloaderInit(); 1432 EnsureDnsReloaderInit();
1254 #endif 1433 #endif
1255 NetworkChangeNotifier::AddDNSObserver(this); 1434 NetworkChangeNotifier::AddDNSObserver(this);
1256 #endif 1435 #endif
1436
1437 if (dns_config_service_.get())
1438 dns_config_service_->AddObserver(this);
1257 } 1439 }
1258 1440
1259 HostResolverImpl::~HostResolverImpl() { 1441 HostResolverImpl::~HostResolverImpl() {
1260 DiscardIPv6ProbeJob(); 1442 DiscardIPv6ProbeJob();
1261 1443
1262 // This will also cancel all outstanding requests. 1444 // This will also cancel all outstanding requests.
1263 STLDeleteValues(&jobs_); 1445 STLDeleteValues(&jobs_);
1264 1446
1265 NetworkChangeNotifier::RemoveIPAddressObserver(this); 1447 NetworkChangeNotifier::RemoveIPAddressObserver(this);
1266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) 1448 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
(...skipping 21 matching lines...) Expand all
1288 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); 1470 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST);
1289 1471
1290 LogStartRequest(source_net_log, request_net_log, info); 1472 LogStartRequest(source_net_log, request_net_log, info);
1291 1473
1292 // Build a key that identifies the request in the cache and in the 1474 // Build a key that identifies the request in the cache and in the
1293 // outstanding jobs map. 1475 // outstanding jobs map.
1294 Key key = GetEffectiveKeyForRequest(info); 1476 Key key = GetEffectiveKeyForRequest(info);
1295 1477
1296 int rv = ResolveHelper(key, info, addresses, request_net_log); 1478 int rv = ResolveHelper(key, info, addresses, request_net_log);
1297 if (rv != ERR_DNS_CACHE_MISS) { 1479 if (rv != ERR_DNS_CACHE_MISS) {
1298 LogFinishRequest(source_net_log, request_net_log, info, rv, 1480 LogFinishRequest(source_net_log, request_net_log, info, rv);
1299 0 /* os_error (unknown since from cache) */);
1300 return rv; 1481 return rv;
1301 } 1482 }
1302 1483
1303 // Next we need to attach our request to a "job". This job is responsible for 1484 // Next we need to attach our request to a "job". This job is responsible for
1304 // calling "getaddrinfo(hostname)" on a worker thread. 1485 // calling "getaddrinfo(hostname)" on a worker thread.
1305 1486
1306 JobMap::iterator jobit = jobs_.find(key); 1487 JobMap::iterator jobit = jobs_.find(key);
1307 Job* job; 1488 Job* job;
1308 if (jobit == jobs_.end()) { 1489 if (jobit == jobs_.end()) {
1309 // Create new Job. 1490 // Create new Job.
1310 job = new Job(this, key, request_net_log); 1491 job = new Job(this, key, request_net_log, info.priority());
1311 job->set_handle(dispatcher_.Add(job, info.priority()));
1312 1492
1313 // Check for queue overflow. 1493 // Check for queue overflow.
1314 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { 1494 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) {
1315 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); 1495 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest());
1316 DCHECK(evicted); 1496 DCHECK(evicted);
1317 if (evicted == job) { 1497 if (evicted == job) {
1318 delete job; 1498 delete job;
1319 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 1499 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
1320 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); 1500 LogFinishRequest(source_net_log, request_net_log, info, rv);
1321 return rv; 1501 return rv;
1322 } 1502 }
1323 evicted->OnEvicted(); // Deletes |evicted|. 1503 evicted->OnEvicted(); // Deletes |evicted|.
1324 } 1504 }
1325
1326 jobs_.insert(jobit, std::make_pair(key, job)); 1505 jobs_.insert(jobit, std::make_pair(key, job));
1327 } else { 1506 } else {
1328 job = jobit->second; 1507 job = jobit->second;
1329 } 1508 }
1330 1509
1331 // Can't complete synchronously. Create and attach request. 1510 // Can't complete synchronously. Create and attach request.
1332 Request* req = new Request(source_net_log, request_net_log, info, callback, 1511 scoped_ptr<Request> req(new Request(source_net_log,
1333 addresses); 1512 request_net_log,
1334 job->AddRequest(req); 1513 info,
1335 if (!job->handle().is_null()) 1514 callback,
1336 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); 1515 addresses));
1337 if (out_req) 1516 if (out_req)
1338 *out_req = reinterpret_cast<RequestHandle>(req); 1517 *out_req = reinterpret_cast<RequestHandle>(req.get());
1339 1518
1340 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); 1519 job->AddRequest(req.Pass());
1341 // Completion happens during Job::CompleteRequests(). 1520 // Completion happens during Job::CompleteRequests().
1342 return ERR_IO_PENDING; 1521 return ERR_IO_PENDING;
1343 } 1522 }
1344 1523
1345 int HostResolverImpl::ResolveHelper(const Key& key, 1524 int HostResolverImpl::ResolveHelper(const Key& key,
1346 const RequestInfo& info, 1525 const RequestInfo& info,
1347 AddressList* addresses, 1526 AddressList* addresses,
1348 const BoundNetLog& request_net_log) { 1527 const BoundNetLog& request_net_log) {
1349 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. 1528 // The result of |getaddrinfo| for empty hosts is inconsistent across systems.
1350 // On Windows it gives the default interface's address, whereas on Linux it 1529 // On Windows it gives the default interface's address, whereas on Linux it
(...skipping 18 matching lines...) Expand all
1369 // Make a log item for the request. 1548 // Make a log item for the request.
1370 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 1549 BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
1371 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); 1550 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST);
1372 1551
1373 // Update the net log and notify registered observers. 1552 // Update the net log and notify registered observers.
1374 LogStartRequest(source_net_log, request_net_log, info); 1553 LogStartRequest(source_net_log, request_net_log, info);
1375 1554
1376 Key key = GetEffectiveKeyForRequest(info); 1555 Key key = GetEffectiveKeyForRequest(info);
1377 1556
1378 int rv = ResolveHelper(key, info, addresses, request_net_log); 1557 int rv = ResolveHelper(key, info, addresses, request_net_log);
1379 LogFinishRequest(source_net_log, request_net_log, info, rv, 1558 LogFinishRequest(source_net_log, request_net_log, info, rv);
1380 0 /* os_error (unknown since from cache) */);
1381 return rv; 1559 return rv;
1382 } 1560 }
1383 1561
1384 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { 1562 void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
1385 DCHECK(CalledOnValidThread()); 1563 DCHECK(CalledOnValidThread());
1386 Request* req = reinterpret_cast<Request*>(req_handle); 1564 Request* req = reinterpret_cast<Request*>(req_handle);
1387 DCHECK(req); 1565 DCHECK(req);
1388 1566
1389 Job* job = req->job(); 1567 Job* job = req->job();
1390 DCHECK(job); 1568 DCHECK(job);
1391 1569
1392 job->CancelRequest(req); 1570 job->CancelRequest(req);
1393 1571
1394 if (!job->handle().is_null()) { 1572 if (job->num_active_requests() == 0) {
1395 // Still in queue. 1573 RemoveJob(job);
1396 if (job->num_active_requests()) { 1574 if (job->is_running()) {
1397 job->set_handle(dispatcher_.ChangePriority(job->handle(), 1575 // If we were called from a Requests's callback within
1398 job->priority())); 1576 // Job::CompleteRequests, that Request could not have been cancelled, so
1399 } else { 1577 // job->num_active_requests() could not be 0. Therefore, we are not in
1400 dispatcher_.Cancel(job->handle()); 1578 // Job::CompleteRequests().
mmenke 2012/02/21 16:34:24 nit: Might want to move this comment up to "if (j
1401 RemoveJob(job);
1402 delete job;
1403 }
1404 } else {
1405 // Job is running (and could be in CompleteRequests right now).
1406 // But to be in Request::OnComplete we would have to have a non-canceled
1407 // request. So it is safe to Abort it if it has no more active requests.
1408 if (!job->num_active_requests()) {
1409 job->Abort(); 1579 job->Abort();
1410 } 1580 }
1581 delete job;
1411 } 1582 }
1412 } 1583 }
1413 1584
1414 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { 1585 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
1415 DCHECK(CalledOnValidThread()); 1586 DCHECK(CalledOnValidThread());
1416 ipv6_probe_monitoring_ = false; 1587 ipv6_probe_monitoring_ = false;
1417 DiscardIPv6ProbeJob(); 1588 DiscardIPv6ProbeJob();
1418 default_address_family_ = address_family; 1589 default_address_family_ = address_family;
1419 } 1590 }
1420 1591
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 if (!cache_entry) 1646 if (!cache_entry)
1476 return false; 1647 return false;
1477 1648
1478 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); 1649 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL);
1479 *net_error = cache_entry->error; 1650 *net_error = cache_entry->error;
1480 if (*net_error == OK) 1651 if (*net_error == OK)
1481 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); 1652 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port());
1482 return true; 1653 return true;
1483 } 1654 }
1484 1655
1485 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { 1656 void HostResolverImpl::OnJobFinished(Job* job,
1657 int net_error,
1658 const AddressList& addr_list,
1659 base::TimeDelta ttl) {
1486 DCHECK(job); 1660 DCHECK(job);
1487 DCHECK(job->handle().is_null()); 1661 DCHECK(!job->is_queued());
1662 DCHECK_NE(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, net_error);
1663 DCHECK_NE(ERR_ABORTED, net_error);
1664
1488 RemoveJob(job); 1665 RemoveJob(job);
1489 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE)
1490 return;
1491
1492 // Signal dispatcher that a slot has opened. 1666 // Signal dispatcher that a slot has opened.
1493 dispatcher_.OnJobFinished(); 1667 dispatcher_.OnJobFinished();
1494 if (job->net_error() == ERR_ABORTED)
1495 return;
1496 // Write result to the cache. 1668 // Write result to the cache.
1497 if (cache_.get()) { 1669 if (cache_.get()) {
1498 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); 1670 cache_->Set(job->key(), net_error, addr_list,
1499 if (job->net_error() == OK)
1500 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
1501 cache_->Set(job->key(), job->net_error(), addrlist,
1502 base::TimeTicks::Now(), ttl); 1671 base::TimeTicks::Now(), ttl);
1503 } 1672 }
1504 } 1673 }
1505 1674
1506 void HostResolverImpl::RemoveJob(Job* job) { 1675 void HostResolverImpl::RemoveJob(Job* job) {
1507 DCHECK(job); 1676 DCHECK(job);
1508 jobs_.erase(job->key()); 1677 jobs_.erase(job->key());
1509 } 1678 }
1510 1679
1511 void HostResolverImpl::DiscardIPv6ProbeJob() { 1680 void HostResolverImpl::DiscardIPv6ProbeJob() {
(...skipping 26 matching lines...) Expand all
1538 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { 1707 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) {
1539 effective_address_family = default_address_family_; 1708 effective_address_family = default_address_family_;
1540 if (ipv6_probe_monitoring_) 1709 if (ipv6_probe_monitoring_)
1541 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; 1710 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
1542 } 1711 }
1543 return Key(info.hostname(), effective_address_family, effective_flags); 1712 return Key(info.hostname(), effective_address_family, effective_flags);
1544 } 1713 }
1545 1714
1546 void HostResolverImpl::AbortAllInProgressJobs() { 1715 void HostResolverImpl::AbortAllInProgressJobs() {
1547 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); 1716 base::WeakPtr<HostResolverImpl> self = AsWeakPtr();
1548 // Scan |jobs_| for running jobs and abort them. 1717 // In Abort, a Request callback could spawn new Jobs with matching keys, so
1718 // first collect and remove all running jobs from |jobs_|.
1719 std::vector<Job*> jobs_to_abort;
1549 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { 1720 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) {
1550 Job* job = it->second; 1721 Job* job = it->second;
1551 // Advance the iterator before we might erase it.
1552 ++it;
1553 if (job->is_running()) { 1722 if (job->is_running()) {
1554 job->Abort(); 1723 jobs_to_abort.push_back(job);
1555 // Check if resolver was deleted in a request callback. 1724 jobs_.erase(it++);
1556 if (!self)
1557 return;
1558 } else { 1725 } else {
1559 // Keep it in |dispatch_|. 1726 DCHECK(job->is_queued());
1560 DCHECK(!job->handle().is_null()); 1727 ++it;
1561 } 1728 }
1562 } 1729 }
1730
1731 // Then Abort them and dispatch new Jobs.
1732 for (size_t i = 0; i < jobs_to_abort.size(); ++i) {
1733 jobs_to_abort[i]->Abort();
1734 dispatcher_.OnJobFinished();
1735 }
1736 STLDeleteElements(&jobs_to_abort);
1563 } 1737 }
1564 1738
1565 void HostResolverImpl::OnIPAddressChanged() { 1739 void HostResolverImpl::OnIPAddressChanged() {
1566 if (cache_.get()) 1740 if (cache_.get())
1567 cache_->clear(); 1741 cache_->clear();
1568 if (ipv6_probe_monitoring_) { 1742 if (ipv6_probe_monitoring_) {
1569 DiscardIPv6ProbeJob(); 1743 DiscardIPv6ProbeJob();
1570 ipv6_probe_job_ = new IPv6ProbeJob(this); 1744 ipv6_probe_job_ = new IPv6ProbeJob(this);
1571 ipv6_probe_job_->Start(); 1745 ipv6_probe_job_->Start();
1572 } 1746 }
(...skipping 14 matching lines...) Expand all
1587 // as NSCD's cache should be dropped automatically by the OS when 1761 // as NSCD's cache should be dropped automatically by the OS when
1588 // resolv.conf changes so we don't need to do anything to clear that cache. 1762 // resolv.conf changes so we don't need to do anything to clear that cache.
1589 if (cache_.get()) 1763 if (cache_.get())
1590 cache_->clear(); 1764 cache_->clear();
1591 // Existing jobs will have been sent to the original server so they need to 1765 // Existing jobs will have been sent to the original server so they need to
1592 // be aborted. TODO(Craig): Should these jobs be restarted? 1766 // be aborted. TODO(Craig): Should these jobs be restarted?
1593 AbortAllInProgressJobs(); 1767 AbortAllInProgressJobs();
1594 // |this| may be deleted inside AbortAllInProgressJobs(). 1768 // |this| may be deleted inside AbortAllInProgressJobs().
1595 } 1769 }
1596 1770
1771 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) {
1772 // We want a new factory in place, before we Abort running Jobs, so that the
1773 // newly started jobs use the new factory.
1774 bool had_factory = (dns_transaction_factory_.get() != NULL);
1775 if (dns_config.IsValid()) {
1776 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory(
1777 new DnsSession(dns_config,
1778 ClientSocketFactory::GetDefaultFactory(),
1779 base::Bind(&base::RandInt),
1780 net_log_));
1781 } else {
1782 dns_transaction_factory_.reset();
1783 }
1784 if (had_factory) {
1785 OnDNSChanged();
1786 }
1787 }
1788
1597 } // namespace net 1789 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698