| 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |