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

Side by Side Diff: net/base/host_resolver_impl.cc

Issue 9369045: [net] HostResolverImpl + DnsTransaction + DnsConfigService = Asynchronous DNS ready for experiments. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased to master. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698