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

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

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

Powered by Google App Engine
This is Rietveld 408576698