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