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

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

Issue 22909037: [net/dns] Reland of 218616 (Simultaneous A/AAAA queries). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix printing unsigned Created 7 years, 3 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
« no previous file with comments | « net/dns/host_resolver_impl.h ('k') | net/dns/host_resolver_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/dns/host_resolver_impl.h" 5 #include "net/dns/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>
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 62
63 // Default TTL for successful resolutions with ProcTask. 63 // Default TTL for successful resolutions with ProcTask.
64 const unsigned kCacheEntryTTLSeconds = 60; 64 const unsigned kCacheEntryTTLSeconds = 60;
65 65
66 // Default TTL for unsuccessful resolutions with ProcTask. 66 // Default TTL for unsuccessful resolutions with ProcTask.
67 const unsigned kNegativeCacheEntryTTLSeconds = 0; 67 const unsigned kNegativeCacheEntryTTLSeconds = 0;
68 68
69 // Minimum TTL for successful resolutions with DnsTask. 69 // Minimum TTL for successful resolutions with DnsTask.
70 const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds; 70 const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds;
71 71
72 // Number of consecutive failures of DnsTask (with successful fallback) before
73 // the DnsClient is disabled until the next DNS change.
74 const unsigned kMaximumDnsFailures = 16;
75
76 // We use a separate histogram name for each platform to facilitate the 72 // We use a separate histogram name for each platform to facilitate the
77 // display of error codes by their symbolic name (since each platform has 73 // display of error codes by their symbolic name (since each platform has
78 // different mappings). 74 // different mappings).
79 const char kOSErrorsForGetAddrinfoHistogramName[] = 75 const char kOSErrorsForGetAddrinfoHistogramName[] =
80 #if defined(OS_WIN) 76 #if defined(OS_WIN)
81 "Net.OSErrorsForGetAddrinfo_Win"; 77 "Net.OSErrorsForGetAddrinfo_Win";
82 #elif defined(OS_MACOSX) 78 #elif defined(OS_MACOSX)
83 "Net.OSErrorsForGetAddrinfo_Mac"; 79 "Net.OSErrorsForGetAddrinfo_Mac";
84 #elif defined(OS_LINUX) 80 #elif defined(OS_LINUX)
85 "Net.OSErrorsForGetAddrinfo_Linux"; 81 "Net.OSErrorsForGetAddrinfo_Linux";
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 private: 445 private:
450 RequestPriority highest_priority_; 446 RequestPriority highest_priority_;
451 size_t total_count_; 447 size_t total_count_;
452 size_t counts_[NUM_PRIORITIES]; 448 size_t counts_[NUM_PRIORITIES];
453 }; 449 };
454 450
455 } // namespace 451 } // namespace
456 452
457 //----------------------------------------------------------------------------- 453 //-----------------------------------------------------------------------------
458 454
455 const unsigned HostResolverImpl::kMaximumDnsFailures = 16;
456
459 // Holds the data for a request that could not be completed synchronously. 457 // Holds the data for a request that could not be completed synchronously.
460 // It is owned by a Job. Canceled Requests are only marked as canceled rather 458 // It is owned by a Job. Canceled Requests are only marked as canceled rather
461 // than removed from the Job's |requests_| list. 459 // than removed from the Job's |requests_| list.
462 class HostResolverImpl::Request { 460 class HostResolverImpl::Request {
463 public: 461 public:
464 Request(const BoundNetLog& source_net_log, 462 Request(const BoundNetLog& source_net_log,
465 const BoundNetLog& request_net_log, 463 const BoundNetLog& request_net_log,
466 const RequestInfo& info, 464 const RequestInfo& info,
467 RequestPriority priority, 465 RequestPriority priority,
468 const CompletionCallback& callback, 466 const CompletionCallback& callback,
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 961
964 DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); 962 DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob);
965 }; 963 };
966 964
967 //----------------------------------------------------------------------------- 965 //-----------------------------------------------------------------------------
968 966
969 // Resolves the hostname using DnsTransaction. 967 // Resolves the hostname using DnsTransaction.
970 // TODO(szym): This could be moved to separate source file as well. 968 // TODO(szym): This could be moved to separate source file as well.
971 class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> { 969 class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> {
972 public: 970 public:
973 typedef base::Callback<void(int net_error, 971 class Delegate {
974 const AddressList& addr_list, 972 public:
975 base::TimeDelta ttl)> Callback; 973 virtual void OnDnsTaskComplete(base::TimeTicks start_time,
974 int net_error,
975 const AddressList& addr_list,
976 base::TimeDelta ttl) = 0;
977
978 // Called when the first of two jobs succeeds. If the first completed
979 // transaction fails, this is not called. Also not called when the DnsTask
980 // only needs to run one transaction.
981 virtual void OnFirstDnsTransactionComplete() = 0;
982
983 protected:
984 Delegate() {}
985 virtual ~Delegate() {}
986 };
976 987
977 DnsTask(DnsClient* client, 988 DnsTask(DnsClient* client,
978 const Key& key, 989 const Key& key,
979 const Callback& callback, 990 Delegate* delegate,
980 const BoundNetLog& job_net_log) 991 const BoundNetLog& job_net_log)
981 : client_(client), 992 : client_(client),
982 family_(key.address_family), 993 key_(key),
983 callback_(callback), 994 delegate_(delegate),
984 net_log_(job_net_log) { 995 net_log_(job_net_log),
996 num_completed_transactions_(0),
997 task_start_time_(base::TimeTicks::Now()) {
985 DCHECK(client); 998 DCHECK(client);
986 DCHECK(!callback.is_null()); 999 DCHECK(delegate_);
1000 }
987 1001
988 // If unspecified, do IPv4 first, because suffix search will be faster. 1002 bool needs_two_transactions() const {
989 uint16 qtype = (family_ == ADDRESS_FAMILY_IPV6) ? 1003 return key_.address_family == ADDRESS_FAMILY_UNSPECIFIED;
990 dns_protocol::kTypeAAAA : 1004 }
991 dns_protocol::kTypeA; 1005
992 transaction_ = client_->GetTransactionFactory()->CreateTransaction( 1006 bool needs_another_transaction() const {
993 key.hostname, 1007 return needs_two_transactions() && !transaction_aaaa_;
994 qtype, 1008 }
1009
1010 void StartFirstTransaction() {
1011 DCHECK_EQ(0u, num_completed_transactions_);
1012 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK);
1013 if (key_.address_family == ADDRESS_FAMILY_IPV6) {
1014 StartAAAA();
1015 } else {
1016 StartA();
1017 }
1018 }
1019
1020 void StartSecondTransaction() {
1021 DCHECK(needs_two_transactions());
1022 StartAAAA();
1023 }
1024
1025 private:
1026 void StartA() {
1027 DCHECK(!transaction_a_);
1028 DCHECK_NE(ADDRESS_FAMILY_IPV6, key_.address_family);
1029 transaction_a_ = CreateTransaction(ADDRESS_FAMILY_IPV4);
1030 transaction_a_->Start();
1031 }
1032
1033 void StartAAAA() {
1034 DCHECK(!transaction_aaaa_);
1035 DCHECK_NE(ADDRESS_FAMILY_IPV4, key_.address_family);
1036 transaction_aaaa_ = CreateTransaction(ADDRESS_FAMILY_IPV6);
1037 transaction_aaaa_->Start();
1038 }
1039
1040 scoped_ptr<DnsTransaction> CreateTransaction(AddressFamily family) {
1041 DCHECK_NE(ADDRESS_FAMILY_UNSPECIFIED, family);
1042 return client_->GetTransactionFactory()->CreateTransaction(
1043 key_.hostname,
1044 family == ADDRESS_FAMILY_IPV6 ? dns_protocol::kTypeAAAA :
1045 dns_protocol::kTypeA,
995 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), 1046 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this),
996 true /* first_query */, base::TimeTicks::Now()), 1047 base::TimeTicks::Now()),
997 net_log_); 1048 net_log_);
998 } 1049 }
999 1050
1000 void Start() { 1051 void OnTransactionComplete(const base::TimeTicks& start_time,
1001 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK);
1002 transaction_->Start();
1003 }
1004
1005 private:
1006 void OnTransactionComplete(bool first_query,
1007 const base::TimeTicks& start_time,
1008 DnsTransaction* transaction, 1052 DnsTransaction* transaction,
1009 int net_error, 1053 int net_error,
1010 const DnsResponse* response) { 1054 const DnsResponse* response) {
1011 DCHECK(transaction); 1055 DCHECK(transaction);
1012 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 1056 base::TimeDelta duration = base::TimeTicks::Now() - start_time;
1013 // Run |callback_| last since the owning Job will then delete this DnsTask.
1014 if (net_error != OK) { 1057 if (net_error != OK) {
1015 DNS_HISTOGRAM("AsyncDNS.TransactionFailure", duration); 1058 DNS_HISTOGRAM("AsyncDNS.TransactionFailure", duration);
1016 OnFailure(net_error, DnsResponse::DNS_PARSE_OK); 1059 OnFailure(net_error, DnsResponse::DNS_PARSE_OK);
1017 return; 1060 return;
1018 } 1061 }
1019 1062
1020 CHECK(response);
1021 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", duration); 1063 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", duration);
1022 switch (transaction->GetType()) { 1064 switch (transaction->GetType()) {
1023 case dns_protocol::kTypeA: 1065 case dns_protocol::kTypeA:
1024 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_A", duration); 1066 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_A", duration);
1025 break; 1067 break;
1026 case dns_protocol::kTypeAAAA: 1068 case dns_protocol::kTypeAAAA:
1027 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_AAAA", duration); 1069 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_AAAA", duration);
1028 break; 1070 break;
1029 } 1071 }
1072
1030 AddressList addr_list; 1073 AddressList addr_list;
1031 base::TimeDelta ttl; 1074 base::TimeDelta ttl;
1032 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); 1075 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl);
1033 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", 1076 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList",
1034 result, 1077 result,
1035 DnsResponse::DNS_PARSE_RESULT_MAX); 1078 DnsResponse::DNS_PARSE_RESULT_MAX);
1036 if (result != DnsResponse::DNS_PARSE_OK) { 1079 if (result != DnsResponse::DNS_PARSE_OK) {
1037 // Fail even if the other query succeeds. 1080 // Fail even if the other query succeeds.
1038 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result); 1081 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result);
1039 return; 1082 return;
1040 } 1083 }
1041 1084
1042 bool needs_sort = false; 1085 ++num_completed_transactions_;
1043 if (first_query) { 1086 if (num_completed_transactions_ == 1) {
1044 DCHECK(client_->GetConfig()) << 1087 ttl_ = ttl;
1045 "Transaction should have been aborted when config changed!";
1046 if (family_ == ADDRESS_FAMILY_IPV6) {
1047 needs_sort = (addr_list.size() > 1);
1048 } else if (family_ == ADDRESS_FAMILY_UNSPECIFIED) {
1049 first_addr_list_ = addr_list;
1050 first_ttl_ = ttl;
1051 // Use fully-qualified domain name to avoid search.
1052 transaction_ = client_->GetTransactionFactory()->CreateTransaction(
1053 response->GetDottedName() + ".",
1054 dns_protocol::kTypeAAAA,
1055 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this),
1056 false /* first_query */, base::TimeTicks::Now()),
1057 net_log_);
1058 transaction_->Start();
1059 return;
1060 }
1061 } else { 1088 } else {
1062 DCHECK_EQ(ADDRESS_FAMILY_UNSPECIFIED, family_); 1089 ttl_ = std::min(ttl_, ttl);
1063 bool has_ipv6_addresses = !addr_list.empty();
1064 if (!first_addr_list_.empty()) {
1065 ttl = std::min(ttl, first_ttl_);
1066 // Place IPv4 addresses after IPv6.
1067 addr_list.insert(addr_list.end(), first_addr_list_.begin(),
1068 first_addr_list_.end());
1069 }
1070 needs_sort = (has_ipv6_addresses && addr_list.size() > 1);
1071 } 1090 }
1072 1091
1073 if (addr_list.empty()) { 1092 if (transaction->GetType() == dns_protocol::kTypeA) {
1093 DCHECK_EQ(transaction_a_.get(), transaction);
1094 // Place IPv4 addresses after IPv6.
1095 addr_list_.insert(addr_list_.end(), addr_list.begin(), addr_list.end());
1096 } else {
1097 DCHECK_EQ(transaction_aaaa_.get(), transaction);
1098 // Place IPv6 addresses before IPv4.
1099 addr_list_.insert(addr_list_.begin(), addr_list.begin(), addr_list.end());
1100 }
1101
1102 if (needs_two_transactions() && num_completed_transactions_ == 1) {
1103 // No need to repeat the suffix search.
1104 key_.hostname = transaction->GetHostname();
1105 delegate_->OnFirstDnsTransactionComplete();
1106 return;
1107 }
1108
1109 if (addr_list_.empty()) {
1074 // TODO(szym): Don't fallback to ProcTask in this case. 1110 // TODO(szym): Don't fallback to ProcTask in this case.
1075 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); 1111 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
1076 return; 1112 return;
1077 } 1113 }
1078 1114
1079 if (needs_sort) { 1115 // If there are multiple addresses, and at least one is IPv6, need to sort
1080 // Sort could complete synchronously. 1116 // them. Note that IPv6 addresses are always put before IPv4 ones, so it's
1117 // sufficient to just check the family of the first address.
1118 if (addr_list_.size() > 1 &&
1119 addr_list_[0].GetFamily() == ADDRESS_FAMILY_IPV6) {
1120 // Sort addresses if needed. Sort could complete synchronously.
1081 client_->GetAddressSorter()->Sort( 1121 client_->GetAddressSorter()->Sort(
1082 addr_list, 1122 addr_list_,
1083 base::Bind(&DnsTask::OnSortComplete, 1123 base::Bind(&DnsTask::OnSortComplete,
1084 AsWeakPtr(), 1124 AsWeakPtr(),
1085 base::TimeTicks::Now(), 1125 base::TimeTicks::Now()));
1086 ttl));
1087 } else { 1126 } else {
1088 OnSuccess(addr_list, ttl); 1127 OnSuccess(addr_list_);
1089 } 1128 }
1090 } 1129 }
1091 1130
1092 void OnSortComplete(base::TimeTicks start_time, 1131 void OnSortComplete(base::TimeTicks start_time,
1093 base::TimeDelta ttl,
1094 bool success, 1132 bool success,
1095 const AddressList& addr_list) { 1133 const AddressList& addr_list) {
1096 if (!success) { 1134 if (!success) {
1097 DNS_HISTOGRAM("AsyncDNS.SortFailure", 1135 DNS_HISTOGRAM("AsyncDNS.SortFailure",
1098 base::TimeTicks::Now() - start_time); 1136 base::TimeTicks::Now() - start_time);
1099 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK); 1137 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK);
1100 return; 1138 return;
1101 } 1139 }
1102 1140
1103 DNS_HISTOGRAM("AsyncDNS.SortSuccess", 1141 DNS_HISTOGRAM("AsyncDNS.SortSuccess",
1104 base::TimeTicks::Now() - start_time); 1142 base::TimeTicks::Now() - start_time);
1105 1143
1106 // AddressSorter prunes unusable destinations. 1144 // AddressSorter prunes unusable destinations.
1107 if (addr_list.empty()) { 1145 if (addr_list.empty()) {
1108 LOG(WARNING) << "Address list empty after RFC3484 sort"; 1146 LOG(WARNING) << "Address list empty after RFC3484 sort";
1109 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); 1147 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
1110 return; 1148 return;
1111 } 1149 }
1112 1150
1113 OnSuccess(addr_list, ttl); 1151 OnSuccess(addr_list);
1114 } 1152 }
1115 1153
1116 void OnFailure(int net_error, DnsResponse::Result result) { 1154 void OnFailure(int net_error, DnsResponse::Result result) {
1117 DCHECK_NE(OK, net_error); 1155 DCHECK_NE(OK, net_error);
1118 net_log_.EndEvent( 1156 net_log_.EndEvent(
1119 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1157 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1120 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); 1158 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result));
1121 callback_.Run(net_error, AddressList(), base::TimeDelta()); 1159 delegate_->OnDnsTaskComplete(task_start_time_, net_error, AddressList(),
1160 base::TimeDelta());
1122 } 1161 }
1123 1162
1124 void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) { 1163 void OnSuccess(const AddressList& addr_list) {
1125 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1164 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1126 addr_list.CreateNetLogCallback()); 1165 addr_list.CreateNetLogCallback());
1127 callback_.Run(OK, addr_list, ttl); 1166 delegate_->OnDnsTaskComplete(task_start_time_, OK, addr_list, ttl_);
1128 } 1167 }
1129 1168
1130 DnsClient* client_; 1169 DnsClient* client_;
1131 AddressFamily family_; 1170 Key key_;
1171
1132 // The listener to the results of this DnsTask. 1172 // The listener to the results of this DnsTask.
1133 Callback callback_; 1173 Delegate* delegate_;
1134 const BoundNetLog net_log_; 1174 const BoundNetLog net_log_;
1135 1175
1136 scoped_ptr<DnsTransaction> transaction_; 1176 scoped_ptr<DnsTransaction> transaction_a_;
1177 scoped_ptr<DnsTransaction> transaction_aaaa_;
1137 1178
1138 // Results from the first transaction. Used only if |family_| is unspecified. 1179 unsigned num_completed_transactions_;
1139 AddressList first_addr_list_; 1180
1140 base::TimeDelta first_ttl_; 1181 // These are updated as each transaction completes.
1182 base::TimeDelta ttl_;
1183 // IPv6 addresses must appear first in the list.
1184 AddressList addr_list_;
1185
1186 base::TimeTicks task_start_time_;
1141 1187
1142 DISALLOW_COPY_AND_ASSIGN(DnsTask); 1188 DISALLOW_COPY_AND_ASSIGN(DnsTask);
1143 }; 1189 };
1144 1190
1145 //----------------------------------------------------------------------------- 1191 //-----------------------------------------------------------------------------
1146 1192
1147 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. 1193 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch.
1148 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { 1194 class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
1195 public HostResolverImpl::DnsTask::Delegate {
1149 public: 1196 public:
1150 // Creates new job for |key| where |request_net_log| is bound to the 1197 // Creates new job for |key| where |request_net_log| is bound to the
1151 // request that spawned it. 1198 // request that spawned it.
1152 Job(const base::WeakPtr<HostResolverImpl>& resolver, 1199 Job(const base::WeakPtr<HostResolverImpl>& resolver,
1153 const Key& key, 1200 const Key& key,
1154 RequestPriority priority, 1201 RequestPriority priority,
1155 const BoundNetLog& request_net_log) 1202 const BoundNetLog& request_net_log)
1156 : resolver_(resolver), 1203 : resolver_(resolver),
1157 key_(key), 1204 key_(key),
1158 priority_tracker_(priority), 1205 priority_tracker_(priority),
1159 had_non_speculative_request_(false), 1206 had_non_speculative_request_(false),
1160 had_dns_config_(false), 1207 had_dns_config_(false),
1208 num_occupied_job_slots_(0),
1161 dns_task_error_(OK), 1209 dns_task_error_(OK),
1162 creation_time_(base::TimeTicks::Now()), 1210 creation_time_(base::TimeTicks::Now()),
1163 priority_change_time_(creation_time_), 1211 priority_change_time_(creation_time_),
1164 net_log_(BoundNetLog::Make(request_net_log.net_log(), 1212 net_log_(BoundNetLog::Make(request_net_log.net_log(),
1165 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { 1213 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) {
1166 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB); 1214 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB);
1167 1215
1168 net_log_.BeginEvent( 1216 net_log_.BeginEvent(
1169 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1217 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
1170 base::Bind(&NetLogJobCreationCallback, 1218 base::Bind(&NetLogJobCreationCallback,
1171 request_net_log.source(), 1219 request_net_log.source(),
1172 &key_.hostname)); 1220 &key_.hostname));
1173 } 1221 }
1174 1222
1175 virtual ~Job() { 1223 virtual ~Job() {
1176 if (is_running()) { 1224 if (is_running()) {
1177 // |resolver_| was destroyed with this Job still in flight. 1225 // |resolver_| was destroyed with this Job still in flight.
1178 // Clean-up, record in the log, but don't run any callbacks. 1226 // Clean-up, record in the log, but don't run any callbacks.
1179 if (is_proc_running()) { 1227 if (is_proc_running()) {
1180 proc_task_->Cancel(); 1228 proc_task_->Cancel();
1181 proc_task_ = NULL; 1229 proc_task_ = NULL;
1182 } 1230 }
1183 // Clean up now for nice NetLog. 1231 // Clean up now for nice NetLog.
1184 dns_task_.reset(NULL); 1232 KillDnsTask();
1185 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1233 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
1186 ERR_ABORTED); 1234 ERR_ABORTED);
1187 } else if (is_queued()) { 1235 } else if (is_queued()) {
1188 // |resolver_| was destroyed without running this Job. 1236 // |resolver_| was destroyed without running this Job.
1189 // TODO(szym): is there any benefit in having this distinction? 1237 // TODO(szym): is there any benefit in having this distinction?
1190 net_log_.AddEvent(NetLog::TYPE_CANCELLED); 1238 net_log_.AddEvent(NetLog::TYPE_CANCELLED);
1191 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB); 1239 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB);
1192 } 1240 }
1193 // else CompleteRequests logged EndEvent. 1241 // else CompleteRequests logged EndEvent.
1194 1242
1195 // Log any remaining Requests as cancelled. 1243 // Log any remaining Requests as cancelled.
1196 for (RequestsList::const_iterator it = requests_.begin(); 1244 for (RequestsList::const_iterator it = requests_.begin();
1197 it != requests_.end(); ++it) { 1245 it != requests_.end(); ++it) {
1198 Request* req = *it; 1246 Request* req = *it;
1199 if (req->was_canceled()) 1247 if (req->was_canceled())
1200 continue; 1248 continue;
1201 DCHECK_EQ(this, req->job()); 1249 DCHECK_EQ(this, req->job());
1202 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1250 LogCancelRequest(req->source_net_log(), req->request_net_log(),
1203 req->info()); 1251 req->info());
1204 } 1252 }
1205 } 1253 }
1206 1254
1207 // Add this job to the dispatcher. 1255 // Add this job to the dispatcher. If "at_head" is true, adds at the front
1208 void Schedule() { 1256 // of the queue.
1209 handle_ = resolver_->dispatcher_.Add(this, priority()); 1257 void Schedule(bool at_head) {
1258 DCHECK(!is_queued());
1259 PrioritizedDispatcher::Handle handle;
1260 if (!at_head) {
1261 handle = resolver_->dispatcher_.Add(this, priority());
1262 } else {
1263 handle = resolver_->dispatcher_.AddAtHead(this, priority());
1264 }
1265 // The dispatcher could have started |this| in the above call to Add, which
1266 // could have called Schedule again. In that case |handle| will be null,
1267 // but |handle_| may have been set by the other nested call to Schedule.
1268 if (!handle.is_null()) {
1269 DCHECK(handle_.is_null());
1270 handle_ = handle;
1271 }
1210 } 1272 }
1211 1273
1212 void AddRequest(scoped_ptr<Request> req) { 1274 void AddRequest(scoped_ptr<Request> req) {
1213 DCHECK_EQ(key_.hostname, req->info().hostname()); 1275 DCHECK_EQ(key_.hostname, req->info().hostname());
1214 1276
1215 req->set_job(this); 1277 req->set_job(this);
1216 priority_tracker_.Add(req->priority()); 1278 priority_tracker_.Add(req->priority());
1217 1279
1218 req->request_net_log().AddEvent( 1280 req->request_net_log().AddEvent(
1219 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, 1281 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 // Called from AbortAllInProgressJobs. Completes all requests and destroys 1329 // Called from AbortAllInProgressJobs. Completes all requests and destroys
1268 // the job. This currently assumes the abort is due to a network change. 1330 // the job. This currently assumes the abort is due to a network change.
1269 void Abort() { 1331 void Abort() {
1270 DCHECK(is_running()); 1332 DCHECK(is_running());
1271 CompleteRequestsWithError(ERR_NETWORK_CHANGED); 1333 CompleteRequestsWithError(ERR_NETWORK_CHANGED);
1272 } 1334 }
1273 1335
1274 // If DnsTask present, abort it and fall back to ProcTask. 1336 // If DnsTask present, abort it and fall back to ProcTask.
1275 void AbortDnsTask() { 1337 void AbortDnsTask() {
1276 if (dns_task_) { 1338 if (dns_task_) {
1277 dns_task_.reset(); 1339 KillDnsTask();
1278 dns_task_error_ = OK; 1340 dns_task_error_ = OK;
1279 StartProcTask(); 1341 StartProcTask();
1280 } 1342 }
1281 } 1343 }
1282 1344
1283 // Called by HostResolverImpl when this job is evicted due to queue overflow. 1345 // Called by HostResolverImpl when this job is evicted due to queue overflow.
1284 // Completes all requests and destroys the job. 1346 // Completes all requests and destroys the job.
1285 void OnEvicted() { 1347 void OnEvicted() {
1286 DCHECK(!is_running()); 1348 DCHECK(!is_running());
1287 DCHECK(is_queued()); 1349 DCHECK(is_queued());
(...skipping 28 matching lines...) Expand all
1316 1378
1317 bool is_queued() const { 1379 bool is_queued() const {
1318 return !handle_.is_null(); 1380 return !handle_.is_null();
1319 } 1381 }
1320 1382
1321 bool is_running() const { 1383 bool is_running() const {
1322 return is_dns_running() || is_proc_running(); 1384 return is_dns_running() || is_proc_running();
1323 } 1385 }
1324 1386
1325 private: 1387 private:
1388 void KillDnsTask() {
1389 if (dns_task_) {
1390 ReduceToOneJobSlot();
1391 dns_task_.reset();
1392 }
1393 }
1394
1395 // Reduce the number of job slots occupied and queued in the dispatcher
1396 // to one. If the second Job slot is queued in the dispatcher, cancels the
1397 // queued job. Otherwise, the second Job has been started by the
1398 // PrioritizedDispatcher, so signals it is complete.
1399 void ReduceToOneJobSlot() {
1400 DCHECK_GE(num_occupied_job_slots_, 1u);
1401 if (is_queued()) {
1402 resolver_->dispatcher_.Cancel(handle_);
1403 handle_.Reset();
1404 } else if (num_occupied_job_slots_ > 1) {
1405 resolver_->dispatcher_.OnJobFinished();
1406 --num_occupied_job_slots_;
1407 }
1408 DCHECK_EQ(1u, num_occupied_job_slots_);
1409 }
1410
1326 void UpdatePriority() { 1411 void UpdatePriority() {
1327 if (is_queued()) { 1412 if (is_queued()) {
1328 if (priority() != static_cast<RequestPriority>(handle_.priority())) 1413 if (priority() != static_cast<RequestPriority>(handle_.priority()))
1329 priority_change_time_ = base::TimeTicks::Now(); 1414 priority_change_time_ = base::TimeTicks::Now();
1330 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); 1415 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority());
1331 } 1416 }
1332 } 1417 }
1333 1418
1334 AddressList MakeAddressListForRequest(const AddressList& list) const { 1419 AddressList MakeAddressListForRequest(const AddressList& list) const {
1335 if (requests_.empty()) 1420 if (requests_.empty())
1336 return list; 1421 return list;
1337 return AddressList::CopyWithPort(list, requests_.front()->info().port()); 1422 return AddressList::CopyWithPort(list, requests_.front()->info().port());
1338 } 1423 }
1339 1424
1340 // PriorityDispatch::Job: 1425 // PriorityDispatch::Job:
1341 virtual void Start() OVERRIDE { 1426 virtual void Start() OVERRIDE {
1427 DCHECK_LE(num_occupied_job_slots_, 1u);
1428
1429 handle_.Reset();
1430 ++num_occupied_job_slots_;
1431
1432 if (num_occupied_job_slots_ == 2) {
1433 StartSecondDnsTransaction();
1434 return;
1435 }
1436
1342 DCHECK(!is_running()); 1437 DCHECK(!is_running());
1343 handle_.Reset();
1344 1438
1345 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED); 1439 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED);
1346 1440
1347 had_dns_config_ = resolver_->HaveDnsConfig(); 1441 had_dns_config_ = resolver_->HaveDnsConfig();
1348 1442
1349 base::TimeTicks now = base::TimeTicks::Now(); 1443 base::TimeTicks now = base::TimeTicks::Now();
1350 base::TimeDelta queue_time = now - creation_time_; 1444 base::TimeDelta queue_time = now - creation_time_;
1351 base::TimeDelta queue_time_after_change = now - priority_change_time_; 1445 base::TimeDelta queue_time_after_change = now - priority_change_time_;
1352 1446
1353 if (had_dns_config_) { 1447 if (had_dns_config_) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); 1531 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
1438 1532
1439 // Don't store the |ttl| in cache since it's not obtained from the server. 1533 // Don't store the |ttl| in cache since it's not obtained from the server.
1440 CompleteRequests( 1534 CompleteRequests(
1441 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)), 1535 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)),
1442 ttl); 1536 ttl);
1443 } 1537 }
1444 1538
1445 void StartDnsTask() { 1539 void StartDnsTask() {
1446 DCHECK(resolver_->HaveDnsConfig()); 1540 DCHECK(resolver_->HaveDnsConfig());
1447 base::TimeTicks start_time = base::TimeTicks::Now(); 1541 dns_task_.reset(new DnsTask(resolver_->dns_client_.get(), key_, this,
1448 dns_task_.reset(new DnsTask( 1542 net_log_));
1449 resolver_->dns_client_.get(),
1450 key_,
1451 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this), start_time),
1452 net_log_));
1453 1543
1454 dns_task_->Start(); 1544 dns_task_->StartFirstTransaction();
1545 // Schedule a second transaction, if needed.
1546 if (dns_task_->needs_two_transactions())
1547 Schedule(true);
1548 }
1549
1550 void StartSecondDnsTransaction() {
1551 DCHECK(dns_task_->needs_two_transactions());
1552 dns_task_->StartSecondTransaction();
1455 } 1553 }
1456 1554
1457 // Called if DnsTask fails. It is posted from StartDnsTask, so Job may be 1555 // Called if DnsTask fails. It is posted from StartDnsTask, so Job may be
1458 // deleted before this callback. In this case dns_task is deleted as well, 1556 // deleted before this callback. In this case dns_task is deleted as well,
1459 // so we use it as indicator whether Job is still valid. 1557 // so we use it as indicator whether Job is still valid.
1460 void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task, 1558 void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
1461 base::TimeDelta duration, 1559 base::TimeDelta duration,
1462 int net_error) { 1560 int net_error) {
1463 DNS_HISTOGRAM("AsyncDNS.ResolveFail", duration); 1561 DNS_HISTOGRAM("AsyncDNS.ResolveFail", duration);
1464 1562
1465 if (dns_task == NULL) 1563 if (dns_task == NULL)
1466 return; 1564 return;
1467 1565
1468 dns_task_error_ = net_error; 1566 dns_task_error_ = net_error;
1469 1567
1470 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. 1568 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so.
1471 // http://crbug.com/117655 1569 // http://crbug.com/117655
1472 1570
1473 // TODO(szym): Some net errors indicate lack of connectivity. Starting 1571 // TODO(szym): Some net errors indicate lack of connectivity. Starting
1474 // ProcTask in that case is a waste of time. 1572 // ProcTask in that case is a waste of time.
1475 if (resolver_->fallback_to_proctask_) { 1573 if (resolver_->fallback_to_proctask_) {
1476 dns_task_.reset(); 1574 KillDnsTask();
1477 StartProcTask(); 1575 StartProcTask();
1478 } else { 1576 } else {
1479 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); 1577 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
1480 CompleteRequestsWithError(net_error); 1578 CompleteRequestsWithError(net_error);
1481 } 1579 }
1482 } 1580 }
1483 1581
1484 // Called by DnsTask when it completes. 1582
1485 void OnDnsTaskComplete(base::TimeTicks start_time, 1583 // HostResolverImpl::DnsTask::Delegate implementation:
1486 int net_error, 1584
1487 const AddressList& addr_list, 1585 virtual void OnDnsTaskComplete(base::TimeTicks start_time,
1488 base::TimeDelta ttl) { 1586 int net_error,
1587 const AddressList& addr_list,
1588 base::TimeDelta ttl) OVERRIDE {
1489 DCHECK(is_dns_running()); 1589 DCHECK(is_dns_running());
1490 1590
1491 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 1591 base::TimeDelta duration = base::TimeTicks::Now() - start_time;
1492 if (net_error != OK) { 1592 if (net_error != OK) {
1493 OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error); 1593 OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error);
1494 return; 1594 return;
1495 } 1595 }
1496 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess", duration); 1596 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess", duration);
1497 // Log DNS lookups based on |address_family|. 1597 // Log DNS lookups based on |address_family|.
1498 switch(key_.address_family) { 1598 switch(key_.address_family) {
(...skipping 14 matching lines...) Expand all
1513 resolver_->OnDnsTaskResolve(OK); 1613 resolver_->OnDnsTaskResolve(OK);
1514 1614
1515 base::TimeDelta bounded_ttl = 1615 base::TimeDelta bounded_ttl =
1516 std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds)); 1616 std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
1517 1617
1518 CompleteRequests( 1618 CompleteRequests(
1519 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl), 1619 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl),
1520 bounded_ttl); 1620 bounded_ttl);
1521 } 1621 }
1522 1622
1623 virtual void OnFirstDnsTransactionComplete() OVERRIDE {
1624 DCHECK(dns_task_->needs_two_transactions());
1625 DCHECK_EQ(dns_task_->needs_another_transaction(), is_queued());
1626 // No longer need to occupy two dispatcher slots.
1627 ReduceToOneJobSlot();
1628
1629 // We already have a job slot at the dispatcher, so if the second
1630 // transaction hasn't started, reuse it now instead of waiting in the queue
1631 // for the second slot.
1632 if (dns_task_->needs_another_transaction())
1633 dns_task_->StartSecondTransaction();
1634 }
1635
1523 // Performs Job's last rites. Completes all Requests. Deletes this. 1636 // Performs Job's last rites. Completes all Requests. Deletes this.
1524 void CompleteRequests(const HostCache::Entry& entry, 1637 void CompleteRequests(const HostCache::Entry& entry,
1525 base::TimeDelta ttl) { 1638 base::TimeDelta ttl) {
1526 CHECK(resolver_.get()); 1639 CHECK(resolver_.get());
1527 1640
1528 // This job must be removed from resolver's |jobs_| now to make room for a 1641 // This job must be removed from resolver's |jobs_| now to make room for a
1529 // new job with the same key in case one of the OnComplete callbacks decides 1642 // new job with the same key in case one of the OnComplete callbacks decides
1530 // to spawn one. Consequently, the job deletes itself when CompleteRequests 1643 // to spawn one. Consequently, the job deletes itself when CompleteRequests
1531 // is done. 1644 // is done.
1532 scoped_ptr<Job> self_deleter(this); 1645 scoped_ptr<Job> self_deleter(this);
1533 1646
1534 resolver_->RemoveJob(this); 1647 resolver_->RemoveJob(this);
1535 1648
1536 if (is_running()) { 1649 if (is_running()) {
1537 DCHECK(!is_queued());
1538 if (is_proc_running()) { 1650 if (is_proc_running()) {
1651 DCHECK(!is_queued());
1539 proc_task_->Cancel(); 1652 proc_task_->Cancel();
1540 proc_task_ = NULL; 1653 proc_task_ = NULL;
1541 } 1654 }
1542 dns_task_.reset(); 1655 KillDnsTask();
1543 1656
1544 // Signal dispatcher that a slot has opened. 1657 // Signal dispatcher that a slot has opened.
1545 resolver_->dispatcher_.OnJobFinished(); 1658 resolver_->dispatcher_.OnJobFinished();
1546 } else if (is_queued()) { 1659 } else if (is_queued()) {
1547 resolver_->dispatcher_.Cancel(handle_); 1660 resolver_->dispatcher_.Cancel(handle_);
1548 handle_.Reset(); 1661 handle_.Reset();
1549 } 1662 }
1550 1663
1551 if (num_active_requests() == 0) { 1664 if (num_active_requests() == 0) {
1552 net_log_.AddEvent(NetLog::TYPE_CANCELLED); 1665 net_log_.AddEvent(NetLog::TYPE_CANCELLED);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1626 Key key_; 1739 Key key_;
1627 1740
1628 // Tracks the highest priority across |requests_|. 1741 // Tracks the highest priority across |requests_|.
1629 PriorityTracker priority_tracker_; 1742 PriorityTracker priority_tracker_;
1630 1743
1631 bool had_non_speculative_request_; 1744 bool had_non_speculative_request_;
1632 1745
1633 // Distinguishes measurements taken while DnsClient was fully configured. 1746 // Distinguishes measurements taken while DnsClient was fully configured.
1634 bool had_dns_config_; 1747 bool had_dns_config_;
1635 1748
1749 // Number of slots occupied by this Job in resolver's PrioritizedDispatcher.
1750 unsigned num_occupied_job_slots_;
1751
1636 // Result of DnsTask. 1752 // Result of DnsTask.
1637 int dns_task_error_; 1753 int dns_task_error_;
1638 1754
1639 const base::TimeTicks creation_time_; 1755 const base::TimeTicks creation_time_;
1640 base::TimeTicks priority_change_time_; 1756 base::TimeTicks priority_change_time_;
1641 1757
1642 BoundNetLog net_log_; 1758 BoundNetLog net_log_;
1643 1759
1644 // Resolves the host using a HostResolverProc. 1760 // Resolves the host using a HostResolverProc.
1645 scoped_refptr<ProcTask> proc_task_; 1761 scoped_refptr<ProcTask> proc_task_;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 { 1829 {
1714 DnsConfig dns_config; 1830 DnsConfig dns_config;
1715 NetworkChangeNotifier::GetDnsConfig(&dns_config); 1831 NetworkChangeNotifier::GetDnsConfig(&dns_config);
1716 received_dns_config_ = dns_config.IsValid(); 1832 received_dns_config_ = dns_config.IsValid();
1717 } 1833 }
1718 1834
1719 fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial(); 1835 fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial();
1720 } 1836 }
1721 1837
1722 HostResolverImpl::~HostResolverImpl() { 1838 HostResolverImpl::~HostResolverImpl() {
1723 // This will also cancel all outstanding requests. 1839 // Prevent the dispatcher from starting new jobs.
1840 dispatcher_.SetLimitsToZero();
1841 // It's now safe for Jobs to call KillDsnTask on destruction, because
1842 // OnJobComplete will not start any new jobs.
1724 STLDeleteValues(&jobs_); 1843 STLDeleteValues(&jobs_);
1725 1844
1726 NetworkChangeNotifier::RemoveIPAddressObserver(this); 1845 NetworkChangeNotifier::RemoveIPAddressObserver(this);
1727 NetworkChangeNotifier::RemoveDNSObserver(this); 1846 NetworkChangeNotifier::RemoveDNSObserver(this);
1728 } 1847 }
1729 1848
1730 void HostResolverImpl::SetMaxQueuedJobs(size_t value) { 1849 void HostResolverImpl::SetMaxQueuedJobs(size_t value) {
1731 DCHECK_EQ(0u, dispatcher_.num_queued_jobs()); 1850 DCHECK_EQ(0u, dispatcher_.num_queued_jobs());
1732 DCHECK_GT(value, 0u); 1851 DCHECK_GT(value, 0u);
1733 max_queued_jobs_ = value; 1852 max_queued_jobs_ = value;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1766 } 1885 }
1767 1886
1768 // Next we need to attach our request to a "job". This job is responsible for 1887 // Next we need to attach our request to a "job". This job is responsible for
1769 // calling "getaddrinfo(hostname)" on a worker thread. 1888 // calling "getaddrinfo(hostname)" on a worker thread.
1770 1889
1771 JobMap::iterator jobit = jobs_.find(key); 1890 JobMap::iterator jobit = jobs_.find(key);
1772 Job* job; 1891 Job* job;
1773 if (jobit == jobs_.end()) { 1892 if (jobit == jobs_.end()) {
1774 job = 1893 job =
1775 new Job(weak_ptr_factory_.GetWeakPtr(), key, priority, request_net_log); 1894 new Job(weak_ptr_factory_.GetWeakPtr(), key, priority, request_net_log);
1776 job->Schedule(); 1895 job->Schedule(false);
1777 1896
1778 // Check for queue overflow. 1897 // Check for queue overflow.
1779 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { 1898 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) {
1780 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); 1899 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest());
1781 DCHECK(evicted); 1900 DCHECK(evicted);
1782 evicted->OnEvicted(); // Deletes |evicted|. 1901 evicted->OnEvicted(); // Deletes |evicted|.
1783 if (evicted == job) { 1902 if (evicted == job) {
1784 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 1903 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
1785 LogFinishRequest(source_net_log, request_net_log, info, rv); 1904 LogFinishRequest(source_net_log, request_net_log, info, rv);
1786 return rv; 1905 return rv;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 Job* job = it->second; 2182 Job* job = it->second;
2064 if (job->is_running()) { 2183 if (job->is_running()) {
2065 jobs_to_abort.push_back(job); 2184 jobs_to_abort.push_back(job);
2066 jobs_.erase(it++); 2185 jobs_.erase(it++);
2067 } else { 2186 } else {
2068 DCHECK(job->is_queued()); 2187 DCHECK(job->is_queued());
2069 ++it; 2188 ++it;
2070 } 2189 }
2071 } 2190 }
2072 2191
2073 // Check if no dispatcher slots leaked out. 2192 // Pause the dispatcher so it won't start any new dispatcher jobs while
2074 DCHECK_EQ(dispatcher_.num_running_jobs(), jobs_to_abort.size()); 2193 // aborting the old ones. This is needed so that it won't start the second
2194 // DnsTransaction for a job in |jobs_to_abort| if the DnsConfig just became
2195 // invalid.
2196 PrioritizedDispatcher::Limits limits = dispatcher_.GetLimits();
2197 dispatcher_.SetLimits(
2198 PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
2075 2199
2076 // Life check to bail once |this| is deleted. 2200 // Life check to bail once |this| is deleted.
2077 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr(); 2201 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr();
2078 2202
2079 // Then Abort them. 2203 // Then Abort them.
2080 for (size_t i = 0; self.get() && i < jobs_to_abort.size(); ++i) { 2204 for (size_t i = 0; self.get() && i < jobs_to_abort.size(); ++i) {
2081 jobs_to_abort[i]->Abort(); 2205 jobs_to_abort[i]->Abort();
2082 jobs_to_abort[i] = NULL; 2206 jobs_to_abort[i] = NULL;
2083 } 2207 }
2208
2209 if (self)
2210 dispatcher_.SetLimits(limits);
2211 }
2212
2213 void HostResolverImpl::AbortDnsTasks() {
2214 // Pause the dispatcher so it won't start any new dispatcher jobs while
2215 // aborting the old ones. This is needed so that it won't start the second
2216 // DnsTransaction for a job if the DnsConfig just changed.
2217 PrioritizedDispatcher::Limits limits = dispatcher_.GetLimits();
2218 dispatcher_.SetLimits(
2219 PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
2220
2221 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
2222 it->second->AbortDnsTask();
2223 dispatcher_.SetLimits(limits);
2084 } 2224 }
2085 2225
2086 void HostResolverImpl::TryServingAllJobsFromHosts() { 2226 void HostResolverImpl::TryServingAllJobsFromHosts() {
2087 if (!HaveDnsConfig()) 2227 if (!HaveDnsConfig())
2088 return; 2228 return;
2089 2229
2090 // TODO(szym): Do not do this if nsswitch.conf instructs not to. 2230 // TODO(szym): Do not do this if nsswitch.conf instructs not to.
2091 // http://crbug.com/117655 2231 // http://crbug.com/117655
2092 2232
2093 // Life check to bail once |this| is deleted. 2233 // Life check to bail once |this| is deleted.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 2308
2169 void HostResolverImpl::OnDnsTaskResolve(int net_error) { 2309 void HostResolverImpl::OnDnsTaskResolve(int net_error) {
2170 DCHECK(dns_client_); 2310 DCHECK(dns_client_);
2171 if (net_error == OK) { 2311 if (net_error == OK) {
2172 num_dns_failures_ = 0; 2312 num_dns_failures_ = 0;
2173 return; 2313 return;
2174 } 2314 }
2175 ++num_dns_failures_; 2315 ++num_dns_failures_;
2176 if (num_dns_failures_ < kMaximumDnsFailures) 2316 if (num_dns_failures_ < kMaximumDnsFailures)
2177 return; 2317 return;
2178 // Disable DnsClient until the next DNS change. 2318
2179 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 2319 // Disable DnsClient until the next DNS change. Must be done before aborting
2180 it->second->AbortDnsTask(); 2320 // DnsTasks, since doing so may start new jobs.
2181 dns_client_->SetConfig(DnsConfig()); 2321 dns_client_->SetConfig(DnsConfig());
2322
2323 // Switch jobs with active DnsTasks over to using ProcTasks.
2324 AbortDnsTasks();
2325
2182 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false); 2326 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false);
2183 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.DnsClientDisabledReason", 2327 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.DnsClientDisabledReason",
2184 std::abs(net_error), 2328 std::abs(net_error),
2185 GetAllErrorCodesForUma()); 2329 GetAllErrorCodesForUma());
2186 } 2330 }
2187 2331
2188 void HostResolverImpl::SetDnsClient(scoped_ptr<DnsClient> dns_client) { 2332 void HostResolverImpl::SetDnsClient(scoped_ptr<DnsClient> dns_client) {
2189 if (HaveDnsConfig()) { 2333 // DnsClient and config must be updated before aborting DnsTasks, since doing
2190 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 2334 // so may start new jobs.
2191 it->second->AbortDnsTask(); 2335 dns_client_ = dns_client.Pass();
2336 if (dns_client_ && !dns_client_->GetConfig() &&
2337 num_dns_failures_ < kMaximumDnsFailures) {
2338 DnsConfig dns_config;
2339 NetworkChangeNotifier::GetDnsConfig(&dns_config);
2340 dns_client_->SetConfig(dns_config);
2341 num_dns_failures_ = 0;
2342 if (dns_client_->GetConfig())
2343 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true);
2192 } 2344 }
2193 dns_client_ = dns_client.Pass(); 2345
2194 if (!dns_client_ || dns_client_->GetConfig() || 2346 AbortDnsTasks();
2195 num_dns_failures_ >= kMaximumDnsFailures) {
2196 return;
2197 }
2198 DnsConfig dns_config;
2199 NetworkChangeNotifier::GetDnsConfig(&dns_config);
2200 dns_client_->SetConfig(dns_config);
2201 num_dns_failures_ = 0;
2202 if (dns_client_->GetConfig())
2203 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true);
2204 } 2347 }
2205 2348
2206 } // namespace net 2349 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/host_resolver_impl.h ('k') | net/dns/host_resolver_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698