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

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: Fix ClientSocketFactory lifetime. Move ScopedAllowIO to StartWatch. Added DnsTask logging. 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
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698