Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 316 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 309 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | 317 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); |
| 310 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 318 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
| 311 } | 319 } |
| 312 | 320 |
| 313 //----------------------------------------------------------------------------- | 321 //----------------------------------------------------------------------------- |
| 314 | 322 |
| 315 // Keeps track of the highest priority. | 323 // Keeps track of the highest priority. |
| 316 class PriorityTracker { | 324 class PriorityTracker { |
| 317 public: | 325 public: |
| 318 PriorityTracker() | 326 PriorityTracker(RequestPriority priority) |
|
cbentzel
2012/02/14 13:08:26
explicit
| |
| 319 : highest_priority_(IDLE), total_count_(0) { | 327 : highest_priority_(priority), total_count_(0) { |
|
cbentzel
2012/02/14 13:08:26
This was a little tricky - I expected total_count_
| |
| 320 memset(counts_, 0, sizeof(counts_)); | 328 memset(counts_, 0, sizeof(counts_)); |
| 321 } | 329 } |
| 322 | 330 |
| 323 RequestPriority highest_priority() const { | 331 RequestPriority highest_priority() const { |
| 324 return highest_priority_; | 332 return highest_priority_; |
| 325 } | 333 } |
| 326 | 334 |
| 327 size_t total_count() const { | 335 size_t total_count() const { |
| 328 return total_count_; | 336 return total_count_; |
| 329 } | 337 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 352 } | 360 } |
| 353 | 361 |
| 354 private: | 362 private: |
| 355 RequestPriority highest_priority_; | 363 RequestPriority highest_priority_; |
| 356 size_t total_count_; | 364 size_t total_count_; |
| 357 size_t counts_[NUM_PRIORITIES]; | 365 size_t counts_[NUM_PRIORITIES]; |
| 358 }; | 366 }; |
| 359 | 367 |
| 360 //----------------------------------------------------------------------------- | 368 //----------------------------------------------------------------------------- |
| 361 | 369 |
| 370 // Convenience wrapper for PrioritizedDispatcher::Handle so that we don't forget | |
| 371 // to update it when cancelling or changing the priority. | |
| 372 // TODO(szym): consider making PrioritizedDispatcher::Handle into this. | |
| 373 class DispatcherHandle { | |
| 374 public: | |
| 375 DispatcherHandle() : dispatcher_(NULL) {} | |
| 376 DispatcherHandle(PrioritizedDispatcher* dispatcher, | |
| 377 const PrioritizedDispatcher::Handle& handle) | |
| 378 : dispatcher_(dispatcher), handle_(handle) { | |
| 379 if (handle_.is_null()) | |
| 380 dispatcher_ = NULL; | |
| 381 } | |
| 382 | |
| 383 bool is_null() const { | |
| 384 return dispatcher_ == NULL; | |
| 385 } | |
| 386 | |
| 387 void Reset() { | |
| 388 dispatcher_ = NULL; | |
| 389 handle_ = PrioritizedDispatcher::Handle(); | |
| 390 } | |
| 391 | |
| 392 void ChangePriority(RequestPriority priority) { | |
| 393 DCHECK(!is_null()); | |
| 394 handle_ = dispatcher_->ChangePriority(handle_, priority); | |
| 395 } | |
| 396 | |
| 397 void Cancel() { | |
| 398 DCHECK(!is_null()); | |
| 399 dispatcher_->Cancel(handle_); | |
| 400 Reset(); | |
| 401 } | |
| 402 | |
| 403 private: | |
| 404 PrioritizedDispatcher* dispatcher_; | |
| 405 PrioritizedDispatcher::Handle handle_; | |
| 406 }; | |
| 407 | |
| 408 //----------------------------------------------------------------------------- | |
| 409 | |
| 362 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, | 410 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, |
| 363 size_t max_retry_attempts, | 411 size_t max_retry_attempts, |
| 364 bool use_cache, | 412 HostCache* cache, |
| 413 scoped_ptr<DnsConfigService> config_service, | |
| 365 NetLog* net_log) { | 414 NetLog* net_log) { |
| 366 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | 415 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) |
| 367 max_concurrent_resolves = kDefaultMaxProcTasks; | 416 max_concurrent_resolves = kDefaultMaxProcTasks; |
| 368 | 417 |
| 369 // TODO(szym): Add experiments with reserved slots for higher priority | 418 // TODO(szym): Add experiments with reserved slots for higher priority |
| 370 // requests. | 419 // requests. |
| 420 // TODO(szym): Add tighter limits for proc_dispatcher_ | |
|
cbentzel
2012/02/14 13:12:06
Why do you need this TODO? In this case it will on
szym
2012/02/14 15:56:24
I need this TODO to remember that even if I start
| |
| 371 | 421 |
| 372 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); | 422 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); |
| 373 | 423 |
| 374 HostResolverImpl* resolver = new HostResolverImpl( | 424 HostResolverImpl* resolver = new HostResolverImpl( |
| 375 use_cache ? HostCache::CreateDefaultCache() : NULL, | 425 cache, |
| 426 limits, | |
| 376 limits, | 427 limits, |
| 377 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), | 428 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), |
| 429 config_service.Pass(), | |
| 378 net_log); | 430 net_log); |
| 379 | 431 |
| 380 return resolver; | 432 return resolver; |
| 381 } | 433 } |
| 382 | 434 |
| 383 } // anonymous namespace | 435 } // anonymous namespace |
| 384 | 436 |
| 385 //----------------------------------------------------------------------------- | 437 //----------------------------------------------------------------------------- |
| 386 | 438 |
| 387 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | 439 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, |
| 388 size_t max_retry_attempts, | 440 size_t max_retry_attempts, |
| 389 NetLog* net_log) { | 441 NetLog* net_log) { |
| 390 return CreateHostResolver(max_concurrent_resolves, | 442 return CreateHostResolver(max_concurrent_resolves, |
| 391 max_retry_attempts, | 443 max_retry_attempts, |
| 392 true /* use_cache */, | 444 HostCache::CreateDefaultCache(), |
| 445 scoped_ptr<DnsConfigService>(NULL), | |
| 393 net_log); | 446 net_log); |
| 394 } | 447 } |
| 395 | 448 |
| 396 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, | 449 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, |
| 397 size_t max_retry_attempts, | 450 size_t max_retry_attempts, |
| 398 NetLog* net_log) { | 451 NetLog* net_log) { |
| 399 return CreateHostResolver(max_concurrent_resolves, | 452 return CreateHostResolver(max_concurrent_resolves, |
| 400 max_retry_attempts, | 453 max_retry_attempts, |
| 401 false /* use_cache */, | 454 NULL, |
| 455 scoped_ptr<DnsConfigService>(NULL), | |
| 402 net_log); | 456 net_log); |
| 403 } | 457 } |
| 404 | 458 |
| 459 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, | |
| 460 size_t max_retry_attempts, | |
| 461 NetLog* net_log) { | |
| 462 scoped_ptr<DnsConfigService> config_service | |
| 463 = DnsConfigService::CreateSystemService(); | |
|
mmenke
2012/02/14 18:46:00
nit: Put the equals sign on the previous line (Ca
| |
| 464 config_service->Watch(); | |
| 465 return CreateHostResolver(max_concurrent_resolves, | |
| 466 max_retry_attempts, | |
| 467 HostCache::CreateDefaultCache(), | |
| 468 config_service.Pass(), | |
| 469 net_log); | |
| 470 } | |
| 471 | |
| 405 //----------------------------------------------------------------------------- | 472 //----------------------------------------------------------------------------- |
| 406 | 473 |
| 407 // Holds the data for a request that could not be completed synchronously. | 474 // 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 | 475 // It is owned by a Job. Canceled Requests are only marked as canceled rather |
| 409 // than removed from the Job's |requests_| list. | 476 // than removed from the Job's |requests_| list. |
| 410 class HostResolverImpl::Request { | 477 class HostResolverImpl::Request { |
| 411 public: | 478 public: |
| 412 Request(const BoundNetLog& source_net_log, | 479 Request(const BoundNetLog& source_net_log, |
| 413 const BoundNetLog& request_net_log, | 480 const BoundNetLog& request_net_log, |
| 414 const RequestInfo& info, | 481 const RequestInfo& info, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 // resolution (OnLookupComplete) is completed or not. If the original attempt | 565 // resolution (OnLookupComplete) is completed or not. If the original attempt |
| 499 // hasn't completed, then we start another attempt for host resolution. We take | 566 // 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 | 567 // the results from the first attempt that finishes and ignore the results from |
| 501 // all other attempts. | 568 // all other attempts. |
| 502 // | 569 // |
| 503 // TODO(szym): Move to separate source file for testing and mocking. | 570 // TODO(szym): Move to separate source file for testing and mocking. |
| 504 // | 571 // |
| 505 class HostResolverImpl::ProcTask | 572 class HostResolverImpl::ProcTask |
| 506 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { | 573 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { |
| 507 public: | 574 public: |
| 508 typedef base::Callback<void(int, int, const AddressList&)> Callback; | 575 typedef base::Callback<void(int net_error, |
| 576 int os_error, | |
| 577 const AddressList& addr_list)> Callback; | |
| 509 | 578 |
| 510 ProcTask(const Key& key, | 579 ProcTask(const Key& key, |
| 511 const ProcTaskParams& params, | 580 const ProcTaskParams& params, |
| 512 const Callback& callback, | 581 const Callback& callback, |
| 513 const BoundNetLog& job_net_log) | 582 const BoundNetLog& job_net_log) |
| 514 : key_(key), | 583 : key_(key), |
| 515 params_(params), | 584 params_(params), |
| 516 callback_(callback), | 585 callback_(callback), |
| 517 origin_loop_(base::MessageLoopProxy::current()), | 586 origin_loop_(base::MessageLoopProxy::current()), |
| 518 attempt_number_(0), | 587 attempt_number_(0), |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 884 AddressList results_; | 953 AddressList results_; |
| 885 | 954 |
| 886 BoundNetLog net_log_; | 955 BoundNetLog net_log_; |
| 887 | 956 |
| 888 DISALLOW_COPY_AND_ASSIGN(ProcTask); | 957 DISALLOW_COPY_AND_ASSIGN(ProcTask); |
| 889 }; | 958 }; |
| 890 | 959 |
| 891 //----------------------------------------------------------------------------- | 960 //----------------------------------------------------------------------------- |
| 892 | 961 |
| 893 // Represents a request to the worker pool for a "probe for IPv6 support" call. | 962 // Represents a request to the worker pool for a "probe for IPv6 support" call. |
| 963 // | |
| 964 // TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks. | |
| 894 class HostResolverImpl::IPv6ProbeJob | 965 class HostResolverImpl::IPv6ProbeJob |
| 895 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { | 966 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
| 896 public: | 967 public: |
| 897 explicit IPv6ProbeJob(HostResolverImpl* resolver) | 968 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
| 898 : resolver_(resolver), | 969 : resolver_(resolver), |
| 899 origin_loop_(base::MessageLoopProxy::current()) { | 970 origin_loop_(base::MessageLoopProxy::current()) { |
| 900 DCHECK(resolver); | 971 DCHECK(resolver); |
| 901 } | 972 } |
| 902 | 973 |
| 903 void Start() { | 974 void Start() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 951 HostResolverImpl* resolver_; | 1022 HostResolverImpl* resolver_; |
| 952 | 1023 |
| 953 // Used to post ourselves onto the origin thread. | 1024 // Used to post ourselves onto the origin thread. |
| 954 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 1025 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
| 955 | 1026 |
| 956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 1027 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
| 957 }; | 1028 }; |
| 958 | 1029 |
| 959 //----------------------------------------------------------------------------- | 1030 //----------------------------------------------------------------------------- |
| 960 | 1031 |
| 1032 // Resolves the hostname using DnsTransaction. | |
| 1033 // TODO(szym): This could be moved to separate source file as well. | |
| 1034 class HostResolverImpl::DnsTask { | |
| 1035 public: | |
| 1036 typedef base::Callback<void(int net_error, | |
| 1037 const AddressList& addr_list, | |
| 1038 base::TimeDelta ttl)> Callback; | |
| 1039 | |
| 1040 DnsTask(DnsTransactionFactory* factory, | |
| 1041 const Key& key, | |
| 1042 const Callback& callback, | |
| 1043 const BoundNetLog& job_net_log) | |
| 1044 : callback_(callback), net_log_(job_net_log) { | |
| 1045 DCHECK(factory); | |
| 1046 DCHECK(!callback.is_null()); | |
| 1047 | |
| 1048 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. | |
| 1049 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) | |
| 1050 ? dns_protocol::kTypeAAAA | |
| 1051 : dns_protocol::kTypeA; | |
| 1052 // TODO(szym): Implement "happy eyeballs". | |
| 1053 transaction_ = factory->CreateTransaction( | |
| 1054 key.hostname, | |
| 1055 qtype, | |
| 1056 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)), | |
| 1057 net_log_); | |
| 1058 DCHECK(transaction_.get()); | |
| 1059 } | |
| 1060 | |
| 1061 int Start() { | |
| 1062 net_log_.BeginEvent( | |
| 1063 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
| 1064 new NetLogSourceParameter("source_dependency", | |
| 1065 transaction_->net_log().source())); | |
| 1066 return transaction_->Start(); | |
| 1067 } | |
| 1068 | |
| 1069 void OnTransactionComplete(DnsTransaction* transaction, | |
| 1070 int net_error, | |
| 1071 const DnsResponse* response) { | |
| 1072 // TODO(szym): Record performance histograms. | |
| 1073 if (net_error == OK) { | |
| 1074 AddressList addr_list; | |
| 1075 base::TimeDelta ttl; | |
| 1076 if (response->ParseAddressList(&addr_list, &ttl)) { | |
| 1077 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
| 1078 new AddressListNetLogParam(addr_list)); | |
| 1079 callback_.Run(net_error, addr_list, ttl); | |
| 1080 return; | |
| 1081 } | |
| 1082 net_error = ERR_DNS_MALFORMED_RESPONSE; | |
| 1083 } | |
| 1084 callback_.Run(net_error, AddressList(), base::TimeDelta()); | |
| 1085 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
| 1086 net_error); | |
| 1087 } | |
| 1088 | |
| 1089 private: | |
| 1090 // The listener to the results of this DnsTask. | |
| 1091 Callback callback_; | |
| 1092 | |
| 1093 const BoundNetLog net_log_; | |
| 1094 | |
| 1095 scoped_ptr<DnsTransaction> transaction_; | |
| 1096 }; | |
| 1097 | |
| 1098 //----------------------------------------------------------------------------- | |
| 1099 | |
| 961 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. | 1100 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
| 962 // Spawns ProcTask when started. | 1101 // Spawns ProcTask when started. |
|
cbentzel
2012/02/14 13:08:26
The comment "Spawns ProcTask when started" is no l
| |
| 963 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { | 1102 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
| 964 public: | 1103 public: |
| 965 // Creates new job for |key| where |request_net_log| is bound to the | 1104 // Creates new job for |key| where |request_net_log| is bound to the |
| 966 // request that spawned it. | 1105 // request that spawned it. |
| 967 Job(HostResolverImpl* resolver, | 1106 Job(HostResolverImpl* resolver, |
| 968 const Key& key, | 1107 const Key& key, |
| 969 const BoundNetLog& request_net_log) | 1108 const BoundNetLog& request_net_log, |
| 1109 RequestPriority priority) | |
| 970 : resolver_(resolver->AsWeakPtr()), | 1110 : resolver_(resolver->AsWeakPtr()), |
| 971 key_(key), | 1111 key_(key), |
| 1112 priority_tracker_(priority), | |
| 972 had_non_speculative_request_(false), | 1113 had_non_speculative_request_(false), |
| 973 net_log_(BoundNetLog::Make(request_net_log.net_log(), | 1114 net_log_(BoundNetLog::Make(request_net_log.net_log(), |
| 974 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), | 1115 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), |
| 975 net_error_(ERR_IO_PENDING), | 1116 net_error_(ERR_IO_PENDING), |
| 976 os_error_(0) { | 1117 os_error_(0) { |
| 977 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); | 1118 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); |
| 978 | 1119 |
| 979 net_log_.BeginEvent( | 1120 net_log_.BeginEvent( |
| 980 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1121 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 981 make_scoped_refptr(new JobCreationParameters( | 1122 make_scoped_refptr(new JobCreationParameters( |
| 982 key_.hostname, request_net_log.source()))); | 1123 key_.hostname, request_net_log.source()))); |
| 983 } | 1124 } |
| 984 | 1125 |
| 985 virtual ~Job() { | 1126 virtual ~Job() { |
| 986 if (net_error_ == ERR_IO_PENDING) { | 1127 if (net_error_ == ERR_IO_PENDING) { |
| 987 if (is_running()) { | 1128 if (is_running()) { |
| 988 DCHECK_EQ(ERR_IO_PENDING, net_error_); | 1129 DCHECK_EQ(ERR_IO_PENDING, net_error_); |
| 989 proc_task_->Cancel(); | 1130 proc_task_->Cancel(); |
|
cbentzel
2012/02/14 13:08:26
BUG: This needs to deal with the case where is_run
szym
2012/02/14 15:56:24
Good catch. Needs: "if (proc_task_.get())".
| |
| 990 proc_task_ = NULL; | 1131 proc_task_ = NULL; |
| 991 net_error_ = ERR_ABORTED; | 1132 net_error_ = ERR_ABORTED; |
| 992 } else { | 1133 } else { |
| 993 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 1134 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 994 net_error_ = OK; // For NetLog. | 1135 net_error_ = OK; // For NetLog. |
| 995 } | 1136 } |
| 996 | 1137 |
| 997 for (RequestsList::const_iterator it = requests_.begin(); | 1138 for (RequestsList::const_iterator it = requests_.begin(); |
| 998 it != requests_.end(); ++it) { | 1139 it != requests_.end(); ++it) { |
| 999 Request* req = *it; | 1140 Request* req = *it; |
| 1000 if (req->was_canceled()) | 1141 if (req->was_canceled()) |
| 1001 continue; | 1142 continue; |
| 1002 DCHECK_EQ(this, req->job()); | 1143 DCHECK_EQ(this, req->job()); |
| 1003 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1144 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 1004 req->info()); | 1145 req->info()); |
| 1005 } | 1146 } |
| 1006 } | 1147 } |
| 1007 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1148 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 1008 net_error_); | 1149 net_error_); |
| 1009 STLDeleteElements(&requests_); | 1150 STLDeleteElements(&requests_); |
| 1010 } | 1151 } |
| 1011 | 1152 |
| 1012 HostResolverImpl* resolver() const { | |
| 1013 return resolver_; | |
| 1014 } | |
| 1015 | |
| 1016 RequestPriority priority() const { | 1153 RequestPriority priority() const { |
| 1017 return priority_tracker_.highest_priority(); | 1154 return priority_tracker_.highest_priority(); |
| 1018 } | 1155 } |
| 1019 | 1156 |
| 1020 // Number of non-canceled requests in |requests_|. | 1157 // Number of non-canceled requests in |requests_|. |
| 1021 size_t num_active_requests() const { | 1158 size_t num_active_requests() const { |
| 1022 return priority_tracker_.total_count(); | 1159 return priority_tracker_.total_count(); |
| 1023 } | 1160 } |
| 1024 | 1161 |
| 1025 const Key& key() const { | 1162 const Key& key() const { |
| 1026 return key_; | 1163 return key_; |
| 1027 } | 1164 } |
| 1028 | 1165 |
| 1029 int net_error() const { | 1166 int net_error() const { |
| 1030 return net_error_; | 1167 return net_error_; |
| 1031 } | 1168 } |
| 1032 | 1169 |
| 1033 // Used by HostResolverImpl with |dispatcher_|. | 1170 void AddToDispatcher(PrioritizedDispatcher* dispatcher) { |
| 1034 const PrioritizedDispatcher::Handle& handle() const { | 1171 DCHECK(handle_.is_null()); |
| 1035 return handle_; | 1172 handle_ = DispatcherHandle(dispatcher, dispatcher->Add(this, priority())); |
| 1036 } | 1173 } |
| 1037 | 1174 |
| 1038 void set_handle(const PrioritizedDispatcher::Handle& handle) { | 1175 bool IsWaitingInDispatch() const { |
| 1039 handle_ = handle; | 1176 return !handle_.is_null(); |
| 1040 } | 1177 } |
| 1041 | 1178 |
| 1042 // The Job will own |req| and destroy it in ~Job. | 1179 // The Job will own |req| and destroy it in ~Job. |
|
cbentzel
2012/02/14 13:08:26
Nit: change this to take a scoped_ptr<Request> arg
| |
| 1043 void AddRequest(Request* req) { | 1180 void AddRequest(Request* req) { |
| 1044 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1181 DCHECK_EQ(key_.hostname, req->info().hostname()); |
| 1045 | 1182 |
| 1046 req->set_job(this); | 1183 req->set_job(this); |
| 1047 requests_.push_back(req); | 1184 requests_.push_back(req); |
| 1048 | 1185 |
| 1049 priority_tracker_.Add(req->info().priority()); | 1186 priority_tracker_.Add(req->info().priority()); |
| 1050 | 1187 |
| 1051 req->request_net_log().AddEvent( | 1188 req->request_net_log().AddEvent( |
| 1052 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | 1189 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, |
| 1053 make_scoped_refptr(new NetLogSourceParameter( | 1190 make_scoped_refptr(new NetLogSourceParameter( |
| 1054 "source_dependency", net_log_.source()))); | 1191 "source_dependency", net_log_.source()))); |
| 1055 | 1192 |
| 1056 net_log_.AddEvent( | 1193 net_log_.AddEvent( |
| 1057 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, | 1194 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, |
| 1058 make_scoped_refptr(new JobAttachParameters( | 1195 make_scoped_refptr(new JobAttachParameters( |
| 1059 req->request_net_log().source(), priority()))); | 1196 req->request_net_log().source(), priority()))); |
| 1060 | 1197 |
| 1061 // TODO(szym): Check if this is still needed. | 1198 // TODO(szym): Check if this is still needed. |
| 1062 if (!req->info().is_speculative()) { | 1199 if (!req->info().is_speculative()) { |
| 1063 had_non_speculative_request_ = true; | 1200 had_non_speculative_request_ = true; |
| 1064 if (proc_task_) | 1201 if (proc_task_) |
| 1065 proc_task_->set_had_non_speculative_request(); | 1202 proc_task_->set_had_non_speculative_request(); |
| 1066 } | 1203 } |
| 1204 | |
| 1205 if (!handle_.is_null()) | |
| 1206 handle_.ChangePriority(priority()); | |
| 1067 } | 1207 } |
| 1068 | 1208 |
| 1069 void CancelRequest(Request* req) { | 1209 void CancelRequest(Request* req) { |
| 1070 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1210 DCHECK_EQ(key_.hostname, req->info().hostname()); |
| 1071 DCHECK(!req->was_canceled()); | 1211 DCHECK(!req->was_canceled()); |
| 1072 // Don't remove it from |requests_| just mark it canceled. | 1212 // Don't remove it from |requests_| just mark it canceled. |
| 1073 req->MarkAsCanceled(); | 1213 req->MarkAsCanceled(); |
| 1074 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1214 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 1075 req->info()); | 1215 req->info()); |
| 1076 priority_tracker_.Remove(req->info().priority()); | 1216 priority_tracker_.Remove(req->info().priority()); |
| 1077 net_log_.AddEvent( | 1217 net_log_.AddEvent( |
| 1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, | 1218 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, |
| 1079 make_scoped_refptr(new JobAttachParameters( | 1219 make_scoped_refptr(new JobAttachParameters( |
| 1080 req->request_net_log().source(), priority()))); | 1220 req->request_net_log().source(), priority()))); |
| 1221 | |
| 1222 if (!handle_.is_null()) { | |
| 1223 if (num_active_requests() > 0) { | |
| 1224 handle_.ChangePriority(priority()); | |
| 1225 } else { | |
| 1226 handle_.Cancel(); | |
| 1227 } | |
| 1228 } | |
| 1081 } | 1229 } |
| 1082 | 1230 |
| 1083 // Aborts and destroys the job, completes all requests as aborted. | 1231 // Aborts and destroys the job, completes all requests as aborted. |
| 1084 void Abort() { | 1232 void Abort() { |
| 1085 // Job should only be aborted if it's running. | 1233 // Job should only be aborted if it's running. |
| 1086 DCHECK(is_running()); | 1234 DCHECK(is_running()); |
|
cbentzel
2012/02/14 13:08:26
Should this remove itself from the PrioritizedDisp
szym
2012/02/14 15:56:24
If is_running() then handle_ should be null. (A ru
| |
| 1087 proc_task_->Cancel(); | 1235 if (proc_task_.get()) { |
| 1088 proc_task_ = NULL; | 1236 proc_task_->Cancel(); |
| 1237 proc_task_ = NULL; | |
| 1238 } | |
| 1239 dns_task_.reset(); | |
| 1089 net_error_ = ERR_ABORTED; | 1240 net_error_ = ERR_ABORTED; |
| 1090 os_error_ = 0; | 1241 os_error_ = 0; |
| 1091 CompleteRequests(AddressList()); | 1242 CompleteRequests(AddressList(), base::TimeDelta()); |
| 1243 } | |
| 1244 | |
| 1245 bool is_dns_running() const { | |
| 1246 return dns_task_.get() != NULL; | |
| 1247 } | |
| 1248 | |
| 1249 bool is_proc_running() const { | |
| 1250 return proc_task_.get() != NULL; | |
| 1092 } | 1251 } |
| 1093 | 1252 |
| 1094 bool is_running() const { | 1253 bool is_running() const { |
| 1095 return proc_task_.get() != NULL; | 1254 return is_dns_running() || is_proc_running(); |
| 1096 } | 1255 } |
| 1097 | 1256 |
| 1098 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1257 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
| 1099 void OnEvicted() { | 1258 void OnEvicted() { |
| 1100 // Must not be running. | 1259 // Must not be running. |
| 1101 DCHECK(!is_running()); | 1260 DCHECK(!is_running()); |
| 1102 handle_ = PrioritizedDispatcher::Handle(); | 1261 handle_.Reset(); |
| 1103 | 1262 |
| 1104 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | 1263 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); |
| 1105 | 1264 |
| 1106 // This signals to CompleteRequests that this job never ran. | 1265 // This signals to CompleteRequests that this job never ran. |
| 1107 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1266 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
| 1108 os_error_ = 0; | 1267 os_error_ = 0; |
| 1109 CompleteRequests(AddressList()); | 1268 CompleteRequests(AddressList(), base::TimeDelta()); |
| 1110 } | 1269 } |
| 1111 | 1270 |
| 1112 // PriorityDispatch::Job interface. | 1271 // PriorityDispatch::Job interface. |
| 1113 virtual void Start() OVERRIDE { | 1272 virtual void Start() OVERRIDE { |
| 1114 DCHECK(!is_running()); | 1273 DCHECK(!is_running()); |
| 1115 handle_ = PrioritizedDispatcher::Handle(); | 1274 handle_.Reset(); |
| 1116 | 1275 |
| 1117 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); | 1276 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); |
| 1118 | 1277 |
| 1278 if (resolver_->dns_transaction_factory_.get()) { | |
| 1279 StartDnsTask(); | |
| 1280 } else { | |
| 1281 StartProcTask(); | |
| 1282 } | |
| 1283 } | |
| 1284 | |
| 1285 private: | |
| 1286 void StartProcTask() { | |
| 1119 proc_task_ = new ProcTask( | 1287 proc_task_ = new ProcTask( |
| 1120 key_, | 1288 key_, |
| 1121 resolver_->proc_params_, | 1289 resolver_->proc_params_, |
| 1122 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), | 1290 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), |
| 1123 net_log_); | 1291 net_log_); |
| 1124 | 1292 |
| 1125 if (had_non_speculative_request_) | 1293 if (had_non_speculative_request_) |
| 1126 proc_task_->set_had_non_speculative_request(); | 1294 proc_task_->set_had_non_speculative_request(); |
| 1127 // Start() could be called from within Resolve(), hence it must NOT directly | 1295 // Start() could be called from within Resolve(), hence it must NOT directly |
| 1128 // call OnProcTaskComplete, for example, on synchronous failure. | 1296 // call OnProcTaskComplete, for example, on synchronous failure. |
| 1129 proc_task_->Start(); | 1297 proc_task_->Start(); |
| 1130 } | 1298 } |
| 1131 | 1299 |
| 1132 private: | 1300 void StartDnsTask() { |
| 1301 dns_task_.reset(new DnsTask( | |
| 1302 resolver_->dns_transaction_factory_.get(), | |
| 1303 key_, | |
| 1304 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), | |
| 1305 net_log_)); | |
| 1306 | |
| 1307 int rv = dns_task_->Start(); | |
| 1308 if (rv != ERR_IO_PENDING) { | |
| 1309 DCHECK_NE(OK, rv); | |
| 1310 // TODO(szym): AddToDispatcher(resolver_->proc_dispatcher_); | |
| 1311 StartProcTask(); | |
| 1312 } | |
| 1313 } | |
| 1314 | |
| 1133 // Called by ProcTask when it completes. | 1315 // Called by ProcTask when it completes. |
| 1134 void OnProcTaskComplete(int net_error, int os_error, | 1316 void OnProcTaskComplete(int net_error, int os_error, |
|
cbentzel
2012/02/14 13:08:26
Nit: probably easier to read if this were moved di
| |
| 1135 const AddressList& addrlist) { | 1317 const AddressList& addr_list) { |
| 1136 DCHECK(is_running()); | 1318 DCHECK(is_proc_running()); |
| 1137 proc_task_ = NULL; | 1319 proc_task_ = NULL; |
| 1138 net_error_ = net_error; | 1320 net_error_ = net_error; |
| 1139 os_error_ = os_error; | 1321 os_error_ = os_error; |
| 1140 | 1322 |
| 1141 // We are the only consumer of |addrlist|, so we can safely change the port | 1323 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); |
|
cbentzel
2012/02/14 13:08:26
Should there be a constant for negative cache TTL?
| |
| 1142 // without copy-on-write. This pays off, when job has only one request. | 1324 if (net_error == OK) |
| 1143 AddressList list = addrlist; | 1325 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
| 1144 if (net_error == OK && !requests_.empty()) | 1326 CompleteRequests(addr_list, ttl); |
| 1145 MutableSetPort(requests_.front()->info().port(), &list); | 1327 } |
| 1146 CompleteRequests(list); | 1328 |
| 1329 // Called by DnsTask when it completes. | |
| 1330 void OnDnsTaskComplete(int net_error, | |
| 1331 const AddressList& addr_list, | |
| 1332 base::TimeDelta ttl) { | |
| 1333 DCHECK(is_dns_running()); | |
| 1334 dns_task_.reset(); | |
| 1335 | |
| 1336 if (net_error != OK) { | |
| 1337 // TODO(szym): Some net errors indicate lack of connectivity. Starting | |
| 1338 // ProcTask in that case is a waste of time. | |
| 1339 StartProcTask(); | |
| 1340 return; | |
| 1341 } | |
| 1342 | |
| 1343 net_error_ = OK; | |
| 1344 os_error_ = 0; | |
| 1345 CompleteRequests(addr_list, ttl); | |
| 1147 } | 1346 } |
| 1148 | 1347 |
| 1149 // Completes all Requests. Calls OnJobFinished and deletes self. | 1348 // Completes all Requests. Calls OnJobFinished and deletes self. |
| 1150 void CompleteRequests(const AddressList& addrlist) { | 1349 void CompleteRequests(const AddressList& addr_list, base::TimeDelta ttl) { |
| 1151 CHECK(resolver_); | 1350 CHECK(resolver_); |
| 1152 | 1351 |
| 1352 // We are the only consumer of |addr_list|, so we can safely change the port | |
| 1353 // without copy-on-write. This pays off, when job has only one request. | |
| 1354 AddressList list = addr_list; | |
| 1355 if (net_error_ == OK && !requests_.empty()) | |
| 1356 MutableSetPort(requests_.front()->info().port(), &list); | |
| 1357 | |
| 1153 // This job must be removed from resolver's |jobs_| now to make room for a | 1358 // 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 | 1359 // 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 | 1360 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
| 1156 // is done. | 1361 // is done. |
| 1157 scoped_ptr<Job> self_deleter(this); | 1362 scoped_ptr<Job> self_deleter(this); |
| 1158 resolver_->OnJobFinished(this, addrlist); | 1363 resolver_->OnJobFinished(this, addr_list, ttl); |
|
cbentzel
2012/02/14 13:08:26
Does this need to be called after deleting self? W
szym
2012/02/14 15:56:24
I'm not clear what you mean. After deleting self I
cbentzel
2012/02/14 18:01:27
It was the second point I was concerned about. Agr
| |
| 1159 | 1364 |
| 1160 // Complete all of the requests that were attached to the job. | 1365 // Complete all of the requests that were attached to the job. |
| 1161 for (RequestsList::const_iterator it = requests_.begin(); | 1366 for (RequestsList::const_iterator it = requests_.begin(); |
| 1162 it != requests_.end(); ++it) { | 1367 it != requests_.end(); ++it) { |
| 1163 Request* req = *it; | 1368 Request* req = *it; |
| 1164 | 1369 |
| 1165 if (req->was_canceled()) | 1370 if (req->was_canceled()) |
| 1166 continue; | 1371 continue; |
| 1167 | 1372 |
| 1168 DCHECK_EQ(this, req->job()); | 1373 DCHECK_EQ(this, req->job()); |
| 1169 // Update the net log and notify registered observers. | 1374 // Update the net log and notify registered observers. |
| 1170 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1375 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
| 1171 req->info(), net_error_, os_error_); | 1376 req->info(), net_error_, os_error_); |
| 1172 | 1377 |
| 1173 req->OnComplete(net_error_, addrlist); | 1378 req->OnComplete(net_error_, addr_list); |
| 1174 | 1379 |
| 1175 // Check if the resolver was destroyed as a result of running the | 1380 // 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. | 1381 // callback. If it was, we could continue, but we choose to bail. |
| 1177 if (!resolver_) | 1382 if (!resolver_) |
| 1178 return; | 1383 return; |
| 1179 } | 1384 } |
| 1180 } | 1385 } |
| 1181 | 1386 |
| 1182 // Used to call OnJobFinished and RemoveJob. | 1387 // Used to call OnJobFinished. |
| 1183 base::WeakPtr<HostResolverImpl> resolver_; | 1388 base::WeakPtr<HostResolverImpl> resolver_; |
| 1184 | 1389 |
| 1185 Key key_; | 1390 Key key_; |
| 1186 | 1391 |
| 1187 // Tracks the highest priority across |requests_|. | 1392 // Tracks the highest priority across |requests_|. |
| 1188 PriorityTracker priority_tracker_; | 1393 PriorityTracker priority_tracker_; |
| 1189 | 1394 |
| 1190 bool had_non_speculative_request_; | 1395 bool had_non_speculative_request_; |
| 1191 | 1396 |
| 1192 BoundNetLog net_log_; | 1397 BoundNetLog net_log_; |
| 1193 | 1398 |
| 1194 // Store result here in case the job fails fast in Resolve(). | 1399 // Store result here in case the job fails fast in Resolve(). |
| 1195 int net_error_; | 1400 int net_error_; |
| 1196 int os_error_; | 1401 int os_error_; |
| 1197 | 1402 |
| 1198 // A ProcTask created and started when this Job is dispatched.. | 1403 // Resolves the host using a HostResolverProc. |
| 1199 scoped_refptr<ProcTask> proc_task_; | 1404 scoped_refptr<ProcTask> proc_task_; |
| 1200 | 1405 |
| 1406 // Resolves the host using a DnsTransaction. | |
| 1407 scoped_ptr<DnsTask> dns_task_; | |
| 1408 | |
| 1201 // All Requests waiting for the result of this Job. Some can be canceled. | 1409 // All Requests waiting for the result of this Job. Some can be canceled. |
| 1202 RequestsList requests_; | 1410 RequestsList requests_; |
| 1203 | 1411 |
| 1204 // A handle used by HostResolverImpl in |dispatcher_|. | 1412 // A handle used by HostResolverImpl in |dispatcher_|. |
| 1205 PrioritizedDispatcher::Handle handle_; | 1413 DispatcherHandle handle_; |
| 1206 }; | 1414 }; |
| 1207 | 1415 |
| 1208 //----------------------------------------------------------------------------- | 1416 //----------------------------------------------------------------------------- |
| 1209 | 1417 |
| 1210 HostResolverImpl::ProcTaskParams::ProcTaskParams( | 1418 HostResolverImpl::ProcTaskParams::ProcTaskParams( |
| 1211 HostResolverProc* resolver_proc, | 1419 HostResolverProc* resolver_proc, |
| 1212 size_t max_retry_attempts) | 1420 size_t max_retry_attempts) |
| 1213 : resolver_proc(resolver_proc), | 1421 : resolver_proc(resolver_proc), |
| 1214 max_retry_attempts(max_retry_attempts), | 1422 max_retry_attempts(max_retry_attempts), |
| 1215 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), | 1423 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), |
| 1216 retry_factor(2) { | 1424 retry_factor(2) { |
| 1217 } | 1425 } |
| 1218 | 1426 |
| 1219 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} | 1427 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} |
| 1220 | 1428 |
| 1221 HostResolverImpl::HostResolverImpl( | 1429 HostResolverImpl::HostResolverImpl( |
| 1222 HostCache* cache, | 1430 HostCache* cache, |
| 1223 const PrioritizedDispatcher::Limits& job_limits, | 1431 const PrioritizedDispatcher::Limits& job_limits, |
| 1432 const PrioritizedDispatcher::Limits& proc_limits, | |
| 1224 const ProcTaskParams& proc_params, | 1433 const ProcTaskParams& proc_params, |
| 1434 scoped_ptr<DnsConfigService> dns_config_service, | |
| 1225 NetLog* net_log) | 1435 NetLog* net_log) |
| 1226 : cache_(cache), | 1436 : cache_(cache), |
| 1227 dispatcher_(job_limits), | 1437 dispatcher_(job_limits), |
| 1438 proc_dispatcher_(proc_limits), | |
|
cbentzel
2012/02/14 13:08:26
Is proc_dispatcher_ even used? It looks like we ju
szym
2012/02/14 15:56:24
Right now it is not. I'm okay removing it until we
cbentzel
2012/02/14 18:01:27
I'd recommend removing it for now, as well as the
| |
| 1228 max_queued_jobs_(job_limits.total_jobs * 100u), | 1439 max_queued_jobs_(job_limits.total_jobs * 100u), |
| 1229 proc_params_(proc_params), | 1440 proc_params_(proc_params), |
| 1230 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 1441 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
| 1442 dns_config_service_(dns_config_service.Pass()), | |
| 1231 ipv6_probe_monitoring_(false), | 1443 ipv6_probe_monitoring_(false), |
| 1232 additional_resolver_flags_(0), | 1444 additional_resolver_flags_(0), |
| 1233 net_log_(net_log) { | 1445 net_log_(net_log) { |
| 1234 | 1446 |
| 1235 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); | 1447 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
| 1448 DCHECK_EQ(proc_dispatcher_.num_priorities(), dispatcher_.num_priorities()); | |
| 1236 | 1449 |
| 1237 // Maximum of 4 retry attempts for host resolution. | 1450 // Maximum of 4 retry attempts for host resolution. |
| 1238 static const size_t kDefaultMaxRetryAttempts = 4u; | 1451 static const size_t kDefaultMaxRetryAttempts = 4u; |
| 1239 | 1452 |
| 1240 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) | 1453 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) |
| 1241 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; | 1454 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; |
| 1242 | 1455 |
| 1243 #if defined(OS_WIN) | 1456 #if defined(OS_WIN) |
| 1244 EnsureWinsockInit(); | 1457 EnsureWinsockInit(); |
| 1245 #endif | 1458 #endif |
| 1246 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1459 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 1247 if (HaveOnlyLoopbackAddresses()) | 1460 if (HaveOnlyLoopbackAddresses()) |
| 1248 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; | 1461 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
| 1249 #endif | 1462 #endif |
| 1250 NetworkChangeNotifier::AddIPAddressObserver(this); | 1463 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 1251 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1464 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| 1252 #if !defined(OS_ANDROID) | 1465 #if !defined(OS_ANDROID) |
| 1253 EnsureDnsReloaderInit(); | 1466 EnsureDnsReloaderInit(); |
| 1254 #endif | 1467 #endif |
| 1255 NetworkChangeNotifier::AddDNSObserver(this); | 1468 NetworkChangeNotifier::AddDNSObserver(this); |
| 1256 #endif | 1469 #endif |
| 1470 | |
| 1471 if (dns_config_service_.get()) | |
| 1472 dns_config_service_->AddObserver(this); | |
| 1257 } | 1473 } |
| 1258 | 1474 |
| 1259 HostResolverImpl::~HostResolverImpl() { | 1475 HostResolverImpl::~HostResolverImpl() { |
| 1260 DiscardIPv6ProbeJob(); | 1476 DiscardIPv6ProbeJob(); |
| 1261 | 1477 |
| 1262 // This will also cancel all outstanding requests. | 1478 // This will also cancel all outstanding requests. |
| 1263 STLDeleteValues(&jobs_); | 1479 STLDeleteValues(&jobs_); |
| 1264 | 1480 |
| 1265 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 1481 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 1266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1482 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1300 return rv; | 1516 return rv; |
| 1301 } | 1517 } |
| 1302 | 1518 |
| 1303 // Next we need to attach our request to a "job". This job is responsible for | 1519 // Next we need to attach our request to a "job". This job is responsible for |
| 1304 // calling "getaddrinfo(hostname)" on a worker thread. | 1520 // calling "getaddrinfo(hostname)" on a worker thread. |
| 1305 | 1521 |
| 1306 JobMap::iterator jobit = jobs_.find(key); | 1522 JobMap::iterator jobit = jobs_.find(key); |
| 1307 Job* job; | 1523 Job* job; |
| 1308 if (jobit == jobs_.end()) { | 1524 if (jobit == jobs_.end()) { |
| 1309 // Create new Job. | 1525 // Create new Job. |
| 1310 job = new Job(this, key, request_net_log); | 1526 job = new Job(this, key, request_net_log, info.priority()); |
| 1311 job->set_handle(dispatcher_.Add(job, info.priority())); | 1527 job->AddToDispatcher(&dispatcher_); |
| 1312 | 1528 |
| 1313 // Check for queue overflow. | 1529 // Check for queue overflow. |
| 1314 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { | 1530 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { |
| 1315 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); | 1531 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); |
| 1316 DCHECK(evicted); | 1532 DCHECK(evicted); |
| 1317 if (evicted == job) { | 1533 if (evicted == job) { |
| 1318 delete job; | 1534 delete job; |
| 1319 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1535 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
| 1320 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); | 1536 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); |
| 1321 return rv; | 1537 return rv; |
| 1322 } | 1538 } |
| 1323 evicted->OnEvicted(); // Deletes |evicted|. | 1539 evicted->OnEvicted(); // Deletes |evicted|. |
| 1324 } | 1540 } |
| 1325 | 1541 |
| 1326 jobs_.insert(jobit, std::make_pair(key, job)); | 1542 jobs_.insert(jobit, std::make_pair(key, job)); |
| 1327 } else { | 1543 } else { |
| 1328 job = jobit->second; | 1544 job = jobit->second; |
| 1329 } | 1545 } |
| 1330 | 1546 |
| 1331 // Can't complete synchronously. Create and attach request. | 1547 // Can't complete synchronously. Create and attach request. |
| 1332 Request* req = new Request(source_net_log, request_net_log, info, callback, | 1548 Request* req = new Request(source_net_log, request_net_log, info, callback, |
| 1333 addresses); | 1549 addresses); |
| 1334 job->AddRequest(req); | 1550 job->AddRequest(req); |
| 1335 if (!job->handle().is_null()) | |
| 1336 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); | |
| 1337 if (out_req) | 1551 if (out_req) |
| 1338 *out_req = reinterpret_cast<RequestHandle>(req); | 1552 *out_req = reinterpret_cast<RequestHandle>(req); |
| 1339 | 1553 |
| 1340 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); | 1554 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); |
| 1341 // Completion happens during Job::CompleteRequests(). | 1555 // Completion happens during Job::CompleteRequests(). |
| 1342 return ERR_IO_PENDING; | 1556 return ERR_IO_PENDING; |
| 1343 } | 1557 } |
| 1344 | 1558 |
| 1345 int HostResolverImpl::ResolveHelper(const Key& key, | 1559 int HostResolverImpl::ResolveHelper(const Key& key, |
| 1346 const RequestInfo& info, | 1560 const RequestInfo& info, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1384 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { | 1598 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { |
| 1385 DCHECK(CalledOnValidThread()); | 1599 DCHECK(CalledOnValidThread()); |
| 1386 Request* req = reinterpret_cast<Request*>(req_handle); | 1600 Request* req = reinterpret_cast<Request*>(req_handle); |
| 1387 DCHECK(req); | 1601 DCHECK(req); |
| 1388 | 1602 |
| 1389 Job* job = req->job(); | 1603 Job* job = req->job(); |
| 1390 DCHECK(job); | 1604 DCHECK(job); |
| 1391 | 1605 |
| 1392 job->CancelRequest(req); | 1606 job->CancelRequest(req); |
| 1393 | 1607 |
| 1394 if (!job->handle().is_null()) { | 1608 if (job->num_active_requests() == 0) { |
| 1395 // Still in queue. | 1609 if (job->is_running()) { |
| 1396 if (job->num_active_requests()) { | 1610 // Job is running (and could be in CompleteRequests right now). |
| 1397 job->set_handle(dispatcher_.ChangePriority(job->handle(), | 1611 // But to be in Request::OnComplete we would have to have a non-canceled |
| 1398 job->priority())); | 1612 // request. So it is safe to Abort it if it has no more active requests. |
| 1613 job->Abort(); | |
| 1399 } else { | 1614 } else { |
| 1400 dispatcher_.Cancel(job->handle()); | |
| 1401 RemoveJob(job); | 1615 RemoveJob(job); |
| 1402 delete job; | 1616 delete job; |
| 1403 } | 1617 } |
| 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(); | |
| 1410 } | |
| 1411 } | 1618 } |
| 1412 } | 1619 } |
| 1413 | 1620 |
| 1414 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { | 1621 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
| 1415 DCHECK(CalledOnValidThread()); | 1622 DCHECK(CalledOnValidThread()); |
| 1416 ipv6_probe_monitoring_ = false; | 1623 ipv6_probe_monitoring_ = false; |
| 1417 DiscardIPv6ProbeJob(); | 1624 DiscardIPv6ProbeJob(); |
| 1418 default_address_family_ = address_family; | 1625 default_address_family_ = address_family; |
| 1419 } | 1626 } |
| 1420 | 1627 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1475 if (!cache_entry) | 1682 if (!cache_entry) |
| 1476 return false; | 1683 return false; |
| 1477 | 1684 |
| 1478 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1685 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
| 1479 *net_error = cache_entry->error; | 1686 *net_error = cache_entry->error; |
| 1480 if (*net_error == OK) | 1687 if (*net_error == OK) |
| 1481 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1688 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
| 1482 return true; | 1689 return true; |
| 1483 } | 1690 } |
| 1484 | 1691 |
| 1485 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { | 1692 void HostResolverImpl::OnJobFinished(Job* job, |
| 1693 const AddressList& addrlist, | |
| 1694 base::TimeDelta ttl) { | |
| 1486 DCHECK(job); | 1695 DCHECK(job); |
| 1487 DCHECK(job->handle().is_null()); | 1696 DCHECK(!job->IsWaitingInDispatch()); |
| 1488 RemoveJob(job); | 1697 RemoveJob(job); |
| 1489 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) | 1698 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) |
| 1490 return; | 1699 return; |
| 1491 | 1700 |
| 1492 // Signal dispatcher that a slot has opened. | 1701 // Signal dispatcher that a slot has opened. |
| 1493 dispatcher_.OnJobFinished(); | 1702 dispatcher_.OnJobFinished(); |
| 1494 if (job->net_error() == ERR_ABORTED) | 1703 if (job->net_error() == ERR_ABORTED) |
| 1495 return; | 1704 return; |
| 1496 // Write result to the cache. | 1705 // Write result to the cache. |
| 1497 if (cache_.get()) { | 1706 if (cache_.get()) { |
| 1498 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); | |
| 1499 if (job->net_error() == OK) | |
| 1500 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | |
| 1501 cache_->Set(job->key(), job->net_error(), addrlist, | 1707 cache_->Set(job->key(), job->net_error(), addrlist, |
| 1502 base::TimeTicks::Now(), ttl); | 1708 base::TimeTicks::Now(), ttl); |
| 1503 } | 1709 } |
| 1504 } | 1710 } |
| 1505 | 1711 |
| 1506 void HostResolverImpl::RemoveJob(Job* job) { | 1712 void HostResolverImpl::RemoveJob(Job* job) { |
| 1507 DCHECK(job); | 1713 DCHECK(job); |
| 1508 jobs_.erase(job->key()); | 1714 jobs_.erase(job->key()); |
| 1509 } | 1715 } |
| 1510 | 1716 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1550 Job* job = it->second; | 1756 Job* job = it->second; |
| 1551 // Advance the iterator before we might erase it. | 1757 // Advance the iterator before we might erase it. |
| 1552 ++it; | 1758 ++it; |
| 1553 if (job->is_running()) { | 1759 if (job->is_running()) { |
| 1554 job->Abort(); | 1760 job->Abort(); |
| 1555 // Check if resolver was deleted in a request callback. | 1761 // Check if resolver was deleted in a request callback. |
| 1556 if (!self) | 1762 if (!self) |
| 1557 return; | 1763 return; |
| 1558 } else { | 1764 } else { |
| 1559 // Keep it in |dispatch_|. | 1765 // Keep it in |dispatch_|. |
| 1560 DCHECK(!job->handle().is_null()); | 1766 DCHECK(job->IsWaitingInDispatch()); |
| 1561 } | 1767 } |
| 1562 } | 1768 } |
| 1563 } | 1769 } |
| 1564 | 1770 |
| 1565 void HostResolverImpl::OnIPAddressChanged() { | 1771 void HostResolverImpl::OnIPAddressChanged() { |
| 1566 if (cache_.get()) | 1772 if (cache_.get()) |
| 1567 cache_->clear(); | 1773 cache_->clear(); |
| 1568 if (ipv6_probe_monitoring_) { | 1774 if (ipv6_probe_monitoring_) { |
| 1569 DiscardIPv6ProbeJob(); | 1775 DiscardIPv6ProbeJob(); |
| 1570 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1776 ipv6_probe_job_ = new IPv6ProbeJob(this); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1587 // as NSCD's cache should be dropped automatically by the OS when | 1793 // 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. | 1794 // resolv.conf changes so we don't need to do anything to clear that cache. |
| 1589 if (cache_.get()) | 1795 if (cache_.get()) |
| 1590 cache_->clear(); | 1796 cache_->clear(); |
| 1591 // Existing jobs will have been sent to the original server so they need to | 1797 // Existing jobs will have been sent to the original server so they need to |
| 1592 // be aborted. TODO(Craig): Should these jobs be restarted? | 1798 // be aborted. TODO(Craig): Should these jobs be restarted? |
| 1593 AbortAllInProgressJobs(); | 1799 AbortAllInProgressJobs(); |
| 1594 // |this| may be deleted inside AbortAllInProgressJobs(). | 1800 // |this| may be deleted inside AbortAllInProgressJobs(). |
| 1595 } | 1801 } |
| 1596 | 1802 |
| 1803 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { | |
| 1804 // We want a new factory in place, before we Abort running Jobs, so that the | |
| 1805 // newly started jobs use the new factory. | |
| 1806 bool had_factory = (dns_transaction_factory_.get() != NULL); | |
| 1807 if (dns_config.IsValid()) { | |
| 1808 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( | |
| 1809 new DnsSession(dns_config, | |
| 1810 ClientSocketFactory::GetDefaultFactory(), | |
| 1811 base::Bind(&base::RandInt), | |
| 1812 net_log_)); | |
| 1813 } else { | |
| 1814 dns_transaction_factory_.reset(); | |
| 1815 } | |
| 1816 if (had_factory) { | |
| 1817 OnDNSChanged(); | |
| 1818 } | |
| 1819 } | |
| 1820 | |
| 1597 } // namespace net | 1821 } // namespace net |
| OLD | NEW |