Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/host_resolver_impl.h" | 5 #include "net/base/host_resolver_impl.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <Winsock2.h> | 8 #include <Winsock2.h> |
| 9 #elif defined(OS_POSIX) | 9 #elif defined(OS_POSIX) |
| 10 #include <netdb.h> | 10 #include <netdb.h> |
| 11 #endif | 11 #endif |
| 12 | 12 |
| 13 #include <cmath> | 13 #include <cmath> |
| 14 #include <deque> | 14 #include <utility> |
| 15 #include <vector> | 15 #include <vector> |
| 16 | 16 |
| 17 #include "base/basictypes.h" | 17 #include "base/basictypes.h" |
| 18 #include "base/bind.h" | 18 #include "base/bind.h" |
| 19 #include "base/bind_helpers.h" | 19 #include "base/bind_helpers.h" |
| 20 #include "base/callback.h" | |
| 20 #include "base/compiler_specific.h" | 21 #include "base/compiler_specific.h" |
| 21 #include "base/debug/debugger.h" | 22 #include "base/debug/debugger.h" |
| 22 #include "base/debug/stack_trace.h" | 23 #include "base/debug/stack_trace.h" |
| 23 #include "base/message_loop_proxy.h" | 24 #include "base/message_loop_proxy.h" |
| 24 #include "base/metrics/field_trial.h" | 25 #include "base/metrics/field_trial.h" |
| 25 #include "base/metrics/histogram.h" | 26 #include "base/metrics/histogram.h" |
| 26 #include "base/stl_util.h" | 27 #include "base/stl_util.h" |
| 27 #include "base/string_util.h" | 28 #include "base/string_util.h" |
| 28 #include "base/threading/worker_pool.h" | 29 #include "base/threading/worker_pool.h" |
| 29 #include "base/time.h" | 30 #include "base/time.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 43 #endif | 44 #endif |
| 44 | 45 |
| 45 namespace net { | 46 namespace net { |
| 46 | 47 |
| 47 namespace { | 48 namespace { |
| 48 | 49 |
| 49 // Limit the size of hostnames that will be resolved to combat issues in | 50 // Limit the size of hostnames that will be resolved to combat issues in |
| 50 // some platform's resolvers. | 51 // some platform's resolvers. |
| 51 const size_t kMaxHostLength = 4096; | 52 const size_t kMaxHostLength = 4096; |
| 52 | 53 |
| 54 // Maximum of 8 concurrent resolver threads (excluding retries). | |
| 55 // Some routers (or resolvers) appear to start to provide host-not-found if | |
| 56 // too many simultaneous resolutions are pending. This number needs to be | |
| 57 // further optimized, but 8 is what FF currently does. | |
| 58 static const size_t kDefaultMaxProcTasks = 8u; | |
| 59 | |
| 60 | |
| 53 // Helper to mutate the linked list contained by AddressList to the given | 61 // Helper to mutate the linked list contained by AddressList to the given |
| 54 // port. Note that in general this is dangerous since the AddressList's | 62 // port. Note that in general this is dangerous since the AddressList's |
| 55 // data might be shared (and you should use AddressList::SetPort). | 63 // data might be shared (and you should use AddressList::SetPort). |
| 56 // | 64 // |
| 57 // However since we allocated the AddressList ourselves we can safely | 65 // However since we allocated the AddressList ourselves we can safely |
| 58 // do this optimization and avoid reallocating the list. | 66 // do this optimization and avoid reallocating the list. |
| 59 void MutableSetPort(int port, AddressList* addrlist) { | 67 void MutableSetPort(int port, AddressList* addrlist) { |
| 60 struct addrinfo* mutable_head = | 68 struct addrinfo* mutable_head = |
| 61 const_cast<struct addrinfo*>(addrlist->head()); | 69 const_cast<struct addrinfo*>(addrlist->head()); |
| 62 SetPortForAllAddrinfos(mutable_head, port); | 70 SetPortForAllAddrinfos(mutable_head, port); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 | 127 |
| 120 // Ensure all errors are positive, as histogram only tracks positive values. | 128 // Ensure all errors are positive, as histogram only tracks positive values. |
| 121 for (size_t i = 0; i < arraysize(os_errors); ++i) { | 129 for (size_t i = 0; i < arraysize(os_errors); ++i) { |
| 122 os_errors[i] = std::abs(os_errors[i]); | 130 os_errors[i] = std::abs(os_errors[i]); |
| 123 } | 131 } |
| 124 | 132 |
| 125 return base::CustomHistogram::ArrayToCustomRanges(os_errors, | 133 return base::CustomHistogram::ArrayToCustomRanges(os_errors, |
| 126 arraysize(os_errors)); | 134 arraysize(os_errors)); |
| 127 } | 135 } |
| 128 | 136 |
| 129 } // anonymous namespace | 137 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. |
| 130 | 138 // TODO(szym): This should probably be declared in host_resolver_proc.h. |
| 131 // static | 139 class CallSystemHostResolverProc : public HostResolverProc { |
| 132 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | 140 public: |
| 133 size_t max_retry_attempts, | 141 CallSystemHostResolverProc() : HostResolverProc(NULL) {} |
| 134 NetLog* net_log) { | 142 virtual int Resolve(const std::string& hostname, |
| 135 // Maximum of 8 concurrent resolver threads. | 143 AddressFamily address_family, |
| 136 // Some routers (or resolvers) appear to start to provide host-not-found if | 144 HostResolverFlags host_resolver_flags, |
| 137 // too many simultaneous resolutions are pending. This number needs to be | 145 AddressList* addrlist, |
| 138 // further optimized, but 8 is what FF currently does. | 146 int* os_error) OVERRIDE { |
| 139 static const size_t kDefaultMaxJobs = 8u; | 147 return SystemHostResolverProc(hostname, |
| 140 | 148 address_family, |
| 141 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | 149 host_resolver_flags, |
| 142 max_concurrent_resolves = kDefaultMaxJobs; | 150 addrlist, |
| 143 | 151 os_error); |
| 144 HostResolverImpl* resolver = | |
| 145 new HostResolverImpl(NULL, HostCache::CreateDefaultCache(), | |
| 146 max_concurrent_resolves, max_retry_attempts, net_log); | |
| 147 | |
| 148 return resolver; | |
| 149 } | |
| 150 | |
| 151 static int ResolveAddrInfo(HostResolverProc* resolver_proc, | |
| 152 const std::string& host, | |
| 153 AddressFamily address_family, | |
| 154 HostResolverFlags host_resolver_flags, | |
| 155 AddressList* out, | |
| 156 int* os_error) { | |
| 157 if (resolver_proc) { | |
| 158 // Use the custom procedure. | |
| 159 return resolver_proc->Resolve(host, address_family, | |
| 160 host_resolver_flags, out, os_error); | |
| 161 } else { | |
| 162 // Use the system procedure (getaddrinfo). | |
| 163 return SystemHostResolverProc(host, address_family, | |
| 164 host_resolver_flags, out, os_error); | |
| 165 } | 152 } |
| 166 } | 153 }; |
| 167 | 154 |
| 168 // Extra parameters to attach to the NetLog when the resolve failed. | 155 // Extra parameters to attach to the NetLog when the resolve failed. |
| 169 class HostResolveFailedParams : public NetLog::EventParameters { | 156 class HostResolveFailedParams : public NetLog::EventParameters { |
| 170 public: | 157 public: |
| 171 HostResolveFailedParams(uint32 attempt_number, | 158 HostResolveFailedParams(uint32 attempt_number, |
| 172 int net_error, | 159 int net_error, |
| 173 int os_error) | 160 int os_error) |
| 174 : attempt_number_(attempt_number), | 161 : attempt_number_(attempt_number), |
| 175 net_error_(net_error), | 162 net_error_(net_error), |
| 176 os_error_(os_error) { | 163 os_error_(os_error) { |
| 177 } | 164 } |
| 178 | 165 |
| 179 virtual Value* ToValue() const { | 166 virtual Value* ToValue() const OVERRIDE { |
| 180 DictionaryValue* dict = new DictionaryValue(); | 167 DictionaryValue* dict = new DictionaryValue(); |
| 181 if (attempt_number_) | 168 if (attempt_number_) |
| 182 dict->SetInteger("attempt_number", attempt_number_); | 169 dict->SetInteger("attempt_number", attempt_number_); |
| 183 | 170 |
| 184 dict->SetInteger("net_error", net_error_); | 171 dict->SetInteger("net_error", net_error_); |
| 185 | 172 |
| 186 if (os_error_) { | 173 if (os_error_) { |
| 187 dict->SetInteger("os_error", os_error_); | 174 dict->SetInteger("os_error", os_error_); |
| 188 #if defined(OS_POSIX) | 175 #if defined(OS_POSIX) |
| 189 dict->SetString("os_error_string", gai_strerror(os_error_)); | 176 dict->SetString("os_error_string", gai_strerror(os_error_)); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 213 }; | 200 }; |
| 214 | 201 |
| 215 // Parameters representing the information in a RequestInfo object, along with | 202 // Parameters representing the information in a RequestInfo object, along with |
| 216 // the associated NetLog::Source. | 203 // the associated NetLog::Source. |
| 217 class RequestInfoParameters : public NetLog::EventParameters { | 204 class RequestInfoParameters : public NetLog::EventParameters { |
| 218 public: | 205 public: |
| 219 RequestInfoParameters(const HostResolver::RequestInfo& info, | 206 RequestInfoParameters(const HostResolver::RequestInfo& info, |
| 220 const NetLog::Source& source) | 207 const NetLog::Source& source) |
| 221 : info_(info), source_(source) {} | 208 : info_(info), source_(source) {} |
| 222 | 209 |
| 223 virtual Value* ToValue() const { | 210 virtual Value* ToValue() const OVERRIDE { |
| 224 DictionaryValue* dict = new DictionaryValue(); | 211 DictionaryValue* dict = new DictionaryValue(); |
| 225 dict->SetString("host", info_.host_port_pair().ToString()); | 212 dict->SetString("host", info_.host_port_pair().ToString()); |
| 226 dict->SetInteger("address_family", | 213 dict->SetInteger("address_family", |
| 227 static_cast<int>(info_.address_family())); | 214 static_cast<int>(info_.address_family())); |
| 228 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); | 215 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); |
| 229 dict->SetBoolean("is_speculative", info_.is_speculative()); | 216 dict->SetBoolean("is_speculative", info_.is_speculative()); |
| 230 dict->SetInteger("priority", info_.priority()); | 217 dict->SetInteger("priority", info_.priority()); |
| 231 | 218 |
| 232 if (source_.is_valid()) | 219 if (source_.is_valid()) |
| 233 dict->Set("source_dependency", source_.ToValue()); | 220 dict->Set("source_dependency", source_.ToValue()); |
| 234 | 221 |
| 235 return dict; | 222 return dict; |
| 236 } | 223 } |
| 237 | 224 |
| 238 private: | 225 private: |
| 239 const HostResolver::RequestInfo info_; | 226 const HostResolver::RequestInfo info_; |
| 240 const NetLog::Source source_; | 227 const NetLog::Source source_; |
| 241 }; | 228 }; |
| 242 | 229 |
| 243 // Parameters associated with the creation of a HostResolverImpl::Job. | 230 // Parameters associated with the creation of a HostResolverImpl::Job |
| 231 // or a HostResolverImpl::ProcTask. | |
| 244 class JobCreationParameters : public NetLog::EventParameters { | 232 class JobCreationParameters : public NetLog::EventParameters { |
| 245 public: | 233 public: |
| 246 JobCreationParameters(const std::string& host, const NetLog::Source& source) | 234 JobCreationParameters(const std::string& host, |
| 235 const NetLog::Source& source) | |
| 247 : host_(host), source_(source) {} | 236 : host_(host), source_(source) {} |
| 248 | 237 |
| 249 virtual Value* ToValue() const { | 238 virtual Value* ToValue() const OVERRIDE { |
| 250 DictionaryValue* dict = new DictionaryValue(); | 239 DictionaryValue* dict = new DictionaryValue(); |
| 251 dict->SetString("host", host_); | 240 dict->SetString("host", host_); |
| 252 dict->Set("source_dependency", source_.ToValue()); | 241 dict->Set("source_dependency", source_.ToValue()); |
| 253 return dict; | 242 return dict; |
| 254 } | 243 } |
| 255 | 244 |
| 256 private: | 245 private: |
| 257 const std::string host_; | 246 const std::string host_; |
| 258 const NetLog::Source source_; | 247 const NetLog::Source source_; |
| 259 }; | 248 }; |
| 260 | 249 |
| 250 // Parameters of the HOST_RESOLVER_IMPL_JOB_ATTACH/DETACH event. | |
| 251 class JobAttachParameters : public NetLog::EventParameters { | |
| 252 public: | |
| 253 JobAttachParameters(const NetLog::Source& source, | |
| 254 RequestPriority priority) | |
| 255 : source_(source), priority_(priority) {} | |
| 256 | |
| 257 virtual Value* ToValue() const OVERRIDE { | |
| 258 DictionaryValue* dict = new DictionaryValue(); | |
| 259 dict->Set("source_dependency", source_.ToValue()); | |
| 260 dict->SetInteger("priority", priority_); | |
| 261 return dict; | |
| 262 } | |
| 263 | |
| 264 private: | |
| 265 const NetLog::Source source_; | |
| 266 const RequestPriority priority_; | |
| 267 }; | |
| 268 | |
| 269 // The logging routines are defined here because some requests are resolved | |
| 270 // without a Request object. | |
| 271 | |
| 272 // Logs when a request has just been started. | |
| 273 void LogStartRequest(const BoundNetLog& source_net_log, | |
| 274 const BoundNetLog& request_net_log, | |
| 275 const HostResolver::RequestInfo& info) { | |
| 276 source_net_log.BeginEvent( | |
| 277 NetLog::TYPE_HOST_RESOLVER_IMPL, | |
| 278 make_scoped_refptr(new NetLogSourceParameter( | |
| 279 "source_dependency", request_net_log.source()))); | |
| 280 | |
| 281 request_net_log.BeginEvent( | |
| 282 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, | |
| 283 make_scoped_refptr(new RequestInfoParameters( | |
| 284 info, source_net_log.source()))); | |
| 285 } | |
| 286 | |
| 287 // Logs when a request has just completed (before its callback is run). | |
| 288 void LogFinishRequest(const BoundNetLog& source_net_log, | |
| 289 const BoundNetLog& request_net_log, | |
| 290 const HostResolver::RequestInfo& info, | |
| 291 int net_error, | |
| 292 int os_error) { | |
| 293 scoped_refptr<NetLog::EventParameters> params; | |
| 294 if (net_error != OK) { | |
| 295 params = new HostResolveFailedParams(0, net_error, os_error); | |
| 296 } | |
| 297 | |
| 298 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params); | |
| 299 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | |
| 300 } | |
| 301 | |
| 302 // Logs when a request has been cancelled. | |
| 303 void LogCancelRequest(const BoundNetLog& source_net_log, | |
| 304 const BoundNetLog& request_net_log, | |
| 305 const HostResolverImpl::RequestInfo& info) { | |
| 306 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 307 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | |
| 308 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | |
| 309 } | |
| 310 | |
| 311 //----------------------------------------------------------------------------- | |
| 312 | |
| 313 // Keeps track of the highest priority. | |
| 314 class PriorityTracker { | |
| 315 public: | |
| 316 PriorityTracker() | |
| 317 : highest_priority_(IDLE), total_count_(0) { | |
| 318 memset(counts_, 0, sizeof(counts_)); | |
| 319 } | |
| 320 | |
| 321 RequestPriority highest_priority() const { | |
| 322 return highest_priority_; | |
| 323 } | |
| 324 | |
| 325 size_t total_count() const { | |
| 326 return total_count_; | |
| 327 } | |
| 328 | |
| 329 void Add(RequestPriority req_priority) { | |
| 330 ++total_count_; | |
| 331 ++counts_[req_priority]; | |
| 332 if (highest_priority_ > req_priority) | |
| 333 highest_priority_ = req_priority; | |
| 334 } | |
| 335 | |
| 336 void Remove(RequestPriority req_priority) { | |
| 337 DCHECK_GT(total_count_, 0u); | |
| 338 DCHECK_GT(counts_[req_priority], 0u); | |
| 339 --total_count_; | |
| 340 --counts_[req_priority]; | |
| 341 size_t i; | |
| 342 for (i = highest_priority_; i < NUM_PRIORITIES && !counts_[i]; ++i); | |
| 343 highest_priority_ = static_cast<RequestPriority>(i); | |
| 344 | |
| 345 // In absence of requests set default. | |
| 346 if (highest_priority_ == NUM_PRIORITIES) { | |
| 347 DCHECK_EQ(0u, total_count_); | |
| 348 highest_priority_ = IDLE; | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 private: | |
| 353 RequestPriority highest_priority_; | |
| 354 size_t total_count_; | |
| 355 size_t counts_[NUM_PRIORITIES]; | |
| 356 }; | |
| 357 | |
| 261 //----------------------------------------------------------------------------- | 358 //----------------------------------------------------------------------------- |
| 262 | 359 |
| 360 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, | |
| 361 size_t max_retry_attempts, | |
| 362 bool use_cache, | |
| 363 NetLog* net_log) { | |
| 364 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | |
| 365 max_concurrent_resolves = kDefaultMaxProcTasks; | |
| 366 | |
| 367 // TODO(szym): Add experiments with reserved slots for higher priority | |
| 368 // requests. | |
| 369 | |
| 370 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); | |
| 371 | |
| 372 HostResolverImpl* resolver = new HostResolverImpl( | |
| 373 use_cache ? HostCache::CreateDefaultCache() : NULL, | |
| 374 limits, | |
| 375 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), | |
| 376 net_log); | |
| 377 | |
| 378 return resolver; | |
| 379 } | |
| 380 | |
| 381 } // anonymous namespace | |
| 382 | |
| 383 //----------------------------------------------------------------------------- | |
| 384 | |
| 385 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | |
| 386 size_t max_retry_attempts, | |
| 387 NetLog* net_log) { | |
| 388 return CreateHostResolver(max_concurrent_resolves, | |
| 389 max_retry_attempts, | |
| 390 true /* use_cache */, | |
| 391 net_log); | |
| 392 } | |
| 393 | |
| 394 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, | |
| 395 size_t max_retry_attempts, | |
| 396 NetLog* net_log) { | |
| 397 return CreateHostResolver(max_concurrent_resolves, | |
| 398 max_retry_attempts, | |
| 399 false /* use_cache */, | |
| 400 net_log); | |
| 401 } | |
| 402 | |
| 403 //----------------------------------------------------------------------------- | |
| 404 | |
| 405 // Holds the data for a request that could not be completed synchronously. | |
| 406 // It is owned by a Job. Canceled Requests are only marked as canceled rather | |
| 407 // than removed from the Job's |requests_| list. | |
| 263 class HostResolverImpl::Request { | 408 class HostResolverImpl::Request { |
| 264 public: | 409 public: |
| 265 Request(const BoundNetLog& source_net_log, | 410 Request(const BoundNetLog& source_net_log, |
| 266 const BoundNetLog& request_net_log, | 411 const BoundNetLog& request_net_log, |
| 267 const RequestInfo& info, | 412 const RequestInfo& info, |
| 268 const CompletionCallback& callback, | 413 const CompletionCallback& callback, |
| 269 AddressList* addresses) | 414 AddressList* addresses) |
| 270 : source_net_log_(source_net_log), | 415 : source_net_log_(source_net_log), |
| 271 request_net_log_(request_net_log), | 416 request_net_log_(request_net_log), |
| 272 info_(info), | 417 info_(info), |
| 273 job_(NULL), | 418 job_(NULL), |
| 274 callback_(callback), | 419 callback_(callback), |
| 275 addresses_(addresses) { | 420 addresses_(addresses) { |
| 276 } | 421 } |
| 277 | 422 |
| 278 // Mark the request as cancelled. | 423 // Mark the request as canceled. |
| 279 void MarkAsCancelled() { | 424 void MarkAsCanceled() { |
| 280 job_ = NULL; | 425 job_ = NULL; |
| 281 addresses_ = NULL; | 426 addresses_ = NULL; |
| 282 callback_.Reset(); | 427 callback_.Reset(); |
| 283 } | 428 } |
| 284 | 429 |
| 285 bool was_cancelled() const { | 430 bool was_canceled() const { |
| 286 return callback_.is_null(); | 431 return callback_.is_null(); |
| 287 } | 432 } |
| 288 | 433 |
| 289 void set_job(Job* job) { | 434 void set_job(Job* job) { |
| 290 DCHECK(job != NULL); | 435 DCHECK(job); |
| 291 // Identify which job the request is waiting on. | 436 // Identify which job the request is waiting on. |
| 292 job_ = job; | 437 job_ = job; |
| 293 } | 438 } |
| 294 | 439 |
| 440 // Prepare final AddressList and call completion callback. | |
| 295 void OnComplete(int error, const AddressList& addrlist) { | 441 void OnComplete(int error, const AddressList& addrlist) { |
| 296 if (error == OK) | 442 if (error == OK) |
| 297 *addresses_ = CreateAddressListUsingPort(addrlist, port()); | 443 *addresses_ = CreateAddressListUsingPort(addrlist, info_.port()); |
| 298 CompletionCallback callback = callback_; | 444 CompletionCallback callback = callback_; |
| 299 MarkAsCancelled(); | 445 MarkAsCanceled(); |
| 300 callback.Run(error); | 446 callback.Run(error); |
| 301 } | 447 } |
| 302 | 448 |
| 303 int port() const { | |
| 304 return info_.port(); | |
| 305 } | |
| 306 | |
| 307 Job* job() const { | 449 Job* job() const { |
| 308 return job_; | 450 return job_; |
| 309 } | 451 } |
| 310 | 452 |
| 453 // NetLog for the source, passed in HostResolver::Resolve. | |
| 311 const BoundNetLog& source_net_log() { | 454 const BoundNetLog& source_net_log() { |
| 312 return source_net_log_; | 455 return source_net_log_; |
| 313 } | 456 } |
| 314 | 457 |
| 458 // NetLog for this request. | |
| 315 const BoundNetLog& request_net_log() { | 459 const BoundNetLog& request_net_log() { |
| 316 return request_net_log_; | 460 return request_net_log_; |
| 317 } | 461 } |
| 318 | 462 |
| 319 const RequestInfo& info() const { | 463 const RequestInfo& info() const { |
| 320 return info_; | 464 return info_; |
| 321 } | 465 } |
| 322 | 466 |
| 323 private: | 467 private: |
| 324 BoundNetLog source_net_log_; | 468 BoundNetLog source_net_log_; |
| 325 BoundNetLog request_net_log_; | 469 BoundNetLog request_net_log_; |
| 326 | 470 |
| 327 // The request info that started the request. | 471 // The request info that started the request. |
| 328 RequestInfo info_; | 472 RequestInfo info_; |
| 329 | 473 |
| 330 // The resolve job (running in worker pool) that this request is dependent on. | 474 // The resolve job that this request is dependent on. |
| 331 Job* job_; | 475 Job* job_; |
| 332 | 476 |
| 333 // The user's callback to invoke when the request completes. | 477 // The user's callback to invoke when the request completes. |
| 334 CompletionCallback callback_; | 478 CompletionCallback callback_; |
| 335 | 479 |
| 336 // The address list to save result into. | 480 // The address list to save result into. |
| 337 AddressList* addresses_; | 481 AddressList* addresses_; |
| 338 | 482 |
| 339 DISALLOW_COPY_AND_ASSIGN(Request); | 483 DISALLOW_COPY_AND_ASSIGN(Request); |
| 340 }; | 484 }; |
| 341 | 485 |
| 342 //------------------------------------------------------------------------------ | 486 //------------------------------------------------------------------------------ |
| 343 | 487 |
| 344 // Provide a common macro to simplify code and readability. We must use a | 488 // Provide a common macro to simplify code and readability. We must use a |
| 345 // macros as the underlying HISTOGRAM macro creates static varibles. | 489 // macros as the underlying HISTOGRAM macro creates static varibles. |
| 346 #define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ | 490 #define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ |
| 347 base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromHours(1), 100) | 491 base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromHours(1), 100) |
| 348 | 492 |
| 349 // This class represents a request to the worker pool for a "getaddrinfo()" | 493 // Calls HostResolverProc on the WorkerPool. Performs retries if necessary. |
| 350 // call. | 494 // |
| 351 class HostResolverImpl::Job | 495 // Whenever we try to resolve the host, we post a delayed task to check if host |
| 352 : public base::RefCountedThreadSafe<HostResolverImpl::Job> { | 496 // resolution (OnLookupComplete) is completed or not. If the original attempt |
| 497 // hasn't completed, then we start another attempt for host resolution. We take | |
| 498 // the results from the first attempt that finishes and ignore the results from | |
| 499 // all other attempts. | |
| 500 // | |
| 501 // TODO(szym): Move to separate source file for testing and mocking. | |
| 502 // | |
| 503 class HostResolverImpl::ProcTask | |
| 504 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { | |
| 353 public: | 505 public: |
| 354 Job(int id, | 506 typedef base::Callback<void(int, int, const AddressList&)> Callback; |
| 355 HostResolverImpl* resolver, | |
| 356 const Key& key, | |
| 357 const BoundNetLog& source_net_log, | |
| 358 NetLog* net_log) | |
| 359 : id_(id), | |
| 360 key_(key), | |
| 361 resolver_(resolver), | |
| 362 origin_loop_(base::MessageLoopProxy::current()), | |
| 363 resolver_proc_(resolver->effective_resolver_proc()), | |
| 364 unresponsive_delay_(resolver->unresponsive_delay()), | |
| 365 attempt_number_(0), | |
| 366 completed_attempt_number_(0), | |
| 367 completed_attempt_error_(ERR_UNEXPECTED), | |
| 368 had_non_speculative_request_(false), | |
| 369 net_log_(BoundNetLog::Make(net_log, | |
| 370 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { | |
| 371 DCHECK(resolver); | |
| 372 net_log_.BeginEvent( | |
| 373 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | |
| 374 make_scoped_refptr( | |
| 375 new JobCreationParameters(key.hostname, source_net_log.source()))); | |
| 376 } | |
| 377 | 507 |
| 378 // Attaches a request to this job. The job takes ownership of |req| and will | 508 ProcTask(const Key& key, |
| 379 // take care to delete it. | 509 const ProcTaskParams& params, |
| 380 void AddRequest(Request* req) { | 510 const Callback& callback, |
| 381 DCHECK(origin_loop_->BelongsToCurrentThread()); | 511 const BoundNetLog& job_net_log) |
| 382 req->request_net_log().BeginEvent( | 512 : key_(key), |
| 383 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | 513 params_(params), |
| 384 make_scoped_refptr(new NetLogSourceParameter( | 514 callback_(callback), |
| 385 "source_dependency", net_log_.source()))); | 515 origin_loop_(base::MessageLoopProxy::current()), |
| 516 attempt_number_(0), | |
| 517 completed_attempt_number_(0), | |
| 518 completed_attempt_error_(ERR_UNEXPECTED), | |
| 519 had_non_speculative_request_(false), | |
| 520 net_log_(BoundNetLog::Make( | |
| 521 job_net_log.net_log(), | |
| 522 NetLog::SOURCE_HOST_RESOLVER_IMPL_PROC_TASK)) { | |
| 523 if (!params_.resolver_proc) | |
| 524 params_.resolver_proc = HostResolverProc::GetDefault(); | |
| 525 // If default is unset, use the system proc. | |
| 526 if (!params_.resolver_proc) | |
| 527 params_.resolver_proc = new CallSystemHostResolverProc(); | |
| 386 | 528 |
| 387 req->set_job(this); | 529 job_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_PROC_TASK, |
| 388 requests_.push_back(req); | 530 new NetLogSourceParameter("source_dependency", |
| 531 net_log_.source())); | |
| 389 | 532 |
| 390 if (!req->info().is_speculative()) | 533 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, |
| 391 had_non_speculative_request_ = true; | 534 new JobCreationParameters(key_.hostname, |
| 535 job_net_log.source())); | |
| 392 } | 536 } |
| 393 | 537 |
| 394 void Start() { | 538 void Start() { |
| 395 DCHECK(origin_loop_->BelongsToCurrentThread()); | 539 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 396 StartLookupAttempt(); | 540 StartLookupAttempt(); |
| 397 } | 541 } |
| 398 | 542 |
| 543 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve | |
| 544 // attempts running on worker threads will continue running. Only once all the | |
| 545 // attempts complete will the final reference to this ProcTask be released. | |
| 546 void Cancel() { | |
| 547 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 548 | |
| 549 if (was_canceled()) | |
| 550 return; | |
| 551 | |
| 552 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 553 | |
| 554 callback_.Reset(); | |
| 555 | |
| 556 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); | |
| 557 } | |
| 558 | |
| 559 void set_had_non_speculative_request() { | |
| 560 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 561 had_non_speculative_request_ = true; | |
| 562 } | |
| 563 | |
| 564 bool was_canceled() const { | |
| 565 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 566 return callback_.is_null(); | |
| 567 } | |
| 568 | |
| 569 bool was_completed() const { | |
| 570 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 571 return completed_attempt_number_ > 0; | |
| 572 } | |
| 573 | |
| 574 private: | |
| 399 void StartLookupAttempt() { | 575 void StartLookupAttempt() { |
| 400 DCHECK(origin_loop_->BelongsToCurrentThread()); | 576 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 401 base::TimeTicks start_time = base::TimeTicks::Now(); | 577 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 402 ++attempt_number_; | 578 ++attempt_number_; |
| 403 // Dispatch the lookup attempt to a worker thread. | 579 // Dispatch the lookup attempt to a worker thread. |
| 404 if (!base::WorkerPool::PostTask( | 580 if (!base::WorkerPool::PostTask( |
| 405 FROM_HERE, | 581 FROM_HERE, |
| 406 base::Bind(&Job::DoLookup, this, start_time, attempt_number_), | 582 base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), |
| 407 true)) { | 583 true)) { |
| 408 NOTREACHED(); | 584 NOTREACHED(); |
| 409 | 585 |
| 410 // Since we could be running within Resolve() right now, we can't just | 586 // Since we could be running within Resolve() right now, we can't just |
| 411 // call OnLookupComplete(). Instead we must wait until Resolve() has | 587 // call OnLookupComplete(). Instead we must wait until Resolve() has |
| 412 // returned (IO_PENDING). | 588 // returned (IO_PENDING). |
| 413 origin_loop_->PostTask( | 589 origin_loop_->PostTask( |
| 414 FROM_HERE, | 590 FROM_HERE, |
| 415 base::Bind(&Job::OnLookupComplete, this, AddressList(), | 591 base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), |
| 416 start_time, attempt_number_, ERR_UNEXPECTED, 0)); | 592 start_time, attempt_number_, ERR_UNEXPECTED, 0)); |
| 417 return; | 593 return; |
| 418 } | 594 } |
| 419 | 595 |
| 420 net_log_.AddEvent( | 596 net_log_.AddEvent( |
| 421 NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, | 597 NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, |
| 422 make_scoped_refptr(new NetLogIntegerParameter( | 598 make_scoped_refptr(new NetLogIntegerParameter( |
| 423 "attempt_number", attempt_number_))); | 599 "attempt_number", attempt_number_))); |
| 424 | 600 |
| 425 // Post a task to check if we get the results within a given time. | 601 // If we don't get the results within a given time, RetryIfNotComplete |
| 426 // OnCheckForComplete has the potential for starting a new attempt on a | 602 // will start a new attempt on a different worker thread if none of our |
| 427 // different worker thread if none of our outstanding attempts have | 603 // outstanding attempts have completed yet. |
| 428 // completed yet. | 604 if (attempt_number_ <= params_.max_retry_attempts) { |
| 429 if (attempt_number_ <= resolver_->max_retry_attempts()) { | |
| 430 origin_loop_->PostDelayedTask( | 605 origin_loop_->PostDelayedTask( |
| 431 FROM_HERE, | 606 FROM_HERE, |
| 432 base::Bind(&Job::OnCheckForComplete, this), | 607 base::Bind(&ProcTask::RetryIfNotComplete, this), |
| 433 unresponsive_delay_.InMilliseconds()); | 608 params_.unresponsive_delay.InMilliseconds()); |
| 434 } | 609 } |
| 435 } | 610 } |
| 436 | 611 |
| 437 // Cancels the current job. The Job will be orphaned. Any outstanding resolve | |
| 438 // attempts running on worker threads will continue running. Only once all the | |
| 439 // attempts complete will the final reference to this Job be released. | |
| 440 void Cancel() { | |
| 441 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 442 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 443 | |
| 444 HostResolver* resolver = resolver_; | |
| 445 resolver_ = NULL; | |
| 446 | |
| 447 // End here to prevent issues when a Job outlives the HostResolver that | |
| 448 // spawned it. | |
| 449 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL); | |
| 450 | |
| 451 // We will call HostResolverImpl::CancelRequest(Request*) on each one | |
| 452 // in order to notify any observers. | |
| 453 for (RequestsList::const_iterator it = requests_.begin(); | |
| 454 it != requests_.end(); ++it) { | |
| 455 HostResolverImpl::Request* req = *it; | |
| 456 if (!req->was_cancelled()) | |
| 457 resolver->CancelRequest(req); | |
| 458 } | |
| 459 } | |
| 460 | |
| 461 bool was_cancelled() const { | |
| 462 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 463 return resolver_ == NULL; | |
| 464 } | |
| 465 | |
| 466 bool was_completed() const { | |
| 467 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 468 return completed_attempt_number_ > 0; | |
| 469 } | |
| 470 | |
| 471 const Key& key() const { | |
| 472 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 473 return key_; | |
| 474 } | |
| 475 | |
| 476 int id() const { | |
| 477 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 478 return id_; | |
| 479 } | |
| 480 | |
| 481 const RequestsList& requests() const { | |
| 482 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 483 return requests_; | |
| 484 } | |
| 485 | |
| 486 // Returns the first request attached to the job. | |
| 487 const Request* initial_request() const { | |
| 488 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 489 DCHECK(!requests_.empty()); | |
| 490 return requests_[0]; | |
| 491 } | |
| 492 | |
| 493 // Returns true if |req_info| can be fulfilled by this job. | |
| 494 bool CanServiceRequest(const RequestInfo& req_info) const { | |
| 495 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 496 return key_ == resolver_->GetEffectiveKeyForRequest(req_info); | |
| 497 } | |
| 498 | |
| 499 private: | |
| 500 friend class base::RefCountedThreadSafe<HostResolverImpl::Job>; | |
| 501 | |
| 502 ~Job() { | |
| 503 // Free the requests attached to this job. | |
| 504 STLDeleteElements(&requests_); | |
| 505 } | |
| 506 | |
| 507 // WARNING: This code runs inside a worker pool. The shutdown code cannot | 612 // WARNING: This code runs inside a worker pool. The shutdown code cannot |
| 508 // wait for it to finish, so we must be very careful here about using other | 613 // wait for it to finish, so we must be very careful here about using other |
| 509 // objects (like MessageLoops, Singletons, etc). During shutdown these objects | 614 // objects (like MessageLoops, Singletons, etc). During shutdown these objects |
| 510 // may no longer exist. Multiple DoLookups() could be running in parallel, so | 615 // may no longer exist. Multiple DoLookups() could be running in parallel, so |
| 511 // any state inside of |this| must not mutate . | 616 // any state inside of |this| must not mutate . |
| 512 void DoLookup(const base::TimeTicks& start_time, | 617 void DoLookup(const base::TimeTicks& start_time, |
| 513 const uint32 attempt_number) { | 618 const uint32 attempt_number) { |
| 514 AddressList results; | 619 AddressList results; |
| 515 int os_error = 0; | 620 int os_error = 0; |
| 516 // Running on the worker thread | 621 // Running on the worker thread |
| 517 int error = ResolveAddrInfo(resolver_proc_, | 622 |
| 518 key_.hostname, | 623 int error = params_.resolver_proc->Resolve(key_.hostname, |
| 519 key_.address_family, | 624 key_.address_family, |
| 520 key_.host_resolver_flags, | 625 key_.host_resolver_flags, |
| 521 &results, | 626 &results, |
| 522 &os_error); | 627 &os_error); |
| 523 | 628 |
| 524 origin_loop_->PostTask( | 629 origin_loop_->PostTask( |
| 525 FROM_HERE, | 630 FROM_HERE, |
| 526 base::Bind(&Job::OnLookupComplete, this, results, start_time, | 631 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, |
| 527 attempt_number, error, os_error)); | 632 attempt_number, error, os_error)); |
| 528 } | 633 } |
| 529 | 634 |
| 530 // Callback to see if DoLookup() has finished or not (runs on origin thread). | 635 // Makes next attempt if DoLookup() has not finished (runs on origin thread). |
| 531 void OnCheckForComplete() { | 636 void RetryIfNotComplete() { |
| 532 DCHECK(origin_loop_->BelongsToCurrentThread()); | 637 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 533 | 638 |
| 534 if (was_completed() || was_cancelled()) | 639 if (was_completed() || was_canceled()) |
| 535 return; | 640 return; |
| 536 | 641 |
| 537 DCHECK(resolver_); | 642 params_.unresponsive_delay *= params_.retry_factor; |
| 538 unresponsive_delay_ *= resolver_->retry_factor(); | |
| 539 StartLookupAttempt(); | 643 StartLookupAttempt(); |
| 540 } | 644 } |
| 541 | 645 |
| 542 // Callback for when DoLookup() completes (runs on origin thread). | 646 // Callback for when DoLookup() completes (runs on origin thread). |
| 543 void OnLookupComplete(const AddressList& results, | 647 void OnLookupComplete(const AddressList& results, |
| 544 const base::TimeTicks& start_time, | 648 const base::TimeTicks& start_time, |
| 545 const uint32 attempt_number, | 649 const uint32 attempt_number, |
| 546 int error, | 650 int error, |
| 547 const int os_error) { | 651 const int os_error) { |
| 548 DCHECK(origin_loop_->BelongsToCurrentThread()); | 652 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 549 DCHECK(error || results.head()); | 653 DCHECK(error || results.head()); |
| 550 | 654 |
| 551 bool was_retry_attempt = attempt_number > 1; | 655 bool was_retry_attempt = attempt_number > 1; |
| 552 | 656 |
| 553 if (!was_cancelled()) { | |
|
szym
2012/02/01 17:23:51
This logic was a bit confusing. I think the new lo
| |
| 554 scoped_refptr<NetLog::EventParameters> params; | |
| 555 if (error != OK) { | |
| 556 params = new HostResolveFailedParams(attempt_number, error, os_error); | |
| 557 } else { | |
| 558 params = new NetLogIntegerParameter("attempt_number", attempt_number_); | |
| 559 } | |
| 560 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, | |
| 561 params); | |
| 562 | |
| 563 // If host is already resolved, then record data and return. | |
| 564 if (was_completed()) { | |
| 565 // If this is the first attempt that is finishing later, then record | |
| 566 // data for the first attempt. Won't contaminate with retry attempt's | |
| 567 // data. | |
| 568 if (!was_retry_attempt) | |
| 569 RecordPerformanceHistograms(start_time, error, os_error); | |
| 570 | |
| 571 RecordAttemptHistograms(start_time, attempt_number, error, os_error); | |
| 572 return; | |
| 573 } | |
| 574 | |
| 575 // Copy the results from the first worker thread that resolves the host. | |
| 576 results_ = results; | |
| 577 completed_attempt_number_ = attempt_number; | |
| 578 completed_attempt_error_ = error; | |
| 579 } | |
| 580 | |
| 581 // Ideally the following code would be part of host_resolver_proc.cc, | 657 // Ideally the following code would be part of host_resolver_proc.cc, |
| 582 // however it isn't safe to call NetworkChangeNotifier from worker | 658 // however it isn't safe to call NetworkChangeNotifier from worker |
| 583 // threads. So we do it here on the IO thread instead. | 659 // threads. So we do it here on the IO thread instead. |
| 584 if (error != OK && NetworkChangeNotifier::IsOffline()) | 660 if (error != OK && NetworkChangeNotifier::IsOffline()) |
| 585 error = ERR_INTERNET_DISCONNECTED; | 661 error = ERR_INTERNET_DISCONNECTED; |
| 586 | 662 |
| 587 // We will record data for the first attempt. Don't contaminate with retry | 663 // If this is the first attempt that is finishing later, then record |
| 588 // attempt's data. | 664 // data for the first attempt. Won't contaminate with retry attempt's |
| 665 // data. | |
| 589 if (!was_retry_attempt) | 666 if (!was_retry_attempt) |
| 590 RecordPerformanceHistograms(start_time, error, os_error); | 667 RecordPerformanceHistograms(start_time, error, os_error); |
| 591 | 668 |
| 592 RecordAttemptHistograms(start_time, attempt_number, error, os_error); | 669 RecordAttemptHistograms(start_time, attempt_number, error, os_error); |
| 593 | 670 |
| 594 if (was_cancelled()) | 671 if (was_canceled()) |
| 595 return; | 672 return; |
| 596 | 673 |
| 674 scoped_refptr<NetLog::EventParameters> params; | |
| 675 if (error != OK) { | |
| 676 params = new HostResolveFailedParams(attempt_number, error, os_error); | |
| 677 } else { | |
| 678 params = new NetLogIntegerParameter("attempt_number", attempt_number_); | |
| 679 } | |
| 680 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, | |
| 681 params); | |
| 682 | |
| 683 if (was_completed()) | |
| 684 return; | |
| 685 | |
| 686 // Copy the results from the first worker thread that resolves the host. | |
| 687 results_ = results; | |
| 688 completed_attempt_number_ = attempt_number; | |
| 689 completed_attempt_error_ = error; | |
| 690 | |
| 597 if (was_retry_attempt) { | 691 if (was_retry_attempt) { |
| 598 // If retry attempt finishes before 1st attempt, then get stats on how | 692 // If retry attempt finishes before 1st attempt, then get stats on how |
| 599 // much time is saved by having spawned an extra attempt. | 693 // much time is saved by having spawned an extra attempt. |
| 600 retry_attempt_finished_time_ = base::TimeTicks::Now(); | 694 retry_attempt_finished_time_ = base::TimeTicks::Now(); |
| 601 } | 695 } |
| 602 | 696 |
| 603 scoped_refptr<NetLog::EventParameters> params; | 697 scoped_refptr<NetLog::EventParameters> params; |
| 604 if (error != OK) { | 698 if (error != OK) { |
| 605 params = new HostResolveFailedParams(0, error, os_error); | 699 params = new HostResolveFailedParams(0, error, os_error); |
| 606 } else { | 700 } else { |
| 607 params = new AddressListNetLogParam(results_); | 701 params = new AddressListNetLogParam(results_); |
| 608 } | 702 } |
| 609 | 703 |
| 610 // End here to prevent issues when a Job outlives the HostResolver that | 704 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); |
| 611 // spawned it. | |
| 612 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, params); | |
| 613 | 705 |
| 614 DCHECK(!requests_.empty()); | 706 callback_.Run(error, os_error, results_); |
| 615 | |
| 616 // Use the port number of the first request. | |
| 617 if (error == OK) | |
| 618 MutableSetPort(requests_[0]->port(), &results_); | |
| 619 | |
| 620 resolver_->OnJobComplete(this, error, os_error, results_); | |
| 621 } | 707 } |
| 622 | 708 |
| 623 void RecordPerformanceHistograms(const base::TimeTicks& start_time, | 709 void RecordPerformanceHistograms(const base::TimeTicks& start_time, |
| 624 const int error, | 710 const int error, |
| 625 const int os_error) const { | 711 const int os_error) const { |
| 626 DCHECK(origin_loop_->BelongsToCurrentThread()); | 712 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 627 enum Category { // Used in HISTOGRAM_ENUMERATION. | 713 enum Category { // Used in HISTOGRAM_ENUMERATION. |
| 628 RESOLVE_SUCCESS, | 714 RESOLVE_SUCCESS, |
| 629 RESOLVE_FAIL, | 715 RESOLVE_FAIL, |
| 630 RESOLVE_SPECULATIVE_SUCCESS, | 716 RESOLVE_SPECULATIVE_SUCCESS, |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess", | 792 DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess", |
| 707 "DnsParallelism"), duration); | 793 "DnsParallelism"), duration); |
| 708 } | 794 } |
| 709 } | 795 } |
| 710 } | 796 } |
| 711 | 797 |
| 712 void RecordAttemptHistograms(const base::TimeTicks& start_time, | 798 void RecordAttemptHistograms(const base::TimeTicks& start_time, |
| 713 const uint32 attempt_number, | 799 const uint32 attempt_number, |
| 714 const int error, | 800 const int error, |
| 715 const int os_error) const { | 801 const int os_error) const { |
| 802 DCHECK(origin_loop_->BelongsToCurrentThread()); | |
| 716 bool first_attempt_to_complete = | 803 bool first_attempt_to_complete = |
| 717 completed_attempt_number_ == attempt_number; | 804 completed_attempt_number_ == attempt_number; |
| 718 bool is_first_attempt = (attempt_number == 1); | 805 bool is_first_attempt = (attempt_number == 1); |
| 719 | 806 |
| 720 if (first_attempt_to_complete) { | 807 if (first_attempt_to_complete) { |
| 721 // If this was first attempt to complete, then record the resolution | 808 // If this was first attempt to complete, then record the resolution |
| 722 // status of the attempt. | 809 // status of the attempt. |
| 723 if (completed_attempt_error_ == OK) { | 810 if (completed_attempt_error_ == OK) { |
| 724 UMA_HISTOGRAM_ENUMERATION( | 811 UMA_HISTOGRAM_ENUMERATION( |
| 725 "DNS.AttemptFirstSuccess", attempt_number, 100); | 812 "DNS.AttemptFirstSuccess", attempt_number, 100); |
| 726 } else { | 813 } else { |
| 727 UMA_HISTOGRAM_ENUMERATION( | 814 UMA_HISTOGRAM_ENUMERATION( |
| 728 "DNS.AttemptFirstFailure", attempt_number, 100); | 815 "DNS.AttemptFirstFailure", attempt_number, 100); |
| 729 } | 816 } |
| 730 } | 817 } |
| 731 | 818 |
| 732 if (error == OK) | 819 if (error == OK) |
| 733 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100); | 820 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100); |
| 734 else | 821 else |
| 735 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100); | 822 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100); |
| 736 | 823 |
| 737 // If first attempt didn't finish before retry attempt, then calculate stats | 824 // If first attempt didn't finish before retry attempt, then calculate stats |
| 738 // on how much time is saved by having spawned an extra attempt. | 825 // on how much time is saved by having spawned an extra attempt. |
| 739 if (!first_attempt_to_complete && is_first_attempt && !was_cancelled()) { | 826 if (!first_attempt_to_complete && is_first_attempt && !was_canceled()) { |
| 740 DNS_HISTOGRAM("DNS.AttemptTimeSavedByRetry", | 827 DNS_HISTOGRAM("DNS.AttemptTimeSavedByRetry", |
| 741 base::TimeTicks::Now() - retry_attempt_finished_time_); | 828 base::TimeTicks::Now() - retry_attempt_finished_time_); |
| 742 } | 829 } |
| 743 | 830 |
| 744 if (was_cancelled() || !first_attempt_to_complete) { | 831 if (was_canceled() || !first_attempt_to_complete) { |
| 745 // Count those attempts which completed after the job was already canceled | 832 // Count those attempts which completed after the job was already canceled |
| 746 // OR after the job was already completed by an earlier attempt (so in | 833 // OR after the job was already completed by an earlier attempt (so in |
| 747 // effect). | 834 // effect). |
| 748 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100); | 835 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100); |
| 749 | 836 |
| 750 // Record if job is cancelled. | 837 // Record if job is canceled. |
| 751 if (was_cancelled()) | 838 if (was_canceled()) |
| 752 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); | 839 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); |
| 753 } | 840 } |
| 754 | 841 |
| 755 base::TimeDelta duration = base::TimeTicks::Now() - start_time; | 842 base::TimeDelta duration = base::TimeTicks::Now() - start_time; |
| 756 if (error == OK) | 843 if (error == OK) |
| 757 DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); | 844 DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); |
| 758 else | 845 else |
| 759 DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); | 846 DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); |
| 760 } | 847 } |
| 761 | 848 |
| 762 // Immutable. Can be read from either thread, | |
| 763 const int id_; | |
| 764 | |
| 765 // Set on the origin thread, read on the worker thread. | 849 // Set on the origin thread, read on the worker thread. |
| 766 Key key_; | 850 Key key_; |
| 767 | 851 |
| 768 // Only used on the origin thread (where Resolve was called). | 852 // Holds an owning reference to the HostResolverProc that we are going to use. |
| 769 HostResolverImpl* resolver_; | 853 // This may not be the current resolver procedure by the time we call |
| 770 RequestsList requests_; // The requests waiting on this job. | 854 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning |
| 855 // reference ensures that it remains valid until we are done. | |
| 856 ProcTaskParams params_; | |
| 857 | |
| 858 // The listener to the results of this ProcTask. | |
| 859 Callback callback_; | |
| 771 | 860 |
| 772 // Used to post ourselves onto the origin thread. | 861 // Used to post ourselves onto the origin thread. |
| 773 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 862 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
| 774 | 863 |
| 775 // Hold an owning reference to the HostResolverProc that we are going to use. | |
| 776 // This may not be the current resolver procedure by the time we call | |
| 777 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning | |
| 778 // reference ensures that it remains valid until we are done. | |
| 779 scoped_refptr<HostResolverProc> resolver_proc_; | |
| 780 | |
| 781 // The amount of time after starting a resolution attempt until deciding to | |
| 782 // retry. | |
| 783 base::TimeDelta unresponsive_delay_; | |
| 784 | |
| 785 // Keeps track of the number of attempts we have made so far to resolve the | 864 // Keeps track of the number of attempts we have made so far to resolve the |
| 786 // host. Whenever we start an attempt to resolve the host, we increase this | 865 // host. Whenever we start an attempt to resolve the host, we increase this |
| 787 // number. | 866 // number. |
| 788 uint32 attempt_number_; | 867 uint32 attempt_number_; |
| 789 | 868 |
| 790 // The index of the attempt which finished first (or 0 if the job is still in | 869 // The index of the attempt which finished first (or 0 if the job is still in |
| 791 // progress). | 870 // progress). |
| 792 uint32 completed_attempt_number_; | 871 uint32 completed_attempt_number_; |
| 793 | 872 |
| 794 // The result (a net error code) from the first attempt to complete. | 873 // The result (a net error code) from the first attempt to complete. |
| 795 int completed_attempt_error_; | 874 int completed_attempt_error_; |
| 796 | 875 |
| 797 // The time when retry attempt was finished. | 876 // The time when retry attempt was finished. |
| 798 base::TimeTicks retry_attempt_finished_time_; | 877 base::TimeTicks retry_attempt_finished_time_; |
| 799 | 878 |
| 800 // True if a non-speculative request was ever attached to this job | 879 // True if a non-speculative request was ever attached to this job |
| 801 // (regardless of whether or not it was later cancelled. | 880 // (regardless of whether or not it was later canceled. |
| 802 // This boolean is used for histogramming the duration of jobs used to | 881 // This boolean is used for histogramming the duration of jobs used to |
| 803 // service non-speculative requests. | 882 // service non-speculative requests. |
| 804 bool had_non_speculative_request_; | 883 bool had_non_speculative_request_; |
| 805 | 884 |
| 806 AddressList results_; | 885 AddressList results_; |
| 807 | 886 |
| 808 BoundNetLog net_log_; | 887 BoundNetLog net_log_; |
| 809 | 888 |
| 810 DISALLOW_COPY_AND_ASSIGN(Job); | 889 DISALLOW_COPY_AND_ASSIGN(ProcTask); |
| 811 }; | 890 }; |
| 812 | 891 |
| 813 //----------------------------------------------------------------------------- | 892 //----------------------------------------------------------------------------- |
| 814 | 893 |
| 815 // This class represents a request to the worker pool for a "probe for IPv6 | 894 // Represents a request to the worker pool for a "probe for IPv6 support" call. |
| 816 // support" call. | |
| 817 class HostResolverImpl::IPv6ProbeJob | 895 class HostResolverImpl::IPv6ProbeJob |
| 818 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { | 896 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
| 819 public: | 897 public: |
| 820 explicit IPv6ProbeJob(HostResolverImpl* resolver) | 898 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
| 821 : resolver_(resolver), | 899 : resolver_(resolver), |
| 822 origin_loop_(base::MessageLoopProxy::current()) { | 900 origin_loop_(base::MessageLoopProxy::current()) { |
| 823 DCHECK(resolver); | 901 DCHECK(resolver); |
| 824 } | 902 } |
| 825 | 903 |
| 826 void Start() { | 904 void Start() { |
| 827 DCHECK(origin_loop_->BelongsToCurrentThread()); | 905 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 828 if (was_cancelled()) | 906 if (was_canceled()) |
| 829 return; | 907 return; |
| 830 const bool kIsSlow = true; | 908 const bool kIsSlow = true; |
| 831 base::WorkerPool::PostTask( | 909 base::WorkerPool::PostTask( |
| 832 FROM_HERE, base::Bind(&IPv6ProbeJob::DoProbe, this), kIsSlow); | 910 FROM_HERE, base::Bind(&IPv6ProbeJob::DoProbe, this), kIsSlow); |
| 833 } | 911 } |
| 834 | 912 |
| 835 // Cancels the current job. | 913 // Cancels the current job. |
| 836 void Cancel() { | 914 void Cancel() { |
| 837 DCHECK(origin_loop_->BelongsToCurrentThread()); | 915 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 838 if (was_cancelled()) | 916 if (was_canceled()) |
| 839 return; | 917 return; |
| 840 resolver_ = NULL; // Read/write ONLY on origin thread. | 918 resolver_ = NULL; // Read/write ONLY on origin thread. |
| 841 } | 919 } |
| 842 | 920 |
| 843 private: | 921 private: |
| 844 friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>; | 922 friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>; |
| 845 | 923 |
| 846 ~IPv6ProbeJob() { | 924 ~IPv6ProbeJob() { |
| 847 } | 925 } |
| 848 | 926 |
| 849 bool was_cancelled() const { | 927 bool was_canceled() const { |
| 850 DCHECK(origin_loop_->BelongsToCurrentThread()); | 928 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 851 return !resolver_; | 929 return !resolver_; |
| 852 } | 930 } |
| 853 | 931 |
| 854 // Run on worker thread. | 932 // Run on worker thread. |
| 855 void DoProbe() { | 933 void DoProbe() { |
| 856 // Do actual testing on this thread, as it takes 40-100ms. | 934 // Do actual testing on this thread, as it takes 40-100ms. |
| 857 AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED | 935 AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED |
| 858 : ADDRESS_FAMILY_IPV4; | 936 : ADDRESS_FAMILY_IPV4; |
| 859 | 937 |
| 860 origin_loop_->PostTask( | 938 origin_loop_->PostTask( |
| 861 FROM_HERE, | 939 FROM_HERE, |
| 862 base::Bind(&IPv6ProbeJob::OnProbeComplete, this, family)); | 940 base::Bind(&IPv6ProbeJob::OnProbeComplete, this, family)); |
| 863 } | 941 } |
| 864 | 942 |
| 865 // Callback for when DoProbe() completes. | 943 // Callback for when DoProbe() completes. |
| 866 void OnProbeComplete(AddressFamily address_family) { | 944 void OnProbeComplete(AddressFamily address_family) { |
| 867 DCHECK(origin_loop_->BelongsToCurrentThread()); | 945 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 868 if (was_cancelled()) | 946 if (was_canceled()) |
| 869 return; | 947 return; |
| 870 resolver_->IPv6ProbeSetDefaultAddressFamily(address_family); | 948 resolver_->IPv6ProbeSetDefaultAddressFamily(address_family); |
| 871 } | 949 } |
| 872 | 950 |
| 873 // Used/set only on origin thread. | 951 // Used/set only on origin thread. |
| 874 HostResolverImpl* resolver_; | 952 HostResolverImpl* resolver_; |
| 875 | 953 |
| 876 // Used to post ourselves onto the origin thread. | 954 // Used to post ourselves onto the origin thread. |
| 877 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 955 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
| 878 | 956 |
| 879 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 957 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
| 880 }; | 958 }; |
| 881 | 959 |
| 882 //----------------------------------------------------------------------------- | 960 //----------------------------------------------------------------------------- |
| 883 | 961 |
| 884 // We rely on the priority enum values being sequential having starting at 0, | 962 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
| 885 // and increasing for lower priorities. | 963 // Spawns ProcTask when started. |
| 886 COMPILE_ASSERT(HIGHEST == 0u && | 964 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
| 887 LOWEST > HIGHEST && | |
| 888 IDLE > LOWEST && | |
| 889 NUM_PRIORITIES > IDLE, | |
| 890 priority_indexes_incompatible); | |
| 891 | |
| 892 // JobPool contains all the information relating to queued requests, including | |
| 893 // the limits on how many jobs are allowed to be used for this category of | |
| 894 // requests. | |
| 895 class HostResolverImpl::JobPool { | |
| 896 public: | 965 public: |
| 897 JobPool(size_t max_outstanding_jobs, size_t max_pending_requests) | 966 // Creates new job for |key| where |request_net_log| is bound to the |
| 898 : num_outstanding_jobs_(0u) { | 967 // request that spawned it. |
| 899 SetConstraints(max_outstanding_jobs, max_pending_requests); | 968 Job(HostResolverImpl* resolver, |
| 900 } | 969 const Key& key, |
| 901 | 970 const BoundNetLog& request_net_log) |
| 902 ~JobPool() { | 971 : resolver_(resolver->AsWeakPtr()), |
| 903 // Free the pending requests. | 972 key_(key), |
| 904 for (size_t i = 0; i < arraysize(pending_requests_); ++i) | 973 had_non_speculative_request_(false), |
| 905 STLDeleteElements(&pending_requests_[i]); | 974 net_log_(BoundNetLog::Make(request_net_log.net_log(), |
| 906 } | 975 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), |
| 907 | 976 net_error_(ERR_IO_PENDING), |
| 908 // Sets the constraints for this pool. See SetPoolConstraints() for the | 977 os_error_(0) { |
| 909 // specific meaning of these parameters. | 978 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); |
| 910 void SetConstraints(size_t max_outstanding_jobs, | 979 |
| 911 size_t max_pending_requests) { | 980 net_log_.BeginEvent( |
| 912 CHECK_NE(max_outstanding_jobs, 0u); | 981 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 913 max_outstanding_jobs_ = max_outstanding_jobs; | 982 make_scoped_refptr(new JobCreationParameters( |
| 914 max_pending_requests_ = max_pending_requests; | 983 key_.hostname, request_net_log.source()))); |
| 915 } | 984 } |
| 916 | 985 |
| 917 // Returns the number of pending requests enqueued to this pool. | 986 virtual ~Job() { |
| 918 // A pending request is one waiting to be attached to a job. | 987 if (net_error_ == ERR_IO_PENDING) { |
| 919 size_t GetNumPendingRequests() const { | 988 if (is_running()) { |
| 920 size_t total = 0u; | 989 proc_task_->Cancel(); |
| 921 for (size_t i = 0u; i < arraysize(pending_requests_); ++i) | 990 proc_task_ = NULL; |
| 922 total += pending_requests_[i].size(); | 991 net_error_ = ERR_ABORTED; |
| 923 return total; | 992 } else { |
| 924 } | 993 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 925 | 994 } |
| 926 bool HasPendingRequests() const { | 995 for (RequestsList::const_iterator it = requests_.begin(); |
| 927 return GetNumPendingRequests() > 0u; | 996 it != requests_.end(); ++it) { |
| 928 } | 997 Request* req = *it; |
| 929 | 998 if (req->was_canceled()) |
| 930 // Enqueues a request to this pool. As a result of enqueing this request, | 999 continue; |
| 931 // the queue may have reached its maximum size. In this case, a request is | 1000 DCHECK_EQ(this, req->job()); |
| 932 // evicted from the queue, and returned. Otherwise returns NULL. The caller | 1001 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 933 // is responsible for freeing the evicted request. | 1002 req->info()); |
| 934 Request* InsertPendingRequest(Request* req) { | |
| 935 req->request_net_log().BeginEvent( | |
| 936 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, | |
| 937 NULL); | |
| 938 | |
| 939 PendingRequestsQueue& q = pending_requests_[req->info().priority()]; | |
| 940 q.push_back(req); | |
| 941 | |
| 942 // If the queue is too big, kick out the lowest priority oldest request. | |
| 943 if (GetNumPendingRequests() > max_pending_requests_) { | |
| 944 // Iterate over the queues from lowest priority to highest priority. | |
| 945 for (int i = static_cast<int>(arraysize(pending_requests_)) - 1; | |
| 946 i >= 0; --i) { | |
| 947 PendingRequestsQueue& q = pending_requests_[i]; | |
| 948 if (!q.empty()) { | |
| 949 Request* req = q.front(); | |
| 950 q.pop_front(); | |
| 951 req->request_net_log().AddEvent( | |
| 952 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE_EVICTED, NULL); | |
| 953 req->request_net_log().EndEvent( | |
| 954 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL); | |
| 955 return req; | |
| 956 } | |
| 957 } | 1003 } |
| 958 } | 1004 } |
| 959 | 1005 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 960 return NULL; | 1006 net_error_); |
| 961 } | 1007 STLDeleteElements(&requests_); |
| 962 | 1008 } |
| 963 // Erases |req| from this container. Caller is responsible for freeing | 1009 |
| 964 // |req| afterwards. | 1010 HostResolverImpl* resolver() const { |
| 965 void RemovePendingRequest(Request* req) { | 1011 return resolver_; |
| 966 PendingRequestsQueue& q = pending_requests_[req->info().priority()]; | 1012 } |
| 967 PendingRequestsQueue::iterator it = std::find(q.begin(), q.end(), req); | 1013 |
| 968 DCHECK(it != q.end()); | 1014 RequestPriority priority() const { |
| 969 q.erase(it); | 1015 return priority_tracker_.highest_priority(); |
| 970 req->request_net_log().EndEvent( | 1016 } |
| 971 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL); | 1017 |
| 972 } | 1018 // Number of non-canceled requests in |requests_|. |
| 973 | 1019 size_t num_active_requests() const { |
| 974 // Removes and returns the highest priority pending request. | 1020 return priority_tracker_.total_count(); |
| 975 Request* RemoveTopPendingRequest() { | 1021 } |
| 976 DCHECK(HasPendingRequests()); | 1022 |
| 977 | 1023 const Key& key() const { |
| 978 for (size_t i = 0u; i < arraysize(pending_requests_); ++i) { | 1024 return key_; |
| 979 PendingRequestsQueue& q = pending_requests_[i]; | 1025 } |
| 980 if (!q.empty()) { | 1026 |
| 981 Request* req = q.front(); | 1027 int net_error() const { |
| 982 q.pop_front(); | 1028 return net_error_; |
| 983 req->request_net_log().EndEvent( | 1029 } |
| 984 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL); | 1030 |
| 985 return req; | 1031 // Used by HostResolverImpl with |dispatcher_|. |
| 986 } | 1032 const PrioritizedDispatcher::Handle& handle() const { |
| 1033 return handle_; | |
| 1034 } | |
| 1035 | |
| 1036 void set_handle(const PrioritizedDispatcher::Handle& handle) { | |
| 1037 handle_ = handle; | |
| 1038 } | |
| 1039 | |
| 1040 // The Job will own |req| and destroy it in ~Job. | |
| 1041 void AddRequest(Request* req) { | |
| 1042 DCHECK_EQ(key_.hostname, req->info().hostname()); | |
| 1043 | |
| 1044 req->set_job(this); | |
| 1045 requests_.push_back(req); | |
| 1046 | |
| 1047 priority_tracker_.Add(req->info().priority()); | |
| 1048 | |
| 1049 req->request_net_log().AddEvent( | |
| 1050 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | |
| 1051 make_scoped_refptr(new NetLogSourceParameter( | |
| 1052 "source_dependency", net_log_.source()))); | |
| 1053 | |
| 1054 net_log_.AddEvent( | |
| 1055 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, | |
| 1056 make_scoped_refptr(new JobAttachParameters( | |
| 1057 req->request_net_log().source(), priority()))); | |
| 1058 | |
| 1059 // TODO(szym): Check if this is still needed. | |
| 1060 if (!req->info().is_speculative()) { | |
| 1061 had_non_speculative_request_ = true; | |
| 1062 if (proc_task_) | |
| 1063 proc_task_->set_had_non_speculative_request(); | |
| 987 } | 1064 } |
| 988 | 1065 } |
| 989 NOTREACHED(); | 1066 |
| 990 return NULL; | 1067 void CancelRequest(Request* req) { |
| 991 } | 1068 DCHECK_EQ(key_.hostname, req->info().hostname()); |
| 992 | 1069 DCHECK(!req->was_canceled()); |
| 993 // Keeps track of a job that was just added/removed, and belongs to this pool. | 1070 // Don't remove it from |requests_| just mark it canceled. |
| 994 void AdjustNumOutstandingJobs(int offset) { | 1071 req->MarkAsCanceled(); |
| 995 DCHECK(offset == 1 || (offset == -1 && num_outstanding_jobs_ > 0u)); | 1072 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 996 num_outstanding_jobs_ += offset; | 1073 req->info()); |
| 997 } | 1074 priority_tracker_.Remove(req->info().priority()); |
| 998 | 1075 net_log_.AddEvent( |
| 999 void ResetNumOutstandingJobs() { | 1076 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, |
| 1000 num_outstanding_jobs_ = 0; | 1077 make_scoped_refptr(new JobAttachParameters( |
| 1001 } | 1078 req->request_net_log().source(), priority()))); |
| 1002 | 1079 } |
| 1003 // Returns true if a new job can be created for this pool. | 1080 |
| 1004 bool CanCreateJob() const { | 1081 // Aborts and destroys the job, completes all requests as aborted. |
| 1005 return num_outstanding_jobs_ + 1u <= max_outstanding_jobs_; | 1082 void Abort() { |
| 1006 } | 1083 // Job should only be aborted if it's running. |
| 1007 | 1084 DCHECK(is_running()); |
| 1008 // Removes any pending requests from the queue which are for the | 1085 proc_task_->Cancel(); |
| 1009 // same (hostname / effective address-family) as |job|, and attaches them to | 1086 proc_task_ = NULL; |
| 1010 // |job|. | 1087 net_error_ = ERR_ABORTED; |
| 1011 void MoveRequestsToJob(Job* job) { | 1088 os_error_ = 0; |
| 1012 for (size_t i = 0u; i < arraysize(pending_requests_); ++i) { | 1089 CompleteRequests(AddressList()); |
| 1013 PendingRequestsQueue& q = pending_requests_[i]; | 1090 } |
| 1014 PendingRequestsQueue::iterator req_it = q.begin(); | 1091 |
| 1015 while (req_it != q.end()) { | 1092 bool is_running() const { |
| 1016 Request* req = *req_it; | 1093 return proc_task_.get() != NULL; |
| 1017 if (job->CanServiceRequest(req->info())) { | 1094 } |
| 1018 // Job takes ownership of |req|. | 1095 |
| 1019 job->AddRequest(req); | 1096 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
| 1020 req_it = q.erase(req_it); | 1097 void OnEvicted() { |
| 1021 } else { | 1098 // Must not be running. |
| 1022 ++req_it; | 1099 DCHECK(!is_running()); |
| 1023 } | 1100 handle_ = PrioritizedDispatcher::Handle(); |
| 1024 } | 1101 |
| 1102 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | |
| 1103 | |
| 1104 // This signals to CompleteRequests that this job never ran. | |
| 1105 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | |
| 1106 os_error_ = 0; | |
| 1107 CompleteRequests(AddressList()); | |
| 1108 } | |
| 1109 | |
| 1110 // PriorityDispatch::Job interface. | |
| 1111 virtual void Start() OVERRIDE { | |
| 1112 DCHECK(!is_running()); | |
| 1113 handle_ = PrioritizedDispatcher::Handle(); | |
| 1114 | |
| 1115 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); | |
| 1116 | |
| 1117 proc_task_ = new ProcTask( | |
| 1118 key_, | |
| 1119 resolver_->proc_params_, | |
| 1120 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), | |
| 1121 net_log_); | |
| 1122 | |
| 1123 if (had_non_speculative_request_) | |
| 1124 proc_task_->set_had_non_speculative_request(); | |
| 1125 // Start() could be called from within Resolve(), hence it must NOT directly | |
| 1126 // call OnProcTaskComplete, for example, on synchronous failure. | |
| 1127 proc_task_->Start(); | |
| 1128 } | |
| 1129 | |
| 1130 private: | |
| 1131 // Called by ProcTask when it completes. | |
| 1132 void OnProcTaskComplete(int net_error, int os_error, | |
| 1133 const AddressList& addrlist) { | |
| 1134 DCHECK(is_running()); | |
| 1135 proc_task_ = NULL; | |
| 1136 net_error_ = net_error; | |
| 1137 os_error_ = os_error; | |
| 1138 | |
| 1139 // We are the only consumer of |addrlist|, so we can safely change the port | |
| 1140 // without copy-on-write. This pays off, when job has only one request. | |
| 1141 AddressList list = addrlist; | |
| 1142 if (net_error == OK && !requests_.empty()) | |
| 1143 MutableSetPort(requests_.front()->info().port(), &list); | |
| 1144 CompleteRequests(list); | |
| 1145 } | |
| 1146 | |
| 1147 // Completes all Requests. Calls OnJobFinished and deletes self. | |
| 1148 void CompleteRequests(const AddressList& addrlist) { | |
| 1149 CHECK(resolver_); | |
| 1150 | |
| 1151 // This job must be removed from resolver's |jobs_| now to make room for a | |
| 1152 // new job with the same key in case one of the OnComplete callbacks decides | |
| 1153 // to spawn one. Consequently, the job deletes itself when CompleteRequests | |
| 1154 // is done. | |
| 1155 scoped_ptr<Job> self_deleter(this); | |
| 1156 resolver_->OnJobFinished(this, addrlist); | |
| 1157 | |
| 1158 // Complete all of the requests that were attached to the job. | |
| 1159 for (RequestsList::const_iterator it = requests_.begin(); | |
| 1160 it != requests_.end(); ++it) { | |
| 1161 Request* req = *it; | |
| 1162 | |
| 1163 if (req->was_canceled()) | |
| 1164 continue; | |
| 1165 | |
| 1166 DCHECK_EQ(this, req->job()); | |
| 1167 // Update the net log and notify registered observers. | |
| 1168 LogFinishRequest(req->source_net_log(), req->request_net_log(), | |
| 1169 req->info(), net_error_, os_error_); | |
| 1170 | |
| 1171 req->OnComplete(net_error_, addrlist); | |
| 1172 | |
| 1173 // Check if the resolver was destroyed as a result of running the | |
| 1174 // callback. If it was, we could continue, but we choose to bail. | |
| 1175 if (!resolver_) | |
| 1176 return; | |
| 1025 } | 1177 } |
| 1026 } | 1178 } |
| 1027 | 1179 |
| 1028 private: | 1180 // Used to call OnJobFinished and RemoveJob. |
| 1029 typedef std::deque<Request*> PendingRequestsQueue; | 1181 base::WeakPtr<HostResolverImpl> resolver_; |
| 1030 | 1182 |
| 1031 // Maximum number of concurrent jobs allowed to be started for requests | 1183 Key key_; |
| 1032 // belonging to this pool. | 1184 |
| 1033 size_t max_outstanding_jobs_; | 1185 // Tracks the highest priority across |requests_|. |
| 1034 | 1186 PriorityTracker priority_tracker_; |
| 1035 // The current number of running jobs that were started for requests | 1187 |
| 1036 // belonging to this pool. | 1188 bool had_non_speculative_request_; |
| 1037 size_t num_outstanding_jobs_; | 1189 |
| 1038 | 1190 BoundNetLog net_log_; |
| 1039 // The maximum number of requests we allow to be waiting on a job, | 1191 |
| 1040 // for this pool. | 1192 // Store result here in case the job fails fast in Resolve(). |
| 1041 size_t max_pending_requests_; | 1193 int net_error_; |
| 1042 | 1194 int os_error_; |
| 1043 // The requests which are waiting to be started for this pool. | 1195 |
| 1044 PendingRequestsQueue pending_requests_[NUM_PRIORITIES]; | 1196 // A ProcTask created and started when this Job is dispatched.. |
| 1197 scoped_refptr<ProcTask> proc_task_; | |
| 1198 | |
| 1199 // All Requests waiting for the result of this Job. Some can be canceled. | |
| 1200 RequestsList requests_; | |
| 1201 | |
| 1202 // A handle used by HostResolverImpl in |dispatcher_|. | |
| 1203 PrioritizedDispatcher::Handle handle_; | |
| 1045 }; | 1204 }; |
| 1046 | 1205 |
| 1047 //----------------------------------------------------------------------------- | 1206 //----------------------------------------------------------------------------- |
| 1048 | 1207 |
| 1208 HostResolverImpl::ProcTaskParams::ProcTaskParams( | |
| 1209 HostResolverProc* resolver_proc, | |
| 1210 size_t max_retry_attempts) | |
| 1211 : resolver_proc(resolver_proc), | |
| 1212 max_retry_attempts(max_retry_attempts), | |
| 1213 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), | |
| 1214 retry_factor(2) { | |
| 1215 } | |
| 1216 | |
| 1217 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} | |
| 1218 | |
| 1049 HostResolverImpl::HostResolverImpl( | 1219 HostResolverImpl::HostResolverImpl( |
| 1050 HostResolverProc* resolver_proc, | |
| 1051 HostCache* cache, | 1220 HostCache* cache, |
| 1052 size_t max_jobs, | 1221 const PrioritizedDispatcher::Limits& job_limits, |
| 1053 size_t max_retry_attempts, | 1222 const ProcTaskParams& proc_params, |
| 1054 NetLog* net_log) | 1223 NetLog* net_log) |
| 1055 : cache_(cache), | 1224 : cache_(cache), |
| 1056 max_jobs_(max_jobs), | 1225 dispatcher_(job_limits), |
| 1057 max_retry_attempts_(max_retry_attempts), | 1226 max_queued_jobs_(job_limits.total_jobs * 100u), |
| 1058 unresponsive_delay_(base::TimeDelta::FromMilliseconds(6000)), | 1227 proc_params_(proc_params), |
| 1059 retry_factor_(2), | |
| 1060 next_job_id_(0), | |
| 1061 resolver_proc_(resolver_proc), | |
| 1062 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 1228 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
| 1063 ipv6_probe_monitoring_(false), | 1229 ipv6_probe_monitoring_(false), |
| 1064 additional_resolver_flags_(0), | 1230 additional_resolver_flags_(0), |
| 1065 net_log_(net_log) { | 1231 net_log_(net_log) { |
| 1066 DCHECK_GT(max_jobs, 0u); | 1232 |
| 1233 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); | |
| 1067 | 1234 |
| 1068 // Maximum of 4 retry attempts for host resolution. | 1235 // Maximum of 4 retry attempts for host resolution. |
| 1069 static const size_t kDefaultMaxRetryAttempts = 4u; | 1236 static const size_t kDefaultMaxRetryAttempts = 4u; |
| 1070 | 1237 |
| 1071 if (max_retry_attempts_ == HostResolver::kDefaultRetryAttempts) | 1238 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) |
| 1072 max_retry_attempts_ = kDefaultMaxRetryAttempts; | 1239 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; |
| 1073 | |
| 1074 // It is cumbersome to expose all of the constraints in the constructor, | |
| 1075 // so we choose some defaults, which users can override later. | |
| 1076 job_pools_[POOL_NORMAL] = new JobPool(max_jobs, 100u * max_jobs); | |
| 1077 | 1240 |
| 1078 #if defined(OS_WIN) | 1241 #if defined(OS_WIN) |
| 1079 EnsureWinsockInit(); | 1242 EnsureWinsockInit(); |
| 1080 #endif | 1243 #endif |
| 1081 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1244 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 1082 if (HaveOnlyLoopbackAddresses()) | 1245 if (HaveOnlyLoopbackAddresses()) |
| 1083 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; | 1246 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
| 1084 #endif | 1247 #endif |
| 1085 NetworkChangeNotifier::AddIPAddressObserver(this); | 1248 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 1086 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1249 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| 1087 #if !defined(OS_ANDROID) | 1250 #if !defined(OS_ANDROID) |
| 1088 EnsureDnsReloaderInit(); | 1251 EnsureDnsReloaderInit(); |
| 1089 #endif | 1252 #endif |
| 1090 NetworkChangeNotifier::AddDNSObserver(this); | 1253 NetworkChangeNotifier::AddDNSObserver(this); |
| 1091 #endif | 1254 #endif |
| 1092 } | 1255 } |
| 1093 | 1256 |
| 1094 HostResolverImpl::~HostResolverImpl() { | 1257 HostResolverImpl::~HostResolverImpl() { |
| 1095 // Cancel the outstanding jobs. Those jobs may contain several attached | |
| 1096 // requests, which will also be cancelled. | |
| 1097 DiscardIPv6ProbeJob(); | 1258 DiscardIPv6ProbeJob(); |
| 1098 | 1259 |
| 1099 CancelAllJobs(); | 1260 // This will also cancel all outstanding requests. |
| 1100 | 1261 STLDeleteValues(&jobs_); |
| 1101 // In case we are being deleted during the processing of a callback. | |
| 1102 if (cur_completing_job_) | |
| 1103 cur_completing_job_->Cancel(); | |
| 1104 | 1262 |
| 1105 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 1263 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 1106 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1264 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| 1107 NetworkChangeNotifier::RemoveDNSObserver(this); | 1265 NetworkChangeNotifier::RemoveDNSObserver(this); |
| 1108 #endif | 1266 #endif |
| 1109 | |
| 1110 // Delete the job pools. | |
| 1111 for (size_t i = 0u; i < arraysize(job_pools_); ++i) | |
| 1112 delete job_pools_[i]; | |
| 1113 } | 1267 } |
| 1114 | 1268 |
| 1115 void HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index, | 1269 void HostResolverImpl::SetMaxQueuedJobs(size_t value) { |
| 1116 size_t max_outstanding_jobs, | 1270 DCHECK_EQ(0u, dispatcher_.num_queued_jobs()); |
| 1117 size_t max_pending_requests) { | 1271 DCHECK_GT(value, 0u); |
| 1118 DCHECK(CalledOnValidThread()); | 1272 max_queued_jobs_ = value; |
| 1119 CHECK_GE(pool_index, 0); | |
| 1120 CHECK_LT(pool_index, POOL_COUNT); | |
| 1121 CHECK(jobs_.empty()) << "Can only set constraints during setup"; | |
| 1122 JobPool* pool = job_pools_[pool_index]; | |
| 1123 pool->SetConstraints(max_outstanding_jobs, max_pending_requests); | |
| 1124 } | 1273 } |
| 1125 | 1274 |
| 1126 int HostResolverImpl::Resolve(const RequestInfo& info, | 1275 int HostResolverImpl::Resolve(const RequestInfo& info, |
| 1127 AddressList* addresses, | 1276 AddressList* addresses, |
| 1128 const CompletionCallback& callback, | 1277 const CompletionCallback& callback, |
| 1129 RequestHandle* out_req, | 1278 RequestHandle* out_req, |
| 1130 const BoundNetLog& source_net_log) { | 1279 const BoundNetLog& source_net_log) { |
| 1131 DCHECK(addresses); | 1280 DCHECK(addresses); |
| 1132 DCHECK(CalledOnValidThread()); | 1281 DCHECK(CalledOnValidThread()); |
| 1133 DCHECK_EQ(false, callback.is_null()); | 1282 DCHECK_EQ(false, callback.is_null()); |
| 1134 | 1283 |
| 1135 // Make a log item for the request. | 1284 // Make a log item for the request. |
| 1136 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, | 1285 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, |
| 1137 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); | 1286 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); |
| 1138 | 1287 |
| 1139 // Update the net log and notify registered observers. | 1288 LogStartRequest(source_net_log, request_net_log, info); |
| 1140 OnStartRequest(source_net_log, request_net_log, info); | |
| 1141 | 1289 |
| 1142 // Build a key that identifies the request in the cache and in the | 1290 // Build a key that identifies the request in the cache and in the |
| 1143 // outstanding jobs map. | 1291 // outstanding jobs map. |
| 1144 Key key = GetEffectiveKeyForRequest(info); | 1292 Key key = GetEffectiveKeyForRequest(info); |
| 1145 | 1293 |
| 1146 int rv = ResolveHelper(key, info, addresses, request_net_log); | 1294 int rv = ResolveHelper(key, info, addresses, request_net_log); |
| 1147 if (rv != ERR_DNS_CACHE_MISS) { | 1295 if (rv != ERR_DNS_CACHE_MISS) { |
| 1148 OnFinishRequest(source_net_log, request_net_log, info, | 1296 LogFinishRequest(source_net_log, request_net_log, info, rv, |
| 1149 rv, | 1297 0 /* os_error (unknown since from cache) */); |
| 1150 0 /* os_error (unknown since from cache) */); | |
| 1151 return rv; | 1298 return rv; |
| 1152 } | 1299 } |
| 1153 | 1300 |
| 1154 // Create a handle for this request, and pass it back to the user if they | 1301 // Next we need to attach our request to a "job". This job is responsible for |
| 1155 // asked for it (out_req != NULL). | 1302 // calling "getaddrinfo(hostname)" on a worker thread. |
| 1156 Request* req = new Request(source_net_log, request_net_log, info, | 1303 |
| 1157 callback, addresses); | 1304 JobMap::iterator jobit = jobs_.find(key); |
| 1305 Job* job; | |
| 1306 if (jobit == jobs_.end()) { | |
| 1307 // Create new Job. | |
| 1308 job = new Job(this, key, request_net_log); | |
| 1309 job->set_handle(dispatcher_.Add(job, info.priority())); | |
| 1310 | |
| 1311 // Check for queue overflow. | |
| 1312 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { | |
| 1313 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); | |
| 1314 DCHECK(evicted); | |
| 1315 if (evicted == job) { | |
| 1316 delete job; | |
| 1317 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | |
| 1318 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); | |
| 1319 return rv; | |
| 1320 } | |
| 1321 evicted->OnEvicted(); // Deletes |evicted|. | |
| 1322 } | |
| 1323 | |
| 1324 jobs_.insert(jobit, std::make_pair(key, job)); | |
| 1325 } else { | |
| 1326 job = jobit->second; | |
| 1327 } | |
| 1328 | |
| 1329 // Can't complete synchronously. Create and attach request. | |
| 1330 Request* req = new Request(source_net_log, request_net_log, info, callback, | |
| 1331 addresses); | |
| 1332 job->AddRequest(req); | |
| 1333 if (!job->handle().is_null()) | |
| 1334 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); | |
| 1158 if (out_req) | 1335 if (out_req) |
| 1159 *out_req = reinterpret_cast<RequestHandle>(req); | 1336 *out_req = reinterpret_cast<RequestHandle>(req); |
| 1160 | 1337 |
| 1161 // Next we need to attach our request to a "job". This job is responsible for | 1338 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); |
| 1162 // calling "getaddrinfo(hostname)" on a worker thread. | 1339 // Completion happens during Job::CompleteRequests(). |
| 1163 scoped_refptr<Job> job; | |
| 1164 | |
| 1165 // If there is already an outstanding job to resolve |key|, use | |
| 1166 // it. This prevents starting concurrent resolves for the same hostname. | |
| 1167 job = FindOutstandingJob(key); | |
| 1168 if (job) { | |
| 1169 job->AddRequest(req); | |
| 1170 } else { | |
| 1171 JobPool* pool = GetPoolForRequest(req); | |
| 1172 if (CanCreateJobForPool(*pool)) { | |
| 1173 CreateAndStartJob(req); | |
| 1174 } else { | |
| 1175 return EnqueueRequest(pool, req); | |
| 1176 } | |
| 1177 } | |
| 1178 | |
| 1179 // Completion happens during OnJobComplete(Job*). | |
| 1180 return ERR_IO_PENDING; | 1340 return ERR_IO_PENDING; |
| 1181 } | 1341 } |
| 1182 | 1342 |
| 1183 int HostResolverImpl::ResolveHelper(const Key& key, | 1343 int HostResolverImpl::ResolveHelper(const Key& key, |
| 1184 const RequestInfo& info, | 1344 const RequestInfo& info, |
| 1185 AddressList* addresses, | 1345 AddressList* addresses, |
| 1186 const BoundNetLog& request_net_log) { | 1346 const BoundNetLog& request_net_log) { |
| 1187 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. | 1347 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. |
| 1188 // On Windows it gives the default interface's address, whereas on Linux it | 1348 // On Windows it gives the default interface's address, whereas on Linux it |
| 1189 // gives an error. We will make it fail on all platforms for consistency. | 1349 // gives an error. We will make it fail on all platforms for consistency. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1202 AddressList* addresses, | 1362 AddressList* addresses, |
| 1203 const BoundNetLog& source_net_log) { | 1363 const BoundNetLog& source_net_log) { |
| 1204 DCHECK(CalledOnValidThread()); | 1364 DCHECK(CalledOnValidThread()); |
| 1205 DCHECK(addresses); | 1365 DCHECK(addresses); |
| 1206 | 1366 |
| 1207 // Make a log item for the request. | 1367 // Make a log item for the request. |
| 1208 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, | 1368 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, |
| 1209 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); | 1369 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); |
| 1210 | 1370 |
| 1211 // Update the net log and notify registered observers. | 1371 // Update the net log and notify registered observers. |
| 1212 OnStartRequest(source_net_log, request_net_log, info); | 1372 LogStartRequest(source_net_log, request_net_log, info); |
| 1213 | 1373 |
| 1214 // Build a key that identifies the request in the cache and in the | |
| 1215 // outstanding jobs map. | |
| 1216 Key key = GetEffectiveKeyForRequest(info); | 1374 Key key = GetEffectiveKeyForRequest(info); |
| 1217 | 1375 |
| 1218 int rv = ResolveHelper(key, info, addresses, request_net_log); | 1376 int rv = ResolveHelper(key, info, addresses, request_net_log); |
| 1219 OnFinishRequest(source_net_log, request_net_log, info, | 1377 LogFinishRequest(source_net_log, request_net_log, info, rv, |
| 1220 rv, | 1378 0 /* os_error (unknown since from cache) */); |
| 1221 0 /* os_error (unknown since from cache) */); | |
| 1222 return rv; | 1379 return rv; |
| 1223 } | 1380 } |
| 1224 | 1381 |
| 1225 // See OnJobComplete(Job*) for why it is important not to clean out | |
| 1226 // cancelled requests from Job::requests_. | |
| 1227 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { | 1382 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { |
| 1228 DCHECK(CalledOnValidThread()); | 1383 DCHECK(CalledOnValidThread()); |
| 1229 Request* req = reinterpret_cast<Request*>(req_handle); | 1384 Request* req = reinterpret_cast<Request*>(req_handle); |
| 1230 DCHECK(req); | 1385 DCHECK(req); |
| 1231 | 1386 |
| 1232 scoped_ptr<Request> request_deleter; // Frees at end of function. | 1387 Job* job = req->job(); |
| 1388 DCHECK(job); | |
| 1233 | 1389 |
| 1234 if (!req->job()) { | 1390 job->CancelRequest(req); |
| 1235 // If the request was not attached to a job yet, it must have been | 1391 |
| 1236 // enqueued into a pool. Remove it from that pool's queue. | 1392 if (!job->handle().is_null()) { |
| 1237 // Otherwise if it was attached to a job, the job is responsible for | 1393 // Still in queue. |
| 1238 // deleting it. | 1394 if (job->num_active_requests()) { |
| 1239 JobPool* pool = GetPoolForRequest(req); | 1395 job->set_handle(dispatcher_.ChangePriority(job->handle(), |
| 1240 pool->RemovePendingRequest(req); | 1396 job->priority())); |
| 1241 request_deleter.reset(req); | 1397 } else { |
| 1398 dispatcher_.Cancel(job->handle()); | |
| 1399 RemoveJob(job); | |
| 1400 delete job; | |
| 1401 } | |
| 1242 } else { | 1402 } else { |
| 1243 req->request_net_log().EndEvent( | 1403 // Job is running (and could be in CompleteRequests right now). |
| 1244 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL); | 1404 // But to be in Request::OnComplete we would have to have a non-canceled |
| 1405 // request. So it is safe to Abort it if it has no more active requests. | |
| 1406 if (!job->num_active_requests()) { | |
| 1407 job->Abort(); | |
| 1408 } | |
| 1245 } | 1409 } |
| 1246 | |
| 1247 // NULL out the fields of req, to mark it as cancelled. | |
| 1248 req->MarkAsCancelled(); | |
| 1249 OnCancelRequest(req->source_net_log(), req->request_net_log(), req->info()); | |
| 1250 } | 1410 } |
| 1251 | 1411 |
| 1252 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { | 1412 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
| 1253 DCHECK(CalledOnValidThread()); | 1413 DCHECK(CalledOnValidThread()); |
| 1254 ipv6_probe_monitoring_ = false; | 1414 ipv6_probe_monitoring_ = false; |
| 1255 DiscardIPv6ProbeJob(); | 1415 DiscardIPv6ProbeJob(); |
| 1256 default_address_family_ = address_family; | 1416 default_address_family_ = address_family; |
| 1257 } | 1417 } |
| 1258 | 1418 |
| 1259 AddressFamily HostResolverImpl::GetDefaultAddressFamily() const { | 1419 AddressFamily HostResolverImpl::GetDefaultAddressFamily() const { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1278 DCHECK(addresses); | 1438 DCHECK(addresses); |
| 1279 DCHECK(net_error); | 1439 DCHECK(net_error); |
| 1280 IPAddressNumber ip_number; | 1440 IPAddressNumber ip_number; |
| 1281 if (!ParseIPLiteralToNumber(key.hostname, &ip_number)) | 1441 if (!ParseIPLiteralToNumber(key.hostname, &ip_number)) |
| 1282 return false; | 1442 return false; |
| 1283 | 1443 |
| 1284 DCHECK_EQ(key.host_resolver_flags & | 1444 DCHECK_EQ(key.host_resolver_flags & |
| 1285 ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY | | 1445 ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY | |
| 1286 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6), | 1446 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6), |
| 1287 0) << " Unhandled flag"; | 1447 0) << " Unhandled flag"; |
| 1288 bool ipv6_disabled = default_address_family_ == ADDRESS_FAMILY_IPV4 && | 1448 bool ipv6_disabled = (default_address_family_ == ADDRESS_FAMILY_IPV4) && |
| 1289 !ipv6_probe_monitoring_; | 1449 !ipv6_probe_monitoring_; |
| 1290 *net_error = OK; | 1450 *net_error = OK; |
| 1291 if (ip_number.size() == 16 && ipv6_disabled) { | 1451 if ((ip_number.size() == kIPv6AddressSize) && ipv6_disabled) { |
| 1292 *net_error = ERR_NAME_NOT_RESOLVED; | 1452 *net_error = ERR_NAME_NOT_RESOLVED; |
| 1293 } else { | 1453 } else { |
| 1294 *addresses = AddressList::CreateFromIPAddressWithCname( | 1454 *addresses = AddressList::CreateFromIPAddressWithCname( |
| 1295 ip_number, info.port(), | 1455 ip_number, info.port(), |
| 1296 (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)); | 1456 (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)); |
| 1297 } | 1457 } |
| 1298 return true; | 1458 return true; |
| 1299 } | 1459 } |
| 1300 | 1460 |
| 1301 bool HostResolverImpl::ServeFromCache(const Key& key, | 1461 bool HostResolverImpl::ServeFromCache(const Key& key, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1313 if (!cache_entry) | 1473 if (!cache_entry) |
| 1314 return false; | 1474 return false; |
| 1315 | 1475 |
| 1316 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1476 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
| 1317 *net_error = cache_entry->error; | 1477 *net_error = cache_entry->error; |
| 1318 if (*net_error == OK) | 1478 if (*net_error == OK) |
| 1319 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1479 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
| 1320 return true; | 1480 return true; |
| 1321 } | 1481 } |
| 1322 | 1482 |
| 1323 void HostResolverImpl::AddOutstandingJob(Job* job) { | 1483 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { |
| 1324 scoped_refptr<Job>& found_job = jobs_[job->key()]; | 1484 DCHECK(job); |
| 1325 DCHECK(!found_job); | 1485 DCHECK(job->handle().is_null()); |
| 1326 found_job = job; | 1486 RemoveJob(job); |
| 1327 | 1487 if (job->net_error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) { |
| 1328 JobPool* pool = GetPoolForRequest(job->initial_request()); | 1488 // Signal dispatcher that a slot has opened. |
| 1329 pool->AdjustNumOutstandingJobs(1); | 1489 dispatcher_.OnJobFinished(); |
| 1490 return; | |
| 1491 } | |
| 1492 if (job->net_error() == ERR_ABORTED) | |
| 1493 return; | |
| 1494 // Write result to the cache. | |
| 1495 if (cache_.get()) | |
| 1496 cache_->Set(job->key(), job->net_error(), addrlist, | |
| 1497 base::TimeTicks::Now()); | |
| 1330 } | 1498 } |
| 1331 | 1499 |
| 1332 HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(const Key& key) { | 1500 void HostResolverImpl::RemoveJob(Job* job) { |
| 1333 JobMap::iterator it = jobs_.find(key); | 1501 DCHECK(job); |
| 1334 if (it != jobs_.end()) | 1502 jobs_.erase(job->key()); |
| 1335 return it->second; | |
| 1336 return NULL; | |
| 1337 } | |
| 1338 | |
| 1339 void HostResolverImpl::RemoveOutstandingJob(Job* job) { | |
| 1340 JobMap::iterator it = jobs_.find(job->key()); | |
| 1341 DCHECK(it != jobs_.end()); | |
| 1342 DCHECK_EQ(it->second.get(), job); | |
| 1343 jobs_.erase(it); | |
| 1344 | |
| 1345 JobPool* pool = GetPoolForRequest(job->initial_request()); | |
| 1346 pool->AdjustNumOutstandingJobs(-1); | |
| 1347 } | |
| 1348 | |
| 1349 void HostResolverImpl::OnJobComplete(Job* job, | |
| 1350 int net_error, | |
| 1351 int os_error, | |
| 1352 const AddressList& addrlist) { | |
| 1353 RemoveOutstandingJob(job); | |
| 1354 | |
| 1355 // Write result to the cache. | |
| 1356 if (cache_.get()) | |
| 1357 cache_->Set(job->key(), net_error, addrlist, base::TimeTicks::Now()); | |
| 1358 | |
| 1359 OnJobCompleteInternal(job, net_error, os_error, addrlist); | |
| 1360 } | |
| 1361 | |
| 1362 void HostResolverImpl::AbortJob(Job* job) { | |
| 1363 OnJobCompleteInternal(job, ERR_ABORTED, 0 /* no os_error */, AddressList()); | |
| 1364 } | |
| 1365 | |
| 1366 void HostResolverImpl::OnJobCompleteInternal( | |
| 1367 Job* job, | |
| 1368 int net_error, | |
| 1369 int os_error, | |
| 1370 const AddressList& addrlist) { | |
| 1371 // Make a note that we are executing within OnJobComplete() in case the | |
| 1372 // HostResolver is deleted by a callback invocation. | |
| 1373 DCHECK(!cur_completing_job_); | |
| 1374 cur_completing_job_ = job; | |
| 1375 | |
| 1376 // Try to start any queued requests now that a job-slot has freed up. | |
| 1377 ProcessQueuedRequests(); | |
| 1378 | |
| 1379 // Complete all of the requests that were attached to the job. | |
| 1380 for (RequestsList::const_iterator it = job->requests().begin(); | |
| 1381 it != job->requests().end(); ++it) { | |
| 1382 Request* req = *it; | |
| 1383 if (!req->was_cancelled()) { | |
| 1384 DCHECK_EQ(job, req->job()); | |
| 1385 req->request_net_log().EndEvent( | |
| 1386 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL); | |
| 1387 | |
| 1388 // Update the net log and notify registered observers. | |
| 1389 OnFinishRequest(req->source_net_log(), req->request_net_log(), | |
| 1390 req->info(), net_error, os_error); | |
| 1391 | |
| 1392 req->OnComplete(net_error, addrlist); | |
| 1393 | |
| 1394 // Check if the job was cancelled as a result of running the callback. | |
| 1395 // (Meaning that |this| was deleted). | |
| 1396 if (job->was_cancelled()) | |
| 1397 return; | |
| 1398 } | |
| 1399 } | |
| 1400 | |
| 1401 cur_completing_job_ = NULL; | |
| 1402 } | |
| 1403 | |
| 1404 void HostResolverImpl::OnStartRequest(const BoundNetLog& source_net_log, | |
| 1405 const BoundNetLog& request_net_log, | |
| 1406 const RequestInfo& info) { | |
| 1407 source_net_log.BeginEvent( | |
| 1408 NetLog::TYPE_HOST_RESOLVER_IMPL, | |
| 1409 make_scoped_refptr(new NetLogSourceParameter( | |
| 1410 "source_dependency", request_net_log.source()))); | |
| 1411 | |
| 1412 request_net_log.BeginEvent( | |
| 1413 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, | |
| 1414 make_scoped_refptr(new RequestInfoParameters( | |
| 1415 info, source_net_log.source()))); | |
| 1416 } | |
| 1417 | |
| 1418 void HostResolverImpl::OnFinishRequest(const BoundNetLog& source_net_log, | |
| 1419 const BoundNetLog& request_net_log, | |
| 1420 const RequestInfo& info, | |
| 1421 int net_error, | |
| 1422 int os_error) { | |
| 1423 bool was_resolved = net_error == OK; | |
| 1424 | |
| 1425 // Log some extra parameters on failure for synchronous requests. | |
| 1426 scoped_refptr<NetLog::EventParameters> params; | |
| 1427 if (!was_resolved) { | |
| 1428 params = new HostResolveFailedParams(0, net_error, os_error); | |
| 1429 } | |
| 1430 | |
| 1431 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params); | |
| 1432 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | |
| 1433 } | |
| 1434 | |
| 1435 void HostResolverImpl::OnCancelRequest(const BoundNetLog& source_net_log, | |
| 1436 const BoundNetLog& request_net_log, | |
| 1437 const RequestInfo& info) { | |
| 1438 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 1439 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | |
| 1440 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | |
| 1441 } | 1503 } |
| 1442 | 1504 |
| 1443 void HostResolverImpl::DiscardIPv6ProbeJob() { | 1505 void HostResolverImpl::DiscardIPv6ProbeJob() { |
| 1444 if (ipv6_probe_job_.get()) { | 1506 if (ipv6_probe_job_.get()) { |
| 1445 ipv6_probe_job_->Cancel(); | 1507 ipv6_probe_job_->Cancel(); |
| 1446 ipv6_probe_job_ = NULL; | 1508 ipv6_probe_job_ = NULL; |
| 1447 } | 1509 } |
| 1448 } | 1510 } |
| 1449 | 1511 |
| 1450 void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( | 1512 void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( |
| 1451 AddressFamily address_family) { | 1513 AddressFamily address_family) { |
| 1452 DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || | 1514 DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || |
| 1453 address_family == ADDRESS_FAMILY_IPV4); | 1515 address_family == ADDRESS_FAMILY_IPV4); |
| 1454 if (default_address_family_ != address_family) { | 1516 if (default_address_family_ != address_family) { |
| 1455 VLOG(1) << "IPv6Probe forced AddressFamily setting to " | 1517 VLOG(1) << "IPv6Probe forced AddressFamily setting to " |
| 1456 << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ? | 1518 << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ? |
| 1457 "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4"); | 1519 "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4"); |
| 1458 } | 1520 } |
| 1459 default_address_family_ = address_family; | 1521 default_address_family_ = address_family; |
| 1460 // Drop reference since the job has called us back. | 1522 // Drop reference since the job has called us back. |
| 1461 DiscardIPv6ProbeJob(); | 1523 DiscardIPv6ProbeJob(); |
| 1462 } | 1524 } |
| 1463 | 1525 |
| 1464 bool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const { | |
| 1465 DCHECK_LE(jobs_.size(), max_jobs_); | |
| 1466 | |
| 1467 // We can't create another job if it would exceed the global total. | |
| 1468 if (jobs_.size() + 1 > max_jobs_) | |
| 1469 return false; | |
| 1470 | |
| 1471 // Check whether the pool's constraints are met. | |
| 1472 return pool.CanCreateJob(); | |
| 1473 } | |
| 1474 | |
| 1475 // static | |
| 1476 HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest( | |
| 1477 const Request* req) { | |
| 1478 return POOL_NORMAL; | |
| 1479 } | |
| 1480 | |
| 1481 void HostResolverImpl::ProcessQueuedRequests() { | |
| 1482 // Find the highest priority request that can be scheduled. | |
| 1483 Request* top_req = NULL; | |
| 1484 for (size_t i = 0; i < arraysize(job_pools_); ++i) { | |
| 1485 JobPool* pool = job_pools_[i]; | |
| 1486 if (pool->HasPendingRequests() && CanCreateJobForPool(*pool)) { | |
| 1487 top_req = pool->RemoveTopPendingRequest(); | |
| 1488 break; | |
| 1489 } | |
| 1490 } | |
| 1491 | |
| 1492 if (!top_req) | |
| 1493 return; | |
| 1494 | |
| 1495 scoped_refptr<Job> job(CreateAndStartJob(top_req)); | |
| 1496 | |
| 1497 // Search for any other pending request which can piggy-back off this job. | |
| 1498 for (size_t pool_i = 0; pool_i < POOL_COUNT; ++pool_i) { | |
| 1499 JobPool* pool = job_pools_[pool_i]; | |
| 1500 pool->MoveRequestsToJob(job); | |
| 1501 } | |
| 1502 } | |
| 1503 | |
| 1504 HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( | 1526 HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( |
| 1505 const RequestInfo& info) const { | 1527 const RequestInfo& info) const { |
| 1506 HostResolverFlags effective_flags = | 1528 HostResolverFlags effective_flags = |
| 1507 info.host_resolver_flags() | additional_resolver_flags_; | 1529 info.host_resolver_flags() | additional_resolver_flags_; |
| 1508 AddressFamily effective_address_family = info.address_family(); | 1530 AddressFamily effective_address_family = info.address_family(); |
| 1509 if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED && | 1531 if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED && |
| 1510 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { | 1532 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { |
| 1511 effective_address_family = default_address_family_; | 1533 effective_address_family = default_address_family_; |
| 1512 if (ipv6_probe_monitoring_) | 1534 if (ipv6_probe_monitoring_) |
| 1513 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; | 1535 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; |
| 1514 } | 1536 } |
| 1515 return Key(info.hostname(), effective_address_family, effective_flags); | 1537 return Key(info.hostname(), effective_address_family, effective_flags); |
| 1516 } | 1538 } |
| 1517 | 1539 |
| 1518 HostResolverImpl::Job* HostResolverImpl::CreateAndStartJob(Request* req) { | |
| 1519 DCHECK(CanCreateJobForPool(*GetPoolForRequest(req))); | |
| 1520 Key key = GetEffectiveKeyForRequest(req->info()); | |
| 1521 | |
| 1522 req->request_net_log().AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, | |
| 1523 NULL); | |
| 1524 | |
| 1525 scoped_refptr<Job> job(new Job(next_job_id_++, this, key, | |
| 1526 req->request_net_log(), net_log_)); | |
| 1527 job->AddRequest(req); | |
| 1528 AddOutstandingJob(job); | |
| 1529 job->Start(); | |
| 1530 | |
| 1531 return job.get(); | |
| 1532 } | |
| 1533 | |
| 1534 int HostResolverImpl::EnqueueRequest(JobPool* pool, Request* req) { | |
| 1535 scoped_ptr<Request> req_evicted_from_queue( | |
| 1536 pool->InsertPendingRequest(req)); | |
| 1537 | |
| 1538 // If the queue has become too large, we need to kick something out. | |
| 1539 if (req_evicted_from_queue.get()) { | |
| 1540 Request* r = req_evicted_from_queue.get(); | |
| 1541 int error = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | |
| 1542 | |
| 1543 OnFinishRequest(r->source_net_log(), r->request_net_log(), r->info(), error, | |
| 1544 0 /* os_error (not applicable) */); | |
| 1545 | |
| 1546 if (r == req) | |
| 1547 return error; | |
| 1548 | |
| 1549 r->OnComplete(error, AddressList()); | |
| 1550 } | |
| 1551 | |
| 1552 return ERR_IO_PENDING; | |
| 1553 } | |
| 1554 | |
| 1555 void HostResolverImpl::CancelAllJobs() { | |
| 1556 JobMap jobs; | |
| 1557 jobs.swap(jobs_); | |
| 1558 for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it) | |
| 1559 it->second->Cancel(); | |
| 1560 } | |
| 1561 | |
| 1562 void HostResolverImpl::AbortAllInProgressJobs() { | 1540 void HostResolverImpl::AbortAllInProgressJobs() { |
| 1563 for (size_t i = 0; i < arraysize(job_pools_); ++i) | 1541 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); |
| 1564 job_pools_[i]->ResetNumOutstandingJobs(); | 1542 // Scan |jobs_| for running jobs and abort them. |
| 1565 JobMap jobs; | 1543 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { |
| 1566 jobs.swap(jobs_); | 1544 Job* job = it->second; |
| 1567 for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it) { | 1545 // Advance the iterator before we might erase it. |
| 1568 AbortJob(it->second); | 1546 ++it; |
| 1569 it->second->Cancel(); | 1547 if (job->is_running()) { |
| 1548 job->Abort(); | |
| 1549 // Check if resolver was deleted in a request callback. | |
| 1550 if (!self) | |
| 1551 return; | |
| 1552 } else { | |
| 1553 // Keep it in |dispatch_|. | |
| 1554 DCHECK(!job->handle().is_null()); | |
| 1555 } | |
| 1570 } | 1556 } |
| 1571 } | 1557 } |
| 1572 | 1558 |
| 1573 void HostResolverImpl::OnIPAddressChanged() { | 1559 void HostResolverImpl::OnIPAddressChanged() { |
| 1574 if (cache_.get()) | 1560 if (cache_.get()) |
| 1575 cache_->clear(); | 1561 cache_->clear(); |
| 1576 if (ipv6_probe_monitoring_) { | 1562 if (ipv6_probe_monitoring_) { |
| 1577 DiscardIPv6ProbeJob(); | 1563 DiscardIPv6ProbeJob(); |
| 1578 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1564 ipv6_probe_job_ = new IPv6ProbeJob(this); |
| 1579 ipv6_probe_job_->Start(); | 1565 ipv6_probe_job_->Start(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1596 // resolv.conf changes so we don't need to do anything to clear that cache. | 1582 // resolv.conf changes so we don't need to do anything to clear that cache. |
| 1597 if (cache_.get()) | 1583 if (cache_.get()) |
| 1598 cache_->clear(); | 1584 cache_->clear(); |
| 1599 // Existing jobs will have been sent to the original server so they need to | 1585 // Existing jobs will have been sent to the original server so they need to |
| 1600 // be aborted. TODO(Craig): Should these jobs be restarted? | 1586 // be aborted. TODO(Craig): Should these jobs be restarted? |
| 1601 AbortAllInProgressJobs(); | 1587 AbortAllInProgressJobs(); |
| 1602 // |this| may be deleted inside AbortAllInProgressJobs(). | 1588 // |this| may be deleted inside AbortAllInProgressJobs(). |
| 1603 } | 1589 } |
| 1604 | 1590 |
| 1605 } // namespace net | 1591 } // namespace net |
| OLD | NEW |