OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/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 <utility> | 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/callback.h" |
21 #include "base/compiler_specific.h" | 21 #include "base/compiler_specific.h" |
22 #include "base/debug/debugger.h" | 22 #include "base/debug/debugger.h" |
23 #include "base/debug/stack_trace.h" | 23 #include "base/debug/stack_trace.h" |
24 #include "base/message_loop_proxy.h" | 24 #include "base/message_loop_proxy.h" |
25 #include "base/metrics/field_trial.h" | 25 #include "base/metrics/field_trial.h" |
26 #include "base/metrics/histogram.h" | 26 #include "base/metrics/histogram.h" |
27 #include "base/rand_util.h" | |
27 #include "base/stl_util.h" | 28 #include "base/stl_util.h" |
28 #include "base/string_util.h" | 29 #include "base/string_util.h" |
29 #include "base/threading/worker_pool.h" | 30 #include "base/threading/worker_pool.h" |
30 #include "base/time.h" | 31 #include "base/time.h" |
31 #include "base/utf_string_conversions.h" | 32 #include "base/utf_string_conversions.h" |
32 #include "base/values.h" | 33 #include "base/values.h" |
34 #include "net/base/address_family.h" | |
33 #include "net/base/address_list.h" | 35 #include "net/base/address_list.h" |
34 #include "net/base/address_list_net_log_param.h" | 36 #include "net/base/address_list_net_log_param.h" |
35 #include "net/base/dns_reloader.h" | 37 #include "net/base/dns_reloader.h" |
36 #include "net/base/host_port_pair.h" | 38 #include "net/base/host_port_pair.h" |
37 #include "net/base/host_resolver_proc.h" | 39 #include "net/base/host_resolver_proc.h" |
38 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
39 #include "net/base/net_log.h" | 41 #include "net/base/net_log.h" |
40 #include "net/base/net_util.h" | 42 #include "net/base/net_util.h" |
43 #include "net/dns/dns_config_service.h" | |
44 #include "net/dns/dns_protocol.h" | |
45 #include "net/dns/dns_response.h" | |
46 #include "net/dns/dns_session.h" | |
47 #include "net/dns/dns_transaction.h" | |
48 #include "net/socket/client_socket_factory.h" | |
41 | 49 |
42 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
43 #include "net/base/winsock_init.h" | 51 #include "net/base/winsock_init.h" |
44 #endif | 52 #endif |
45 | 53 |
46 namespace net { | 54 namespace net { |
47 | 55 |
48 namespace { | 56 namespace { |
49 | 57 |
50 // Limit the size of hostnames that will be resolved to combat issues in | 58 // Limit the size of hostnames that will be resolved to combat issues in |
51 // some platform's resolvers. | 59 // some platform's resolvers. |
52 const size_t kMaxHostLength = 4096; | 60 const size_t kMaxHostLength = 4096; |
53 | 61 |
54 // Default TTL for successful resolutions with ProcTask. | 62 // Default TTL for successful resolutions with ProcTask. |
55 const unsigned kCacheEntryTTLSeconds = 60; | 63 const unsigned kCacheEntryTTLSeconds = 60; |
56 | 64 |
65 // Default TTL for unsuccessful resolutions with ProcTask. | |
66 const unsigned kNegativeCacheEntryTTLSeconds = 0; | |
67 | |
57 // Maximum of 8 concurrent resolver threads (excluding retries). | 68 // Maximum of 8 concurrent resolver threads (excluding retries). |
58 // Some routers (or resolvers) appear to start to provide host-not-found if | 69 // Some routers (or resolvers) appear to start to provide host-not-found if |
59 // too many simultaneous resolutions are pending. This number needs to be | 70 // too many simultaneous resolutions are pending. This number needs to be |
60 // further optimized, but 8 is what FF currently does. | 71 // further optimized, but 8 is what FF currently does. |
61 static const size_t kDefaultMaxProcTasks = 8u; | 72 static const size_t kDefaultMaxProcTasks = 8u; |
62 | 73 |
63 // Helper to mutate the linked list contained by AddressList to the given | 74 // Helper to mutate the linked list contained by AddressList to the given |
64 // port. Note that in general this is dangerous since the AddressList's | 75 // port. Note that in general this is dangerous since the AddressList's |
65 // data might be shared (and you should use AddressList::SetPort). | 76 // data might be shared (and you should use AddressList::SetPort). |
66 // | 77 // |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 int* os_error) OVERRIDE { | 159 int* os_error) OVERRIDE { |
149 return SystemHostResolverProc(hostname, | 160 return SystemHostResolverProc(hostname, |
150 address_family, | 161 address_family, |
151 host_resolver_flags, | 162 host_resolver_flags, |
152 addrlist, | 163 addrlist, |
153 os_error); | 164 os_error); |
154 } | 165 } |
155 }; | 166 }; |
156 | 167 |
157 // Extra parameters to attach to the NetLog when the resolve failed. | 168 // Extra parameters to attach to the NetLog when the resolve failed. |
158 class HostResolveFailedParams : public NetLog::EventParameters { | 169 class ProcTaskFailedParams : public NetLog::EventParameters { |
159 public: | 170 public: |
160 HostResolveFailedParams(uint32 attempt_number, | 171 ProcTaskFailedParams(uint32 attempt_number, int net_error, int os_error) |
161 int net_error, | |
162 int os_error) | |
163 : attempt_number_(attempt_number), | 172 : attempt_number_(attempt_number), |
164 net_error_(net_error), | 173 net_error_(net_error), |
165 os_error_(os_error) { | 174 os_error_(os_error) { |
166 } | 175 } |
167 | 176 |
168 virtual Value* ToValue() const OVERRIDE { | 177 virtual Value* ToValue() const OVERRIDE { |
169 DictionaryValue* dict = new DictionaryValue(); | 178 DictionaryValue* dict = new DictionaryValue(); |
170 if (attempt_number_) | 179 if (attempt_number_) |
171 dict->SetInteger("attempt_number", attempt_number_); | 180 dict->SetInteger("attempt_number", attempt_number_); |
172 | 181 |
(...skipping 21 matching lines...) Expand all Loading... | |
194 | 203 |
195 return dict; | 204 return dict; |
196 } | 205 } |
197 | 206 |
198 private: | 207 private: |
199 const uint32 attempt_number_; | 208 const uint32 attempt_number_; |
200 const int net_error_; | 209 const int net_error_; |
201 const int os_error_; | 210 const int os_error_; |
202 }; | 211 }; |
203 | 212 |
213 // Extra parameters to attach to the NetLog when the DnsTask failed. | |
214 class DnsTaskFailedParams : public NetLog::EventParameters { | |
215 public: | |
216 DnsTaskFailedParams(int net_error, int dns_error) | |
217 : net_error_(net_error), dns_error_(dns_error) { | |
218 } | |
219 | |
220 virtual Value* ToValue() const OVERRIDE { | |
221 DictionaryValue* dict = new DictionaryValue(); | |
222 dict->SetInteger("net_error", net_error_); | |
223 if (dns_error_) | |
224 dict->SetInteger("dns_error", dns_error_); | |
225 return dict; | |
226 } | |
227 | |
228 private: | |
229 const int net_error_; | |
230 const int dns_error_; | |
231 }; | |
232 | |
204 // Parameters representing the information in a RequestInfo object, along with | 233 // Parameters representing the information in a RequestInfo object, along with |
205 // the associated NetLog::Source. | 234 // the associated NetLog::Source. |
206 class RequestInfoParameters : public NetLog::EventParameters { | 235 class RequestInfoParameters : public NetLog::EventParameters { |
207 public: | 236 public: |
208 RequestInfoParameters(const HostResolver::RequestInfo& info, | 237 RequestInfoParameters(const HostResolver::RequestInfo& info, |
209 const NetLog::Source& source) | 238 const NetLog::Source& source) |
210 : info_(info), source_(source) {} | 239 : info_(info), source_(source) {} |
211 | 240 |
212 virtual Value* ToValue() const OVERRIDE { | 241 virtual Value* ToValue() const OVERRIDE { |
213 DictionaryValue* dict = new DictionaryValue(); | 242 DictionaryValue* dict = new DictionaryValue(); |
214 dict->SetString("host", info_.host_port_pair().ToString()); | 243 dict->SetString("host", info_.host_port_pair().ToString()); |
215 dict->SetInteger("address_family", | 244 dict->SetInteger("address_family", |
216 static_cast<int>(info_.address_family())); | 245 static_cast<int>(info_.address_family())); |
217 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); | 246 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); |
218 dict->SetBoolean("is_speculative", info_.is_speculative()); | 247 dict->SetBoolean("is_speculative", info_.is_speculative()); |
219 dict->SetInteger("priority", info_.priority()); | 248 dict->SetInteger("priority", info_.priority()); |
220 | 249 |
221 if (source_.is_valid()) | 250 if (source_.is_valid()) |
222 dict->Set("source_dependency", source_.ToValue()); | 251 dict->Set("source_dependency", source_.ToValue()); |
223 | 252 |
224 return dict; | 253 return dict; |
225 } | 254 } |
226 | 255 |
227 private: | 256 private: |
228 const HostResolver::RequestInfo info_; | 257 const HostResolver::RequestInfo info_; |
229 const NetLog::Source source_; | 258 const NetLog::Source source_; |
230 }; | 259 }; |
231 | 260 |
232 // Parameters associated with the creation of a HostResolverImpl::Job | 261 // Parameters associated with the creation of a HostResolverImpl::Job. |
233 // or a HostResolverImpl::ProcTask. | |
234 class JobCreationParameters : public NetLog::EventParameters { | 262 class JobCreationParameters : public NetLog::EventParameters { |
235 public: | 263 public: |
236 JobCreationParameters(const std::string& host, | 264 JobCreationParameters(const std::string& host, |
237 const NetLog::Source& source) | 265 const NetLog::Source& source) |
238 : host_(host), source_(source) {} | 266 : host_(host), source_(source) {} |
239 | 267 |
240 virtual Value* ToValue() const OVERRIDE { | 268 virtual Value* ToValue() const OVERRIDE { |
241 DictionaryValue* dict = new DictionaryValue(); | 269 DictionaryValue* dict = new DictionaryValue(); |
242 dict->SetString("host", host_); | 270 dict->SetString("host", host_); |
243 dict->Set("source_dependency", source_.ToValue()); | 271 dict->Set("source_dependency", source_.ToValue()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 } | 315 } |
288 | 316 |
289 // Logs when a request has just completed (before its callback is run). | 317 // Logs when a request has just completed (before its callback is run). |
290 void LogFinishRequest(const BoundNetLog& source_net_log, | 318 void LogFinishRequest(const BoundNetLog& source_net_log, |
291 const BoundNetLog& request_net_log, | 319 const BoundNetLog& request_net_log, |
292 const HostResolver::RequestInfo& info, | 320 const HostResolver::RequestInfo& info, |
293 int net_error, | 321 int net_error, |
294 int os_error) { | 322 int os_error) { |
295 scoped_refptr<NetLog::EventParameters> params; | 323 scoped_refptr<NetLog::EventParameters> params; |
296 if (net_error != OK) { | 324 if (net_error != OK) { |
297 params = new HostResolveFailedParams(0, net_error, os_error); | 325 params = new ProcTaskFailedParams(0, net_error, os_error); |
298 } | 326 } |
299 | 327 |
300 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params); | 328 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params); |
301 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 329 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
302 } | 330 } |
303 | 331 |
304 // Logs when a request has been cancelled. | 332 // Logs when a request has been cancelled. |
305 void LogCancelRequest(const BoundNetLog& source_net_log, | 333 void LogCancelRequest(const BoundNetLog& source_net_log, |
306 const BoundNetLog& request_net_log, | 334 const BoundNetLog& request_net_log, |
307 const HostResolverImpl::RequestInfo& info) { | 335 const HostResolverImpl::RequestInfo& info) { |
308 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 336 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
309 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | 337 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); |
310 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 338 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
311 } | 339 } |
312 | 340 |
313 //----------------------------------------------------------------------------- | 341 //----------------------------------------------------------------------------- |
314 | 342 |
315 // Keeps track of the highest priority. | 343 // Keeps track of the highest priority. |
316 class PriorityTracker { | 344 class PriorityTracker { |
317 public: | 345 public: |
318 PriorityTracker() | 346 explicit PriorityTracker(RequestPriority priority) |
319 : highest_priority_(IDLE), total_count_(0) { | 347 : highest_priority_(priority), total_count_(0) { |
320 memset(counts_, 0, sizeof(counts_)); | 348 memset(counts_, 0, sizeof(counts_)); |
321 } | 349 } |
322 | 350 |
323 RequestPriority highest_priority() const { | 351 RequestPriority highest_priority() const { |
324 return highest_priority_; | 352 return highest_priority_; |
325 } | 353 } |
326 | 354 |
327 size_t total_count() const { | 355 size_t total_count() const { |
328 return total_count_; | 356 return total_count_; |
329 } | 357 } |
(...skipping 22 matching lines...) Expand all Loading... | |
352 } | 380 } |
353 | 381 |
354 private: | 382 private: |
355 RequestPriority highest_priority_; | 383 RequestPriority highest_priority_; |
356 size_t total_count_; | 384 size_t total_count_; |
357 size_t counts_[NUM_PRIORITIES]; | 385 size_t counts_[NUM_PRIORITIES]; |
358 }; | 386 }; |
359 | 387 |
360 //----------------------------------------------------------------------------- | 388 //----------------------------------------------------------------------------- |
361 | 389 |
390 // Convenience wrapper for PrioritizedDispatcher::Handle so that we don't forget | |
391 // to update it when cancelling or changing the priority. | |
mmenke
2012/02/15 19:54:16
nit: canceling.
szym
2012/02/15 20:28:05
I think the consensus was that it's okay to use no
| |
392 // TODO(szym): consider making PrioritizedDispatcher::Handle into this. | |
393 class DispatcherHandle { | |
cbentzel
2012/02/15 19:48:35
Is this needed as much anymore, since you're restr
szym
2012/02/15 20:28:05
I prefer this over having to remember to set handl
| |
394 public: | |
395 DispatcherHandle() : dispatcher_(NULL) {} | |
396 DispatcherHandle(PrioritizedDispatcher* dispatcher, | |
397 const PrioritizedDispatcher::Handle& handle) | |
398 : dispatcher_(dispatcher), handle_(handle) { | |
399 if (handle_.is_null()) | |
400 dispatcher_ = NULL; | |
401 } | |
402 | |
403 bool is_null() const { | |
404 return dispatcher_ == NULL; | |
405 } | |
406 | |
407 void Reset() { | |
408 dispatcher_ = NULL; | |
409 handle_ = PrioritizedDispatcher::Handle(); | |
410 } | |
411 | |
412 void ChangePriority(RequestPriority priority) { | |
413 DCHECK(!is_null()); | |
414 handle_ = dispatcher_->ChangePriority(handle_, priority); | |
415 } | |
416 | |
417 void Cancel() { | |
418 DCHECK(!is_null()); | |
419 dispatcher_->Cancel(handle_); | |
420 Reset(); | |
421 } | |
422 | |
423 private: | |
424 PrioritizedDispatcher* dispatcher_; | |
425 PrioritizedDispatcher::Handle handle_; | |
426 }; | |
427 | |
428 //----------------------------------------------------------------------------- | |
429 | |
362 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, | 430 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, |
363 size_t max_retry_attempts, | 431 size_t max_retry_attempts, |
364 bool use_cache, | 432 HostCache* cache, |
433 scoped_ptr<DnsConfigService> config_service, | |
365 NetLog* net_log) { | 434 NetLog* net_log) { |
366 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | 435 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) |
367 max_concurrent_resolves = kDefaultMaxProcTasks; | 436 max_concurrent_resolves = kDefaultMaxProcTasks; |
368 | 437 |
369 // TODO(szym): Add experiments with reserved slots for higher priority | 438 // TODO(szym): Add experiments with reserved slots for higher priority |
370 // requests. | 439 // requests. |
371 | 440 |
372 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); | 441 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); |
373 | 442 |
374 HostResolverImpl* resolver = new HostResolverImpl( | 443 HostResolverImpl* resolver = new HostResolverImpl( |
375 use_cache ? HostCache::CreateDefaultCache() : NULL, | 444 cache, |
376 limits, | 445 limits, |
377 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), | 446 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), |
447 config_service.Pass(), | |
378 net_log); | 448 net_log); |
379 | 449 |
380 return resolver; | 450 return resolver; |
381 } | 451 } |
382 | 452 |
383 } // anonymous namespace | 453 } // anonymous namespace |
384 | 454 |
385 //----------------------------------------------------------------------------- | 455 //----------------------------------------------------------------------------- |
386 | 456 |
387 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | 457 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, |
388 size_t max_retry_attempts, | 458 size_t max_retry_attempts, |
389 NetLog* net_log) { | 459 NetLog* net_log) { |
390 return CreateHostResolver(max_concurrent_resolves, | 460 return CreateHostResolver(max_concurrent_resolves, |
391 max_retry_attempts, | 461 max_retry_attempts, |
392 true /* use_cache */, | 462 HostCache::CreateDefaultCache(), |
463 scoped_ptr<DnsConfigService>(NULL), | |
393 net_log); | 464 net_log); |
394 } | 465 } |
395 | 466 |
396 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, | 467 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, |
397 size_t max_retry_attempts, | 468 size_t max_retry_attempts, |
398 NetLog* net_log) { | 469 NetLog* net_log) { |
399 return CreateHostResolver(max_concurrent_resolves, | 470 return CreateHostResolver(max_concurrent_resolves, |
400 max_retry_attempts, | 471 max_retry_attempts, |
401 false /* use_cache */, | 472 NULL, |
473 scoped_ptr<DnsConfigService>(NULL), | |
402 net_log); | 474 net_log); |
403 } | 475 } |
404 | 476 |
477 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, | |
478 size_t max_retry_attempts, | |
479 NetLog* net_log) { | |
480 scoped_ptr<DnsConfigService> config_service = | |
481 DnsConfigService::CreateSystemService(); | |
482 config_service->Watch(); | |
cbentzel
2012/02/15 19:48:35
Should Watch be called by HostResolverImpl, so it
szym
2012/02/15 20:28:05
I'll move it although it doesn't matter: DnsConfig
| |
483 return CreateHostResolver(max_concurrent_resolves, | |
484 max_retry_attempts, | |
485 HostCache::CreateDefaultCache(), | |
486 config_service.Pass(), | |
487 net_log); | |
488 } | |
489 | |
405 //----------------------------------------------------------------------------- | 490 //----------------------------------------------------------------------------- |
406 | 491 |
407 // Holds the data for a request that could not be completed synchronously. | 492 // Holds the data for a request that could not be completed synchronously. |
408 // It is owned by a Job. Canceled Requests are only marked as canceled rather | 493 // It is owned by a Job. Canceled Requests are only marked as canceled rather |
409 // than removed from the Job's |requests_| list. | 494 // than removed from the Job's |requests_| list. |
410 class HostResolverImpl::Request { | 495 class HostResolverImpl::Request { |
411 public: | 496 public: |
412 Request(const BoundNetLog& source_net_log, | 497 Request(const BoundNetLog& source_net_log, |
413 const BoundNetLog& request_net_log, | 498 const BoundNetLog& request_net_log, |
414 const RequestInfo& info, | 499 const RequestInfo& info, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 // resolution (OnLookupComplete) is completed or not. If the original attempt | 583 // resolution (OnLookupComplete) is completed or not. If the original attempt |
499 // hasn't completed, then we start another attempt for host resolution. We take | 584 // hasn't completed, then we start another attempt for host resolution. We take |
500 // the results from the first attempt that finishes and ignore the results from | 585 // the results from the first attempt that finishes and ignore the results from |
501 // all other attempts. | 586 // all other attempts. |
502 // | 587 // |
503 // TODO(szym): Move to separate source file for testing and mocking. | 588 // TODO(szym): Move to separate source file for testing and mocking. |
504 // | 589 // |
505 class HostResolverImpl::ProcTask | 590 class HostResolverImpl::ProcTask |
506 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { | 591 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { |
507 public: | 592 public: |
508 typedef base::Callback<void(int, int, const AddressList&)> Callback; | 593 typedef base::Callback<void(int net_error, |
594 int os_error, | |
595 const AddressList& addr_list)> Callback; | |
509 | 596 |
510 ProcTask(const Key& key, | 597 ProcTask(const Key& key, |
511 const ProcTaskParams& params, | 598 const ProcTaskParams& params, |
512 const Callback& callback, | 599 const Callback& callback, |
513 const BoundNetLog& job_net_log) | 600 const BoundNetLog& job_net_log) |
514 : key_(key), | 601 : key_(key), |
515 params_(params), | 602 params_(params), |
516 callback_(callback), | 603 callback_(callback), |
517 origin_loop_(base::MessageLoopProxy::current()), | 604 origin_loop_(base::MessageLoopProxy::current()), |
518 attempt_number_(0), | 605 attempt_number_(0), |
519 completed_attempt_number_(0), | 606 completed_attempt_number_(0), |
520 completed_attempt_error_(ERR_UNEXPECTED), | 607 completed_attempt_error_(ERR_UNEXPECTED), |
521 had_non_speculative_request_(false), | 608 had_non_speculative_request_(false), |
522 net_log_(BoundNetLog::Make( | 609 net_log_(job_net_log) { |
523 job_net_log.net_log(), | |
524 NetLog::SOURCE_HOST_RESOLVER_IMPL_PROC_TASK)) { | |
525 if (!params_.resolver_proc) | 610 if (!params_.resolver_proc) |
526 params_.resolver_proc = HostResolverProc::GetDefault(); | 611 params_.resolver_proc = HostResolverProc::GetDefault(); |
527 // If default is unset, use the system proc. | 612 // If default is unset, use the system proc. |
528 if (!params_.resolver_proc) | 613 if (!params_.resolver_proc) |
529 params_.resolver_proc = new CallSystemHostResolverProc(); | 614 params_.resolver_proc = new CallSystemHostResolverProc(); |
530 | 615 |
531 job_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_PROC_TASK, | 616 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); |
532 new NetLogSourceParameter("source_dependency", | |
533 net_log_.source())); | |
534 | |
535 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, | |
536 new JobCreationParameters(key_.hostname, | |
537 job_net_log.source())); | |
538 } | 617 } |
539 | 618 |
540 void Start() { | 619 void Start() { |
541 DCHECK(origin_loop_->BelongsToCurrentThread()); | 620 DCHECK(origin_loop_->BelongsToCurrentThread()); |
542 StartLookupAttempt(); | 621 StartLookupAttempt(); |
543 } | 622 } |
544 | 623 |
545 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve | 624 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve |
546 // attempts running on worker threads will continue running. Only once all the | 625 // attempts running on worker threads will continue running. Only once all the |
547 // attempts complete will the final reference to this ProcTask be released. | 626 // attempts complete will the final reference to this ProcTask be released. |
548 void Cancel() { | 627 void Cancel() { |
549 DCHECK(origin_loop_->BelongsToCurrentThread()); | 628 DCHECK(origin_loop_->BelongsToCurrentThread()); |
550 | 629 |
551 if (was_canceled()) | 630 if (was_canceled()) |
552 return; | 631 return; |
553 | 632 |
554 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
555 | |
556 callback_.Reset(); | 633 callback_.Reset(); |
557 | 634 |
558 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); | 635 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); |
559 } | 636 } |
560 | 637 |
561 void set_had_non_speculative_request() { | 638 void set_had_non_speculative_request() { |
562 DCHECK(origin_loop_->BelongsToCurrentThread()); | 639 DCHECK(origin_loop_->BelongsToCurrentThread()); |
563 had_non_speculative_request_ = true; | 640 had_non_speculative_request_ = true; |
564 } | 641 } |
565 | 642 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 const base::TimeTicks& start_time, | 727 const base::TimeTicks& start_time, |
651 const uint32 attempt_number, | 728 const uint32 attempt_number, |
652 int error, | 729 int error, |
653 const int os_error) { | 730 const int os_error) { |
654 DCHECK(origin_loop_->BelongsToCurrentThread()); | 731 DCHECK(origin_loop_->BelongsToCurrentThread()); |
655 DCHECK(error || results.head()); | 732 DCHECK(error || results.head()); |
656 | 733 |
657 bool was_retry_attempt = attempt_number > 1; | 734 bool was_retry_attempt = attempt_number > 1; |
658 | 735 |
659 // Ideally the following code would be part of host_resolver_proc.cc, | 736 // Ideally the following code would be part of host_resolver_proc.cc, |
660 // however it isn't safe to call NetworkChangeNotifier from worker | 737 // however it isn't safe to call NetworkChangeNotifier from worker threads. |
661 // threads. So we do it here on the IO thread instead. | 738 // So we do it here on the IO thread instead. |
662 if (error != OK && NetworkChangeNotifier::IsOffline()) | 739 if (error != OK && NetworkChangeNotifier::IsOffline()) |
663 error = ERR_INTERNET_DISCONNECTED; | 740 error = ERR_INTERNET_DISCONNECTED; |
664 | 741 |
665 // If this is the first attempt that is finishing later, then record | 742 // If this is the first attempt that is finishing later, then record data |
666 // data for the first attempt. Won't contaminate with retry attempt's | 743 // for the first attempt. Won't contaminate with retry attempt's data. |
667 // data. | |
668 if (!was_retry_attempt) | 744 if (!was_retry_attempt) |
669 RecordPerformanceHistograms(start_time, error, os_error); | 745 RecordPerformanceHistograms(start_time, error, os_error); |
670 | 746 |
671 RecordAttemptHistograms(start_time, attempt_number, error, os_error); | 747 RecordAttemptHistograms(start_time, attempt_number, error, os_error); |
672 | 748 |
673 if (was_canceled()) | 749 if (was_canceled()) |
674 return; | 750 return; |
675 | 751 |
676 scoped_refptr<NetLog::EventParameters> params; | 752 scoped_refptr<NetLog::EventParameters> params; |
677 if (error != OK) { | 753 if (error != OK) { |
678 params = new HostResolveFailedParams(attempt_number, error, os_error); | 754 params = new ProcTaskFailedParams(attempt_number, error, os_error); |
679 } else { | 755 } else { |
680 params = new NetLogIntegerParameter("attempt_number", attempt_number); | 756 params = new NetLogIntegerParameter("attempt_number", attempt_number); |
681 } | 757 } |
682 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params); | 758 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params); |
683 | 759 |
684 if (was_completed()) | 760 if (was_completed()) |
685 return; | 761 return; |
686 | 762 |
687 // Copy the results from the first worker thread that resolves the host. | 763 // Copy the results from the first worker thread that resolves the host. |
688 results_ = results; | 764 results_ = results; |
689 completed_attempt_number_ = attempt_number; | 765 completed_attempt_number_ = attempt_number; |
690 completed_attempt_error_ = error; | 766 completed_attempt_error_ = error; |
691 | 767 |
692 if (was_retry_attempt) { | 768 if (was_retry_attempt) { |
693 // If retry attempt finishes before 1st attempt, then get stats on how | 769 // If retry attempt finishes before 1st attempt, then get stats on how |
694 // much time is saved by having spawned an extra attempt. | 770 // much time is saved by having spawned an extra attempt. |
695 retry_attempt_finished_time_ = base::TimeTicks::Now(); | 771 retry_attempt_finished_time_ = base::TimeTicks::Now(); |
696 } | 772 } |
697 | 773 |
698 if (error != OK) { | 774 if (error != OK) { |
699 params = new HostResolveFailedParams(0, error, os_error); | 775 params = new ProcTaskFailedParams(0, error, os_error); |
700 } else { | 776 } else { |
701 params = new AddressListNetLogParam(results_); | 777 params = new AddressListNetLogParam(results_); |
702 } | 778 } |
703 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); | 779 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); |
704 | 780 |
705 callback_.Run(error, os_error, results_); | 781 callback_.Run(error, os_error, results_); |
706 } | 782 } |
707 | 783 |
708 void RecordPerformanceHistograms(const base::TimeTicks& start_time, | 784 void RecordPerformanceHistograms(const base::TimeTicks& start_time, |
709 const int error, | 785 const int error, |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
884 AddressList results_; | 960 AddressList results_; |
885 | 961 |
886 BoundNetLog net_log_; | 962 BoundNetLog net_log_; |
887 | 963 |
888 DISALLOW_COPY_AND_ASSIGN(ProcTask); | 964 DISALLOW_COPY_AND_ASSIGN(ProcTask); |
889 }; | 965 }; |
890 | 966 |
891 //----------------------------------------------------------------------------- | 967 //----------------------------------------------------------------------------- |
892 | 968 |
893 // Represents a request to the worker pool for a "probe for IPv6 support" call. | 969 // Represents a request to the worker pool for a "probe for IPv6 support" call. |
970 // | |
971 // TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks. | |
894 class HostResolverImpl::IPv6ProbeJob | 972 class HostResolverImpl::IPv6ProbeJob |
895 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { | 973 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
896 public: | 974 public: |
897 explicit IPv6ProbeJob(HostResolverImpl* resolver) | 975 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
898 : resolver_(resolver), | 976 : resolver_(resolver), |
899 origin_loop_(base::MessageLoopProxy::current()) { | 977 origin_loop_(base::MessageLoopProxy::current()) { |
900 DCHECK(resolver); | 978 DCHECK(resolver); |
901 } | 979 } |
902 | 980 |
903 void Start() { | 981 void Start() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 HostResolverImpl* resolver_; | 1029 HostResolverImpl* resolver_; |
952 | 1030 |
953 // Used to post ourselves onto the origin thread. | 1031 // Used to post ourselves onto the origin thread. |
954 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 1032 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
955 | 1033 |
956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 1034 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
957 }; | 1035 }; |
958 | 1036 |
959 //----------------------------------------------------------------------------- | 1037 //----------------------------------------------------------------------------- |
960 | 1038 |
1039 // Resolves the hostname using DnsTransaction. | |
1040 // TODO(szym): This could be moved to separate source file as well. | |
1041 class HostResolverImpl::DnsTask { | |
1042 public: | |
1043 typedef base::Callback<void(int net_error, | |
1044 const AddressList& addr_list, | |
1045 base::TimeDelta ttl)> Callback; | |
1046 | |
1047 DnsTask(DnsTransactionFactory* factory, | |
1048 const Key& key, | |
1049 const Callback& callback, | |
1050 const BoundNetLog& job_net_log) | |
1051 : callback_(callback), net_log_(job_net_log) { | |
1052 DCHECK(factory); | |
1053 DCHECK(!callback.is_null()); | |
1054 | |
1055 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. | |
1056 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) | |
1057 ? dns_protocol::kTypeAAAA | |
1058 : dns_protocol::kTypeA; | |
1059 // TODO(szym): Implement "happy eyeballs". | |
1060 transaction_ = factory->CreateTransaction( | |
1061 key.hostname, | |
1062 qtype, | |
1063 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)), | |
1064 net_log_); | |
1065 DCHECK(transaction_.get()); | |
1066 } | |
1067 | |
1068 int Start() { | |
1069 net_log_.BeginEvent( | |
1070 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
1071 new NetLogSourceParameter("source_dependency", | |
1072 transaction_->net_log().source())); | |
1073 return transaction_->Start(); | |
1074 } | |
1075 | |
1076 void OnTransactionComplete(DnsTransaction* transaction, | |
1077 int net_error, | |
1078 const DnsResponse* response) { | |
1079 // TODO(szym): Record performance histograms. | |
1080 DnsResponse::Result result = DnsResponse::DNS_SUCCESS; | |
mmenke
2012/02/15 19:54:16
Fine with this as-is, but does seem a little weird
szym
2012/02/15 20:28:05
It is equivalent to setting os_error = 0 if we don
| |
1081 if (net_error == OK) { | |
1082 AddressList addr_list; | |
1083 base::TimeDelta ttl; | |
1084 result = response->ParseToAddressList(&addr_list, &ttl); | |
1085 if (result == DnsResponse::DNS_SUCCESS) { | |
1086 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
1087 new AddressListNetLogParam(addr_list)); | |
1088 callback_.Run(net_error, addr_list, ttl); | |
mmenke
2012/02/15 19:54:16
Suggest you add a comment that we've been deleted
| |
1089 return; | |
1090 } | |
1091 net_error = ERR_DNS_MALFORMED_RESPONSE; | |
1092 } | |
1093 callback_.Run(net_error, AddressList(), base::TimeDelta()); | |
1094 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | |
mmenke
2012/02/15 19:54:16
Suggest you move this line up, and delete |this| i
szym
2012/02/15 20:28:05
Good catch. This is a bug.
| |
1095 new DnsTaskFailedParams(net_error, result)); | |
1096 } | |
1097 | |
1098 private: | |
1099 // The listener to the results of this DnsTask. | |
1100 Callback callback_; | |
1101 | |
1102 const BoundNetLog net_log_; | |
1103 | |
1104 scoped_ptr<DnsTransaction> transaction_; | |
1105 }; | |
1106 | |
1107 //----------------------------------------------------------------------------- | |
1108 | |
961 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. | 1109 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
962 // Spawns ProcTask when started. | |
963 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { | 1110 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
964 public: | 1111 public: |
965 // Creates new job for |key| where |request_net_log| is bound to the | 1112 // Creates new job for |key| where |request_net_log| is bound to the |
966 // request that spawned it. | 1113 // request that spawned it and |priority| is the initial priority. |
967 Job(HostResolverImpl* resolver, | 1114 Job(HostResolverImpl* resolver, |
968 const Key& key, | 1115 const Key& key, |
969 const BoundNetLog& request_net_log) | 1116 const BoundNetLog& request_net_log, |
1117 RequestPriority priority) | |
970 : resolver_(resolver->AsWeakPtr()), | 1118 : resolver_(resolver->AsWeakPtr()), |
971 key_(key), | 1119 key_(key), |
1120 priority_tracker_(priority), | |
972 had_non_speculative_request_(false), | 1121 had_non_speculative_request_(false), |
973 net_log_(BoundNetLog::Make(request_net_log.net_log(), | 1122 net_log_(BoundNetLog::Make(request_net_log.net_log(), |
974 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), | 1123 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), |
975 net_error_(ERR_IO_PENDING), | 1124 net_error_(ERR_IO_PENDING), |
976 os_error_(0) { | 1125 os_error_(0) { |
977 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); | 1126 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); |
978 | 1127 |
979 net_log_.BeginEvent( | 1128 net_log_.BeginEvent( |
980 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1129 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
981 make_scoped_refptr(new JobCreationParameters( | 1130 make_scoped_refptr(new JobCreationParameters( |
982 key_.hostname, request_net_log.source()))); | 1131 key_.hostname, request_net_log.source()))); |
983 } | 1132 } |
984 | 1133 |
985 virtual ~Job() { | 1134 virtual ~Job() { |
986 if (net_error_ == ERR_IO_PENDING) { | 1135 if (net_error_ == ERR_IO_PENDING) { |
987 if (is_running()) { | 1136 if (is_running()) { |
1137 // |resolver_| was destroyed with this Job still pending. | |
1138 // Clean-up, record in the log, but don't run any callbacks. | |
988 DCHECK_EQ(ERR_IO_PENDING, net_error_); | 1139 DCHECK_EQ(ERR_IO_PENDING, net_error_); |
989 proc_task_->Cancel(); | 1140 if (is_proc_running()) { |
990 proc_task_ = NULL; | 1141 proc_task_->Cancel(); |
1142 proc_task_ = NULL; | |
1143 } | |
991 net_error_ = ERR_ABORTED; | 1144 net_error_ = ERR_ABORTED; |
992 } else { | 1145 } else { |
1146 // The last Request for this Job has been cancelled. | |
993 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 1147 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
994 net_error_ = OK; // For NetLog. | 1148 net_error_ = OK; // For NetLog. |
995 } | 1149 } |
996 | 1150 |
997 for (RequestsList::const_iterator it = requests_.begin(); | 1151 for (RequestsList::const_iterator it = requests_.begin(); |
998 it != requests_.end(); ++it) { | 1152 it != requests_.end(); ++it) { |
999 Request* req = *it; | 1153 Request* req = *it; |
1000 if (req->was_canceled()) | 1154 if (req->was_canceled()) |
1001 continue; | 1155 continue; |
1002 DCHECK_EQ(this, req->job()); | 1156 DCHECK_EQ(this, req->job()); |
1003 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1157 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
1004 req->info()); | 1158 req->info()); |
1005 } | 1159 } |
1006 } | 1160 } |
1007 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1161 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
1008 net_error_); | 1162 net_error_); |
1009 STLDeleteElements(&requests_); | 1163 STLDeleteElements(&requests_); |
1010 } | 1164 } |
1011 | 1165 |
1012 HostResolverImpl* resolver() const { | |
1013 return resolver_; | |
1014 } | |
1015 | |
1016 RequestPriority priority() const { | 1166 RequestPriority priority() const { |
1017 return priority_tracker_.highest_priority(); | 1167 return priority_tracker_.highest_priority(); |
1018 } | 1168 } |
1019 | 1169 |
1020 // Number of non-canceled requests in |requests_|. | 1170 // Number of non-canceled requests in |requests_|. |
1021 size_t num_active_requests() const { | 1171 size_t num_active_requests() const { |
1022 return priority_tracker_.total_count(); | 1172 return priority_tracker_.total_count(); |
1023 } | 1173 } |
1024 | 1174 |
1025 const Key& key() const { | 1175 const Key& key() const { |
1026 return key_; | 1176 return key_; |
1027 } | 1177 } |
1028 | 1178 |
1029 int net_error() const { | 1179 int net_error() const { |
1030 return net_error_; | 1180 return net_error_; |
1031 } | 1181 } |
1032 | 1182 |
1033 // Used by HostResolverImpl with |dispatcher_|. | 1183 void AddToDispatcher(PrioritizedDispatcher* dispatcher) { |
1034 const PrioritizedDispatcher::Handle& handle() const { | 1184 DCHECK(handle_.is_null()); |
1035 return handle_; | 1185 handle_ = DispatcherHandle(dispatcher, dispatcher->Add(this, priority())); |
1036 } | 1186 } |
1037 | 1187 |
1038 void set_handle(const PrioritizedDispatcher::Handle& handle) { | 1188 bool IsWaitingInDispatch() const { |
1039 handle_ = handle; | 1189 return !handle_.is_null(); |
1040 } | 1190 } |
1041 | 1191 |
1042 // The Job will own |req| and destroy it in ~Job. | 1192 void AddRequest(scoped_ptr<Request> req) { |
1043 void AddRequest(Request* req) { | |
1044 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1193 DCHECK_EQ(key_.hostname, req->info().hostname()); |
1045 | 1194 |
1046 req->set_job(this); | 1195 req->set_job(this); |
1047 requests_.push_back(req); | |
1048 | |
1049 priority_tracker_.Add(req->info().priority()); | 1196 priority_tracker_.Add(req->info().priority()); |
1050 | 1197 |
1051 req->request_net_log().AddEvent( | 1198 req->request_net_log().AddEvent( |
1052 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | 1199 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, |
1053 make_scoped_refptr(new NetLogSourceParameter( | 1200 make_scoped_refptr(new NetLogSourceParameter( |
1054 "source_dependency", net_log_.source()))); | 1201 "source_dependency", net_log_.source()))); |
1055 | 1202 |
1056 net_log_.AddEvent( | 1203 net_log_.AddEvent( |
1057 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, | 1204 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, |
1058 make_scoped_refptr(new JobAttachParameters( | 1205 make_scoped_refptr(new JobAttachParameters( |
1059 req->request_net_log().source(), priority()))); | 1206 req->request_net_log().source(), priority()))); |
1060 | 1207 |
1061 // TODO(szym): Check if this is still needed. | 1208 // TODO(szym): Check if this is still needed. |
1062 if (!req->info().is_speculative()) { | 1209 if (!req->info().is_speculative()) { |
1063 had_non_speculative_request_ = true; | 1210 had_non_speculative_request_ = true; |
1064 if (proc_task_) | 1211 if (proc_task_) |
1065 proc_task_->set_had_non_speculative_request(); | 1212 proc_task_->set_had_non_speculative_request(); |
1066 } | 1213 } |
1214 | |
1215 requests_.push_back(req.release()); | |
1216 | |
1217 if (!handle_.is_null()) | |
1218 handle_.ChangePriority(priority()); | |
1067 } | 1219 } |
1068 | 1220 |
1069 void CancelRequest(Request* req) { | 1221 void CancelRequest(Request* req) { |
1070 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1222 DCHECK_EQ(key_.hostname, req->info().hostname()); |
1071 DCHECK(!req->was_canceled()); | 1223 DCHECK(!req->was_canceled()); |
1072 // Don't remove it from |requests_| just mark it canceled. | 1224 // Don't remove it from |requests_| just mark it canceled. |
1073 req->MarkAsCanceled(); | 1225 req->MarkAsCanceled(); |
1074 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1226 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
1075 req->info()); | 1227 req->info()); |
1076 priority_tracker_.Remove(req->info().priority()); | 1228 priority_tracker_.Remove(req->info().priority()); |
1077 net_log_.AddEvent( | 1229 net_log_.AddEvent( |
1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, | 1230 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, |
1079 make_scoped_refptr(new JobAttachParameters( | 1231 make_scoped_refptr(new JobAttachParameters( |
1080 req->request_net_log().source(), priority()))); | 1232 req->request_net_log().source(), priority()))); |
1233 | |
1234 if (!handle_.is_null()) { | |
1235 if (num_active_requests() > 0) { | |
1236 handle_.ChangePriority(priority()); | |
1237 } else { | |
1238 handle_.Cancel(); | |
1239 } | |
1240 } | |
1081 } | 1241 } |
1082 | 1242 |
1083 // Aborts and destroys the job, completes all requests as aborted. | 1243 // Aborts and destroys the job, completes all requests as aborted. |
1084 void Abort() { | 1244 void Abort() { |
1085 // Job should only be aborted if it's running. | 1245 // Job should only be aborted if it's running. |
1086 DCHECK(is_running()); | 1246 DCHECK(is_running()); |
1087 proc_task_->Cancel(); | 1247 if (is_proc_running()) { |
1088 proc_task_ = NULL; | 1248 proc_task_->Cancel(); |
1249 proc_task_ = NULL; | |
1250 } | |
1251 dns_task_.reset(); | |
1089 net_error_ = ERR_ABORTED; | 1252 net_error_ = ERR_ABORTED; |
1090 os_error_ = 0; | 1253 os_error_ = 0; |
1091 CompleteRequests(AddressList()); | 1254 CompleteRequests(AddressList(), base::TimeDelta()); |
1255 } | |
1256 | |
1257 bool is_dns_running() const { | |
1258 return dns_task_.get() != NULL; | |
1259 } | |
1260 | |
1261 bool is_proc_running() const { | |
1262 return proc_task_.get() != NULL; | |
1092 } | 1263 } |
1093 | 1264 |
1094 bool is_running() const { | 1265 bool is_running() const { |
1095 return proc_task_.get() != NULL; | 1266 return is_dns_running() || is_proc_running(); |
1096 } | 1267 } |
1097 | 1268 |
1098 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1269 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
1099 void OnEvicted() { | 1270 void OnEvicted() { |
1100 // Must not be running. | 1271 // Must not be running. |
1101 DCHECK(!is_running()); | 1272 DCHECK(!is_running()); |
1102 handle_ = PrioritizedDispatcher::Handle(); | 1273 handle_.Reset(); |
1103 | 1274 |
1104 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | 1275 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); |
1105 | 1276 |
1106 // This signals to CompleteRequests that this job never ran. | 1277 // This signals to CompleteRequests that this job never ran. |
1107 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1278 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
1108 os_error_ = 0; | 1279 os_error_ = 0; |
1109 CompleteRequests(AddressList()); | 1280 CompleteRequests(AddressList(), base::TimeDelta()); |
1110 } | 1281 } |
1111 | 1282 |
1112 // PriorityDispatch::Job interface. | 1283 // PriorityDispatch::Job interface. |
1113 virtual void Start() OVERRIDE { | 1284 virtual void Start() OVERRIDE { |
1114 DCHECK(!is_running()); | 1285 DCHECK(!is_running()); |
1115 handle_ = PrioritizedDispatcher::Handle(); | 1286 handle_.Reset(); |
1116 | 1287 |
1117 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); | 1288 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); |
1118 | 1289 |
1290 if (resolver_->dns_transaction_factory_.get()) { | |
1291 StartDnsTask(); | |
1292 } else { | |
1293 StartProcTask(); | |
1294 } | |
1295 } | |
1296 | |
1297 private: | |
1298 // TODO(szym): Since DnsTransaction does not consume threads, we can increase | |
1299 // the limits on |dispatcher_|. But in order to keep the number of WorkerPool | |
1300 // threads low, we will need to use an "inner" PrioritizedDispatcher with | |
1301 // tighter limits. | |
1302 void StartProcTask() { | |
1119 proc_task_ = new ProcTask( | 1303 proc_task_ = new ProcTask( |
1120 key_, | 1304 key_, |
1121 resolver_->proc_params_, | 1305 resolver_->proc_params_, |
1122 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), | 1306 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), |
1123 net_log_); | 1307 net_log_); |
1124 | 1308 |
1125 if (had_non_speculative_request_) | 1309 if (had_non_speculative_request_) |
1126 proc_task_->set_had_non_speculative_request(); | 1310 proc_task_->set_had_non_speculative_request(); |
1127 // Start() could be called from within Resolve(), hence it must NOT directly | 1311 // Start() could be called from within Resolve(), hence it must NOT directly |
1128 // call OnProcTaskComplete, for example, on synchronous failure. | 1312 // call OnProcTaskComplete, for example, on synchronous failure. |
1129 proc_task_->Start(); | 1313 proc_task_->Start(); |
1130 } | 1314 } |
1131 | 1315 |
1132 private: | |
1133 // Called by ProcTask when it completes. | 1316 // Called by ProcTask when it completes. |
1134 void OnProcTaskComplete(int net_error, int os_error, | 1317 void OnProcTaskComplete(int net_error, int os_error, |
1135 const AddressList& addrlist) { | 1318 const AddressList& addr_list) { |
1136 DCHECK(is_running()); | 1319 DCHECK(is_proc_running()); |
1137 proc_task_ = NULL; | 1320 proc_task_ = NULL; |
1138 net_error_ = net_error; | 1321 net_error_ = net_error; |
1139 os_error_ = os_error; | 1322 os_error_ = os_error; |
1140 | 1323 |
1141 // We are the only consumer of |addrlist|, so we can safely change the port | 1324 base::TimeDelta ttl = base::TimeDelta::FromSeconds( |
1142 // without copy-on-write. This pays off, when job has only one request. | 1325 kNegativeCacheEntryTTLSeconds); |
1143 AddressList list = addrlist; | 1326 if (net_error == OK) |
1144 if (net_error == OK && !requests_.empty()) | 1327 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
1145 MutableSetPort(requests_.front()->info().port(), &list); | 1328 CompleteRequests(addr_list, ttl); |
1146 CompleteRequests(list); | 1329 } |
1330 | |
1331 void StartDnsTask() { | |
1332 dns_task_.reset(new DnsTask( | |
1333 resolver_->dns_transaction_factory_.get(), | |
1334 key_, | |
1335 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), | |
1336 net_log_)); | |
1337 | |
1338 int rv = dns_task_->Start(); | |
1339 if (rv != ERR_IO_PENDING) { | |
mmenke
2012/02/15 19:54:16
Maybe reset |dns_task| here, and maybe DCHECK it's
| |
1340 DCHECK_NE(OK, rv); | |
1341 StartProcTask(); | |
1342 } | |
1343 } | |
1344 | |
1345 // Called by DnsTask when it completes. | |
1346 void OnDnsTaskComplete(int net_error, | |
1347 const AddressList& addr_list, | |
1348 base::TimeDelta ttl) { | |
1349 DCHECK(is_dns_running()); | |
1350 dns_task_.reset(); | |
1351 | |
1352 if (net_error != OK) { | |
1353 // TODO(szym): Some net errors indicate lack of connectivity. Starting | |
1354 // ProcTask in that case is a waste of time. | |
1355 StartProcTask(); | |
1356 return; | |
1357 } | |
1358 | |
1359 net_error_ = OK; | |
cbentzel
2012/02/15 19:48:35
Are net_error_ and os_error_ needed as members, or
szym
2012/02/15 20:28:05
Agreed that the state indication is all over place
| |
1360 os_error_ = 0; | |
1361 CompleteRequests(addr_list, ttl); | |
1147 } | 1362 } |
1148 | 1363 |
1149 // Completes all Requests. Calls OnJobFinished and deletes self. | 1364 // Completes all Requests. Calls OnJobFinished and deletes self. |
1150 void CompleteRequests(const AddressList& addrlist) { | 1365 void CompleteRequests(const AddressList& addr_list, base::TimeDelta ttl) { |
1151 CHECK(resolver_); | 1366 CHECK(resolver_); |
1152 | 1367 |
1368 // We are the only consumer of |addr_list|, so we can safely change the port | |
1369 // without copy-on-write. This pays off, when job has only one request. | |
1370 AddressList list = addr_list; | |
1371 if (net_error_ == OK && !requests_.empty()) | |
1372 MutableSetPort(requests_.front()->info().port(), &list); | |
1373 | |
1153 // This job must be removed from resolver's |jobs_| now to make room for a | 1374 // This job must be removed from resolver's |jobs_| now to make room for a |
1154 // new job with the same key in case one of the OnComplete callbacks decides | 1375 // new job with the same key in case one of the OnComplete callbacks decides |
1155 // to spawn one. Consequently, the job deletes itself when CompleteRequests | 1376 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
1156 // is done. | 1377 // is done. |
1157 scoped_ptr<Job> self_deleter(this); | 1378 scoped_ptr<Job> self_deleter(this); |
1158 resolver_->OnJobFinished(this, addrlist); | 1379 resolver_->OnJobFinished(this, addr_list, ttl); |
1159 | 1380 |
1160 // Complete all of the requests that were attached to the job. | 1381 // Complete all of the requests that were attached to the job. |
1161 for (RequestsList::const_iterator it = requests_.begin(); | 1382 for (RequestsList::const_iterator it = requests_.begin(); |
1162 it != requests_.end(); ++it) { | 1383 it != requests_.end(); ++it) { |
1163 Request* req = *it; | 1384 Request* req = *it; |
1164 | 1385 |
1165 if (req->was_canceled()) | 1386 if (req->was_canceled()) |
1166 continue; | 1387 continue; |
1167 | 1388 |
1168 DCHECK_EQ(this, req->job()); | 1389 DCHECK_EQ(this, req->job()); |
1169 // Update the net log and notify registered observers. | 1390 // Update the net log and notify registered observers. |
1170 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1391 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
1171 req->info(), net_error_, os_error_); | 1392 req->info(), net_error_, os_error_); |
1172 | 1393 |
1173 req->OnComplete(net_error_, addrlist); | 1394 req->OnComplete(net_error_, addr_list); |
1174 | 1395 |
1175 // Check if the resolver was destroyed as a result of running the | 1396 // Check if the resolver was destroyed as a result of running the |
1176 // callback. If it was, we could continue, but we choose to bail. | 1397 // callback. If it was, we could continue, but we choose to bail. |
1177 if (!resolver_) | 1398 if (!resolver_) |
1178 return; | 1399 return; |
1179 } | 1400 } |
1180 } | 1401 } |
1181 | 1402 |
1182 // Used to call OnJobFinished and RemoveJob. | 1403 // Used to call OnJobFinished. |
1183 base::WeakPtr<HostResolverImpl> resolver_; | 1404 base::WeakPtr<HostResolverImpl> resolver_; |
1184 | 1405 |
1185 Key key_; | 1406 Key key_; |
1186 | 1407 |
1187 // Tracks the highest priority across |requests_|. | 1408 // Tracks the highest priority across |requests_|. |
1188 PriorityTracker priority_tracker_; | 1409 PriorityTracker priority_tracker_; |
1189 | 1410 |
1190 bool had_non_speculative_request_; | 1411 bool had_non_speculative_request_; |
1191 | 1412 |
1192 BoundNetLog net_log_; | 1413 BoundNetLog net_log_; |
1193 | 1414 |
1194 // Store result here in case the job fails fast in Resolve(). | 1415 // Store result here in case the job fails fast in Resolve(). |
1195 int net_error_; | 1416 int net_error_; |
1196 int os_error_; | 1417 int os_error_; |
1197 | 1418 |
1198 // A ProcTask created and started when this Job is dispatched.. | 1419 // Resolves the host using a HostResolverProc. |
1199 scoped_refptr<ProcTask> proc_task_; | 1420 scoped_refptr<ProcTask> proc_task_; |
1200 | 1421 |
1422 // Resolves the host using a DnsTransaction. | |
1423 scoped_ptr<DnsTask> dns_task_; | |
1424 | |
1201 // All Requests waiting for the result of this Job. Some can be canceled. | 1425 // All Requests waiting for the result of this Job. Some can be canceled. |
1202 RequestsList requests_; | 1426 RequestsList requests_; |
1203 | 1427 |
1204 // A handle used by HostResolverImpl in |dispatcher_|. | 1428 // A handle used by HostResolverImpl in |dispatcher_|. |
1205 PrioritizedDispatcher::Handle handle_; | 1429 DispatcherHandle handle_; |
1206 }; | 1430 }; |
1207 | 1431 |
1208 //----------------------------------------------------------------------------- | 1432 //----------------------------------------------------------------------------- |
1209 | 1433 |
1210 HostResolverImpl::ProcTaskParams::ProcTaskParams( | 1434 HostResolverImpl::ProcTaskParams::ProcTaskParams( |
1211 HostResolverProc* resolver_proc, | 1435 HostResolverProc* resolver_proc, |
1212 size_t max_retry_attempts) | 1436 size_t max_retry_attempts) |
1213 : resolver_proc(resolver_proc), | 1437 : resolver_proc(resolver_proc), |
1214 max_retry_attempts(max_retry_attempts), | 1438 max_retry_attempts(max_retry_attempts), |
1215 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), | 1439 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), |
1216 retry_factor(2) { | 1440 retry_factor(2) { |
1217 } | 1441 } |
1218 | 1442 |
1219 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} | 1443 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} |
1220 | 1444 |
1221 HostResolverImpl::HostResolverImpl( | 1445 HostResolverImpl::HostResolverImpl( |
1222 HostCache* cache, | 1446 HostCache* cache, |
1223 const PrioritizedDispatcher::Limits& job_limits, | 1447 const PrioritizedDispatcher::Limits& job_limits, |
1224 const ProcTaskParams& proc_params, | 1448 const ProcTaskParams& proc_params, |
1449 scoped_ptr<DnsConfigService> dns_config_service, | |
1225 NetLog* net_log) | 1450 NetLog* net_log) |
1226 : cache_(cache), | 1451 : cache_(cache), |
1227 dispatcher_(job_limits), | 1452 dispatcher_(job_limits), |
1228 max_queued_jobs_(job_limits.total_jobs * 100u), | 1453 max_queued_jobs_(job_limits.total_jobs * 100u), |
1229 proc_params_(proc_params), | 1454 proc_params_(proc_params), |
1230 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 1455 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
1456 dns_config_service_(dns_config_service.Pass()), | |
1231 ipv6_probe_monitoring_(false), | 1457 ipv6_probe_monitoring_(false), |
1232 additional_resolver_flags_(0), | 1458 additional_resolver_flags_(0), |
1233 net_log_(net_log) { | 1459 net_log_(net_log) { |
1234 | 1460 |
1235 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); | 1461 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
1236 | 1462 |
1237 // Maximum of 4 retry attempts for host resolution. | 1463 // Maximum of 4 retry attempts for host resolution. |
1238 static const size_t kDefaultMaxRetryAttempts = 4u; | 1464 static const size_t kDefaultMaxRetryAttempts = 4u; |
1239 | 1465 |
1240 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) | 1466 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) |
1241 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; | 1467 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; |
1242 | 1468 |
1243 #if defined(OS_WIN) | 1469 #if defined(OS_WIN) |
1244 EnsureWinsockInit(); | 1470 EnsureWinsockInit(); |
1245 #endif | 1471 #endif |
1246 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1472 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
1247 if (HaveOnlyLoopbackAddresses()) | 1473 if (HaveOnlyLoopbackAddresses()) |
1248 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; | 1474 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
1249 #endif | 1475 #endif |
1250 NetworkChangeNotifier::AddIPAddressObserver(this); | 1476 NetworkChangeNotifier::AddIPAddressObserver(this); |
1251 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1477 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
1252 #if !defined(OS_ANDROID) | 1478 #if !defined(OS_ANDROID) |
1253 EnsureDnsReloaderInit(); | 1479 EnsureDnsReloaderInit(); |
1254 #endif | 1480 #endif |
1255 NetworkChangeNotifier::AddDNSObserver(this); | 1481 NetworkChangeNotifier::AddDNSObserver(this); |
1256 #endif | 1482 #endif |
1483 | |
1484 if (dns_config_service_.get()) | |
cbentzel
2012/02/15 19:48:35
Maybe want a note here that |this| is never remove
| |
1485 dns_config_service_->AddObserver(this); | |
1257 } | 1486 } |
1258 | 1487 |
1259 HostResolverImpl::~HostResolverImpl() { | 1488 HostResolverImpl::~HostResolverImpl() { |
1260 DiscardIPv6ProbeJob(); | 1489 DiscardIPv6ProbeJob(); |
1261 | 1490 |
1262 // This will also cancel all outstanding requests. | 1491 // This will also cancel all outstanding requests. |
1263 STLDeleteValues(&jobs_); | 1492 STLDeleteValues(&jobs_); |
1264 | 1493 |
1265 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 1494 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
1266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1495 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1300 return rv; | 1529 return rv; |
1301 } | 1530 } |
1302 | 1531 |
1303 // Next we need to attach our request to a "job". This job is responsible for | 1532 // Next we need to attach our request to a "job". This job is responsible for |
1304 // calling "getaddrinfo(hostname)" on a worker thread. | 1533 // calling "getaddrinfo(hostname)" on a worker thread. |
1305 | 1534 |
1306 JobMap::iterator jobit = jobs_.find(key); | 1535 JobMap::iterator jobit = jobs_.find(key); |
1307 Job* job; | 1536 Job* job; |
1308 if (jobit == jobs_.end()) { | 1537 if (jobit == jobs_.end()) { |
1309 // Create new Job. | 1538 // Create new Job. |
1310 job = new Job(this, key, request_net_log); | 1539 job = new Job(this, key, request_net_log, info.priority()); |
1311 job->set_handle(dispatcher_.Add(job, info.priority())); | 1540 job->AddToDispatcher(&dispatcher_); |
1312 | 1541 |
1313 // Check for queue overflow. | 1542 // Check for queue overflow. |
1314 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { | 1543 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { |
1315 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); | 1544 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); |
1316 DCHECK(evicted); | 1545 DCHECK(evicted); |
1317 if (evicted == job) { | 1546 if (evicted == job) { |
1318 delete job; | 1547 delete job; |
1319 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1548 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
1320 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); | 1549 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); |
1321 return rv; | 1550 return rv; |
1322 } | 1551 } |
1323 evicted->OnEvicted(); // Deletes |evicted|. | 1552 evicted->OnEvicted(); // Deletes |evicted|. |
1324 } | 1553 } |
1325 | 1554 |
1326 jobs_.insert(jobit, std::make_pair(key, job)); | 1555 jobs_.insert(jobit, std::make_pair(key, job)); |
1327 } else { | 1556 } else { |
1328 job = jobit->second; | 1557 job = jobit->second; |
1329 } | 1558 } |
1330 | 1559 |
1331 // Can't complete synchronously. Create and attach request. | 1560 // Can't complete synchronously. Create and attach request. |
1332 Request* req = new Request(source_net_log, request_net_log, info, callback, | 1561 scoped_ptr<Request> req(new Request(source_net_log, |
1333 addresses); | 1562 request_net_log, |
1334 job->AddRequest(req); | 1563 info, |
1335 if (!job->handle().is_null()) | 1564 callback, |
1336 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); | 1565 addresses)); |
1337 if (out_req) | 1566 if (out_req) |
1338 *out_req = reinterpret_cast<RequestHandle>(req); | 1567 *out_req = reinterpret_cast<RequestHandle>(req.get()); |
1568 | |
1569 job->AddRequest(req.Pass()); | |
1339 | 1570 |
1340 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); | 1571 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); |
1341 // Completion happens during Job::CompleteRequests(). | 1572 // Completion happens during Job::CompleteRequests(). |
1342 return ERR_IO_PENDING; | 1573 return ERR_IO_PENDING; |
1343 } | 1574 } |
1344 | 1575 |
1345 int HostResolverImpl::ResolveHelper(const Key& key, | 1576 int HostResolverImpl::ResolveHelper(const Key& key, |
1346 const RequestInfo& info, | 1577 const RequestInfo& info, |
1347 AddressList* addresses, | 1578 AddressList* addresses, |
1348 const BoundNetLog& request_net_log) { | 1579 const BoundNetLog& request_net_log) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1384 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { | 1615 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { |
1385 DCHECK(CalledOnValidThread()); | 1616 DCHECK(CalledOnValidThread()); |
1386 Request* req = reinterpret_cast<Request*>(req_handle); | 1617 Request* req = reinterpret_cast<Request*>(req_handle); |
1387 DCHECK(req); | 1618 DCHECK(req); |
1388 | 1619 |
1389 Job* job = req->job(); | 1620 Job* job = req->job(); |
1390 DCHECK(job); | 1621 DCHECK(job); |
1391 | 1622 |
1392 job->CancelRequest(req); | 1623 job->CancelRequest(req); |
1393 | 1624 |
1394 if (!job->handle().is_null()) { | 1625 if (job->num_active_requests() == 0) { |
1395 // Still in queue. | 1626 if (job->is_running()) { |
1396 if (job->num_active_requests()) { | 1627 // Job is running (and could be in CompleteRequests right now). |
1397 job->set_handle(dispatcher_.ChangePriority(job->handle(), | 1628 // But to be in Request::OnComplete we would have to have a non-canceled |
1398 job->priority())); | 1629 // request. So it is safe to Abort it if it has no more active requests. |
mmenke
2012/02/15 19:54:16
I find this comment confusing.
Maybe something li
| |
1630 job->Abort(); | |
1399 } else { | 1631 } else { |
1400 dispatcher_.Cancel(job->handle()); | |
1401 RemoveJob(job); | 1632 RemoveJob(job); |
1402 delete job; | 1633 delete job; |
1403 } | 1634 } |
1404 } else { | |
1405 // Job is running (and could be in CompleteRequests right now). | |
1406 // But to be in Request::OnComplete we would have to have a non-canceled | |
1407 // request. So it is safe to Abort it if it has no more active requests. | |
1408 if (!job->num_active_requests()) { | |
1409 job->Abort(); | |
1410 } | |
1411 } | 1635 } |
1412 } | 1636 } |
1413 | 1637 |
1414 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { | 1638 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
1415 DCHECK(CalledOnValidThread()); | 1639 DCHECK(CalledOnValidThread()); |
1416 ipv6_probe_monitoring_ = false; | 1640 ipv6_probe_monitoring_ = false; |
1417 DiscardIPv6ProbeJob(); | 1641 DiscardIPv6ProbeJob(); |
1418 default_address_family_ = address_family; | 1642 default_address_family_ = address_family; |
1419 } | 1643 } |
1420 | 1644 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1475 if (!cache_entry) | 1699 if (!cache_entry) |
1476 return false; | 1700 return false; |
1477 | 1701 |
1478 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1702 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
1479 *net_error = cache_entry->error; | 1703 *net_error = cache_entry->error; |
1480 if (*net_error == OK) | 1704 if (*net_error == OK) |
1481 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1705 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
1482 return true; | 1706 return true; |
1483 } | 1707 } |
1484 | 1708 |
1485 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { | 1709 void HostResolverImpl::OnJobFinished(Job* job, |
1710 const AddressList& addrlist, | |
mmenke
2012/02/15 19:54:16
At some point (Not necessarily in this CL), you mi
| |
1711 base::TimeDelta ttl) { | |
1486 DCHECK(job); | 1712 DCHECK(job); |
1487 DCHECK(job->handle().is_null()); | 1713 DCHECK(!job->IsWaitingInDispatch()); |
1488 RemoveJob(job); | 1714 RemoveJob(job); |
1489 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) | 1715 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) |
1490 return; | 1716 return; |
1491 | 1717 |
1492 // Signal dispatcher that a slot has opened. | 1718 // Signal dispatcher that a slot has opened. |
1493 dispatcher_.OnJobFinished(); | 1719 dispatcher_.OnJobFinished(); |
1494 if (job->net_error() == ERR_ABORTED) | 1720 if (job->net_error() == ERR_ABORTED) |
1495 return; | 1721 return; |
1496 // Write result to the cache. | 1722 // Write result to the cache. |
1497 if (cache_.get()) { | 1723 if (cache_.get()) { |
1498 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); | |
1499 if (job->net_error() == OK) | |
1500 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | |
1501 cache_->Set(job->key(), job->net_error(), addrlist, | 1724 cache_->Set(job->key(), job->net_error(), addrlist, |
1502 base::TimeTicks::Now(), ttl); | 1725 base::TimeTicks::Now(), ttl); |
1503 } | 1726 } |
1504 } | 1727 } |
1505 | 1728 |
1506 void HostResolverImpl::RemoveJob(Job* job) { | 1729 void HostResolverImpl::RemoveJob(Job* job) { |
1507 DCHECK(job); | 1730 DCHECK(job); |
1508 jobs_.erase(job->key()); | 1731 jobs_.erase(job->key()); |
1509 } | 1732 } |
1510 | 1733 |
(...skipping 28 matching lines...) Expand all Loading... | |
1539 effective_address_family = default_address_family_; | 1762 effective_address_family = default_address_family_; |
1540 if (ipv6_probe_monitoring_) | 1763 if (ipv6_probe_monitoring_) |
1541 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; | 1764 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; |
1542 } | 1765 } |
1543 return Key(info.hostname(), effective_address_family, effective_flags); | 1766 return Key(info.hostname(), effective_address_family, effective_flags); |
1544 } | 1767 } |
1545 | 1768 |
1546 void HostResolverImpl::AbortAllInProgressJobs() { | 1769 void HostResolverImpl::AbortAllInProgressJobs() { |
1547 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); | 1770 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); |
1548 // Scan |jobs_| for running jobs and abort them. | 1771 // Scan |jobs_| for running jobs and abort them. |
1549 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { | 1772 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { |
cbentzel
2012/02/15 19:48:35
BUG: I don't think this works correctly. The probl
szym
2012/02/15 20:28:05
Right. That's a bug. HostResolverImplTest.OnlyAbor
| |
1550 Job* job = it->second; | 1773 Job* job = it->second; |
1551 // Advance the iterator before we might erase it. | 1774 // Advance the iterator before we might erase it. |
1552 ++it; | 1775 ++it; |
1553 if (job->is_running()) { | 1776 if (job->is_running()) { |
1554 job->Abort(); | 1777 job->Abort(); |
1555 // Check if resolver was deleted in a request callback. | 1778 // Check if resolver was deleted in a request callback. |
1556 if (!self) | 1779 if (!self) |
1557 return; | 1780 return; |
1558 } else { | 1781 } else { |
1559 // Keep it in |dispatch_|. | 1782 // Keep it in |dispatch_|. |
1560 DCHECK(!job->handle().is_null()); | 1783 DCHECK(job->IsWaitingInDispatch()); |
1561 } | 1784 } |
1562 } | 1785 } |
1563 } | 1786 } |
1564 | 1787 |
1565 void HostResolverImpl::OnIPAddressChanged() { | 1788 void HostResolverImpl::OnIPAddressChanged() { |
1566 if (cache_.get()) | 1789 if (cache_.get()) |
1567 cache_->clear(); | 1790 cache_->clear(); |
1568 if (ipv6_probe_monitoring_) { | 1791 if (ipv6_probe_monitoring_) { |
1569 DiscardIPv6ProbeJob(); | 1792 DiscardIPv6ProbeJob(); |
1570 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1793 ipv6_probe_job_ = new IPv6ProbeJob(this); |
(...skipping 16 matching lines...) Expand all Loading... | |
1587 // as NSCD's cache should be dropped automatically by the OS when | 1810 // as NSCD's cache should be dropped automatically by the OS when |
1588 // resolv.conf changes so we don't need to do anything to clear that cache. | 1811 // resolv.conf changes so we don't need to do anything to clear that cache. |
1589 if (cache_.get()) | 1812 if (cache_.get()) |
1590 cache_->clear(); | 1813 cache_->clear(); |
1591 // Existing jobs will have been sent to the original server so they need to | 1814 // Existing jobs will have been sent to the original server so they need to |
1592 // be aborted. TODO(Craig): Should these jobs be restarted? | 1815 // be aborted. TODO(Craig): Should these jobs be restarted? |
1593 AbortAllInProgressJobs(); | 1816 AbortAllInProgressJobs(); |
1594 // |this| may be deleted inside AbortAllInProgressJobs(). | 1817 // |this| may be deleted inside AbortAllInProgressJobs(). |
1595 } | 1818 } |
1596 | 1819 |
1820 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { | |
1821 // We want a new factory in place, before we Abort running Jobs, so that the | |
1822 // newly started jobs use the new factory. | |
1823 bool had_factory = (dns_transaction_factory_.get() != NULL); | |
1824 if (dns_config.IsValid()) { | |
1825 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( | |
1826 new DnsSession(dns_config, | |
1827 ClientSocketFactory::GetDefaultFactory(), | |
1828 base::Bind(&base::RandInt), | |
1829 net_log_)); | |
1830 } else { | |
1831 dns_transaction_factory_.reset(); | |
1832 } | |
1833 if (had_factory) { | |
cbentzel
2012/02/15 19:48:35
Nit: braces not needed.
Also - would it be easier
szym
2012/02/15 20:28:05
OnDNSChanged aborts all in-flight Jobs. Calling it
| |
1834 OnDNSChanged(); | |
1835 } | |
1836 } | |
1837 | |
1597 } // namespace net | 1838 } // namespace net |
OLD | NEW |