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> |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 } | 198 } |
199 } else { | 199 } else { |
200 if (speculative) { | 200 if (speculative) { |
201 DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); | 201 DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); |
202 } else { | 202 } else { |
203 DNS_HISTOGRAM("DNS.TotalTime", duration); | 203 DNS_HISTOGRAM("DNS.TotalTime", duration); |
204 } | 204 } |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 void RecordTTL(base::TimeDelta ttl) { | |
209 UMA_HISTOGRAM_CUSTOM_COUNTS("AsyncDNS.TTL", ttl.InSeconds(), 1, 86400, 100); | |
cbentzel
2012/10/13 10:50:45
Should be UMA_HISTOGRAM_CUSTOM_TIMES?
szym
2012/10/15 19:45:36
I initially used _TIMES, but then I looked at the
| |
210 } | |
211 | |
208 //----------------------------------------------------------------------------- | 212 //----------------------------------------------------------------------------- |
209 | 213 |
210 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. | 214 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. |
211 // TODO(szym): This should probably be declared in host_resolver_proc.h. | 215 // TODO(szym): This should probably be declared in host_resolver_proc.h. |
212 class CallSystemHostResolverProc : public HostResolverProc { | 216 class CallSystemHostResolverProc : public HostResolverProc { |
213 public: | 217 public: |
214 CallSystemHostResolverProc() : HostResolverProc(NULL) {} | 218 CallSystemHostResolverProc() : HostResolverProc(NULL) {} |
215 virtual int Resolve(const std::string& hostname, | 219 virtual int Resolve(const std::string& hostname, |
216 AddressFamily address_family, | 220 AddressFamily address_family, |
217 HostResolverFlags host_resolver_flags, | 221 HostResolverFlags host_resolver_flags, |
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1324 base::Bind(&NetLogJobAttachCallback, | 1328 base::Bind(&NetLogJobAttachCallback, |
1325 req->request_net_log().source(), | 1329 req->request_net_log().source(), |
1326 priority())); | 1330 priority())); |
1327 | 1331 |
1328 if (num_active_requests() > 0) { | 1332 if (num_active_requests() > 0) { |
1329 UpdatePriority(); | 1333 UpdatePriority(); |
1330 } else { | 1334 } else { |
1331 // If we were called from a Request's callback within CompleteRequests, | 1335 // If we were called from a Request's callback within CompleteRequests, |
1332 // that Request could not have been cancelled, so num_active_requests() | 1336 // that Request could not have been cancelled, so num_active_requests() |
1333 // could not be 0. Therefore, we are not in CompleteRequests(). | 1337 // could not be 0. Therefore, we are not in CompleteRequests(). |
1334 CompleteRequests(OK, AddressList(), base::TimeDelta()); | 1338 CompleteRequestsWithError(OK /* cancelled */); |
1335 } | 1339 } |
1336 } | 1340 } |
1337 | 1341 |
1338 // Called from AbortAllInProgressJobs. Completes all requests as aborted | 1342 // Called from AbortAllInProgressJobs. Completes all requests as aborted |
1339 // and destroys the job. | 1343 // and destroys the job. |
1340 void Abort() { | 1344 void Abort() { |
1341 DCHECK(is_running()); | 1345 DCHECK(is_running()); |
1342 CompleteRequests(ERR_ABORTED, AddressList(), base::TimeDelta()); | 1346 CompleteRequestsWithError(ERR_ABORTED); |
1343 } | 1347 } |
1344 | 1348 |
1345 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1349 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
1346 // Completes all requests and destroys the job. | 1350 // Completes all requests and destroys the job. |
1347 void OnEvicted() { | 1351 void OnEvicted() { |
1348 DCHECK(!is_running()); | 1352 DCHECK(!is_running()); |
1349 DCHECK(is_queued()); | 1353 DCHECK(is_queued()); |
1350 handle_.Reset(); | 1354 handle_.Reset(); |
1351 | 1355 |
1352 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); | 1356 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); |
1353 | 1357 |
1354 // This signals to CompleteRequests that this job never ran. | 1358 // This signals to CompleteRequests that this job never ran. |
1355 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, | 1359 CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); |
1356 AddressList(), | |
1357 base::TimeDelta()); | |
1358 } | 1360 } |
1359 | 1361 |
1360 // Attempts to serve the job from HOSTS. Returns true if succeeded and | 1362 // Attempts to serve the job from HOSTS. Returns true if succeeded and |
1361 // this Job was destroyed. | 1363 // this Job was destroyed. |
1362 bool ServeFromHosts() { | 1364 bool ServeFromHosts() { |
1363 DCHECK_GT(num_active_requests(), 0u); | 1365 DCHECK_GT(num_active_requests(), 0u); |
1364 AddressList addr_list; | 1366 AddressList addr_list; |
1365 if (resolver_->ServeFromHosts(key(), | 1367 if (resolver_->ServeFromHosts(key(), |
1366 requests_.front()->info(), | 1368 requests_.front()->info(), |
1367 &addr_list)) { | 1369 &addr_list)) { |
1368 // This will destroy the Job. | 1370 // This will destroy the Job. |
1369 CompleteRequests(OK, addr_list, base::TimeDelta()); | 1371 CompleteRequests(OK, addr_list, base::TimeDelta(), false /* true_ttl */); |
cbentzel
2012/10/13 10:50:45
Would it make sense to change to CompleteRequests(
szym
2012/10/15 19:45:36
I don't see the benefit. Wouldn't this be the only
| |
1370 return true; | 1372 return true; |
1371 } | 1373 } |
1372 return false; | 1374 return false; |
1373 } | 1375 } |
1374 | 1376 |
1375 const Key key() const { | 1377 const Key key() const { |
1376 return key_; | 1378 return key_; |
1377 } | 1379 } |
1378 | 1380 |
1379 bool is_queued() const { | 1381 bool is_queued() const { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1457 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); | 1459 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); |
1458 } | 1460 } |
1459 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", | 1461 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", |
1460 std::abs(dns_task_error_), | 1462 std::abs(dns_task_error_), |
1461 GetAllErrorCodesForUma()); | 1463 GetAllErrorCodesForUma()); |
1462 } else { | 1464 } else { |
1463 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); | 1465 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); |
1464 } | 1466 } |
1465 } | 1467 } |
1466 | 1468 |
1467 base::TimeDelta ttl = base::TimeDelta::FromSeconds( | 1469 base::TimeDelta ttl = |
1468 kNegativeCacheEntryTTLSeconds); | 1470 base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds); |
1469 if (net_error == OK) | 1471 if (net_error == OK) |
1470 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | 1472 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
1471 | 1473 |
1472 CompleteRequests(net_error, addr_list, ttl); | 1474 CompleteRequests(net_error, addr_list, ttl, false /* true_ttl */); |
1473 } | 1475 } |
1474 | 1476 |
1475 void StartDnsTask() { | 1477 void StartDnsTask() { |
1476 DCHECK(resolver_->HaveDnsConfig()); | 1478 DCHECK(resolver_->HaveDnsConfig()); |
1477 dns_task_.reset(new DnsTask( | 1479 dns_task_.reset(new DnsTask( |
1478 resolver_->dns_client_.get(), | 1480 resolver_->dns_client_.get(), |
1479 key_, | 1481 key_, |
1480 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), | 1482 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), |
1481 net_log_)); | 1483 net_log_)); |
1482 | 1484 |
(...skipping 19 matching lines...) Expand all Loading... | |
1502 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. | 1504 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. |
1503 // http://crbug.com/117655 | 1505 // http://crbug.com/117655 |
1504 | 1506 |
1505 // TODO(szym): Some net errors indicate lack of connectivity. Starting | 1507 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
1506 // ProcTask in that case is a waste of time. | 1508 // ProcTask in that case is a waste of time. |
1507 StartProcTask(); | 1509 StartProcTask(); |
1508 return; | 1510 return; |
1509 } | 1511 } |
1510 | 1512 |
1511 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); | 1513 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); |
1514 RecordTTL(ttl); | |
1512 | 1515 |
1513 CompleteRequests(net_error, addr_list, ttl); | 1516 CompleteRequests(net_error, addr_list, ttl, true /* true_ttl */); |
1514 } | 1517 } |
1515 | 1518 |
1516 // Performs Job's last rites. Completes all Requests. Deletes this. | 1519 // Performs Job's last rites. Completes all Requests. Deletes this. |
1517 void CompleteRequests(int net_error, | 1520 void CompleteRequests(int net_error, |
1518 const AddressList& addr_list, | 1521 const AddressList& addr_list, |
1519 base::TimeDelta ttl) { | 1522 base::TimeDelta ttl, |
1523 bool true_ttl) { | |
1520 CHECK(resolver_); | 1524 CHECK(resolver_); |
1521 | 1525 |
1522 // This job must be removed from resolver's |jobs_| now to make room for a | 1526 // This job must be removed from resolver's |jobs_| now to make room for a |
1523 // new job with the same key in case one of the OnComplete callbacks decides | 1527 // new job with the same key in case one of the OnComplete callbacks decides |
1524 // to spawn one. Consequently, the job deletes itself when CompleteRequests | 1528 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
1525 // is done. | 1529 // is done. |
1526 scoped_ptr<Job> self_deleter(this); | 1530 scoped_ptr<Job> self_deleter(this); |
1527 | 1531 |
1528 resolver_->RemoveJob(this); | 1532 resolver_->RemoveJob(this); |
1529 | 1533 |
1530 // |addr_list| will be destroyed once we destroy |proc_task_| and | 1534 // |addr_list| will be destroyed with |proc_task_| and |dns_task_|. |
1531 // |dns_task_|. | |
1532 AddressList list = addr_list; | 1535 AddressList list = addr_list; |
1533 | 1536 |
1534 if (is_running()) { | 1537 if (is_running()) { |
1535 DCHECK(!is_queued()); | 1538 DCHECK(!is_queued()); |
1536 if (is_proc_running()) { | 1539 if (is_proc_running()) { |
1537 proc_task_->Cancel(); | 1540 proc_task_->Cancel(); |
1538 proc_task_ = NULL; | 1541 proc_task_ = NULL; |
1539 } | 1542 } |
1540 dns_task_.reset(); | 1543 dns_task_.reset(); |
1541 | 1544 |
(...skipping 19 matching lines...) Expand all Loading... | |
1561 if (net_error == OK) { | 1564 if (net_error == OK) { |
1562 SetPortOnAddressList(requests_.front()->info().port(), &list); | 1565 SetPortOnAddressList(requests_.front()->info().port(), &list); |
1563 // Record this histogram here, when we know the system has a valid DNS | 1566 // Record this histogram here, when we know the system has a valid DNS |
1564 // configuration. | 1567 // configuration. |
1565 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", | 1568 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", |
1566 resolver_->received_dns_config_); | 1569 resolver_->received_dns_config_); |
1567 } | 1570 } |
1568 | 1571 |
1569 bool did_complete = (net_error != ERR_ABORTED) && | 1572 bool did_complete = (net_error != ERR_ABORTED) && |
1570 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); | 1573 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); |
1571 if (did_complete) | 1574 if (did_complete) { |
1572 resolver_->CacheResult(key_, net_error, list, ttl); | 1575 HostCache::Entry entry = true_ttl ? |
1576 HostCache::Entry(net_error, list, ttl) : | |
1577 HostCache::Entry(net_error, list); | |
1578 resolver_->CacheResult(key_, entry, ttl); | |
1579 } | |
1573 | 1580 |
1574 // Complete all of the requests that were attached to the job. | 1581 // Complete all of the requests that were attached to the job. |
1575 for (RequestsList::const_iterator it = requests_.begin(); | 1582 for (RequestsList::const_iterator it = requests_.begin(); |
1576 it != requests_.end(); ++it) { | 1583 it != requests_.end(); ++it) { |
1577 Request* req = *it; | 1584 Request* req = *it; |
1578 | 1585 |
1579 if (req->was_canceled()) | 1586 if (req->was_canceled()) |
1580 continue; | 1587 continue; |
1581 | 1588 |
1582 DCHECK_EQ(this, req->job()); | 1589 DCHECK_EQ(this, req->job()); |
1583 // Update the net log and notify registered observers. | 1590 // Update the net log and notify registered observers. |
1584 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1591 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
1585 req->info(), net_error); | 1592 req->info(), net_error); |
1586 if (did_complete) { | 1593 if (did_complete) { |
1587 // Record effective total time from creation to completion. | 1594 // Record effective total time from creation to completion. |
1588 RecordTotalTime(had_dns_config_, req->info().is_speculative(), | 1595 RecordTotalTime(had_dns_config_, req->info().is_speculative(), |
1589 base::TimeTicks::Now() - req->request_time()); | 1596 base::TimeTicks::Now() - req->request_time()); |
1590 } | 1597 } |
1591 req->OnComplete(net_error, list); | 1598 req->OnComplete(net_error, list); |
1592 | 1599 |
1593 // Check if the resolver was destroyed as a result of running the | 1600 // Check if the resolver was destroyed as a result of running the |
1594 // callback. If it was, we could continue, but we choose to bail. | 1601 // callback. If it was, we could continue, but we choose to bail. |
1595 if (!resolver_) | 1602 if (!resolver_) |
1596 return; | 1603 return; |
1597 } | 1604 } |
1598 } | 1605 } |
1599 | 1606 |
1607 // Convenience wrapper for CompleteRequests in case of failure. | |
1608 void CompleteRequestsWithError(int net_error) { | |
1609 CompleteRequests(net_error, AddressList(), base::TimeDelta(), false); | |
1610 } | |
1611 | |
1600 RequestPriority priority() const { | 1612 RequestPriority priority() const { |
1601 return priority_tracker_.highest_priority(); | 1613 return priority_tracker_.highest_priority(); |
1602 } | 1614 } |
1603 | 1615 |
1604 // Number of non-canceled requests in |requests_|. | 1616 // Number of non-canceled requests in |requests_|. |
1605 size_t num_active_requests() const { | 1617 size_t num_active_requests() const { |
1606 return priority_tracker_.total_count(); | 1618 return priority_tracker_.total_count(); |
1607 } | 1619 } |
1608 | 1620 |
1609 bool is_dns_running() const { | 1621 bool is_dns_running() const { |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1951 if (!info.allow_cached_response() || !cache_.get()) | 1963 if (!info.allow_cached_response() || !cache_.get()) |
1952 return false; | 1964 return false; |
1953 | 1965 |
1954 const HostCache::Entry* cache_entry = cache_->Lookup( | 1966 const HostCache::Entry* cache_entry = cache_->Lookup( |
1955 key, base::TimeTicks::Now()); | 1967 key, base::TimeTicks::Now()); |
1956 if (!cache_entry) | 1968 if (!cache_entry) |
1957 return false; | 1969 return false; |
1958 | 1970 |
1959 *net_error = cache_entry->error; | 1971 *net_error = cache_entry->error; |
1960 if (*net_error == OK) { | 1972 if (*net_error == OK) { |
1973 if (cache_entry->has_ttl()) | |
1974 RecordTTL(cache_entry->ttl); | |
1961 *addresses = cache_entry->addrlist; | 1975 *addresses = cache_entry->addrlist; |
1962 EnsurePortOnAddressList(info.port(), addresses); | 1976 EnsurePortOnAddressList(info.port(), addresses); |
1963 } | 1977 } |
1964 return true; | 1978 return true; |
1965 } | 1979 } |
1966 | 1980 |
1967 bool HostResolverImpl::ServeFromHosts(const Key& key, | 1981 bool HostResolverImpl::ServeFromHosts(const Key& key, |
1968 const RequestInfo& info, | 1982 const RequestInfo& info, |
1969 AddressList* addresses) { | 1983 AddressList* addresses) { |
1970 DCHECK(addresses); | 1984 DCHECK(addresses); |
(...skipping 20 matching lines...) Expand all Loading... | |
1991 it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); | 2005 it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); |
1992 if (it == hosts.end()) | 2006 if (it == hosts.end()) |
1993 return false; | 2007 return false; |
1994 } | 2008 } |
1995 | 2009 |
1996 *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); | 2010 *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); |
1997 return true; | 2011 return true; |
1998 } | 2012 } |
1999 | 2013 |
2000 void HostResolverImpl::CacheResult(const Key& key, | 2014 void HostResolverImpl::CacheResult(const Key& key, |
2001 int net_error, | 2015 const HostCache::Entry& entry, |
2002 const AddressList& addr_list, | |
2003 base::TimeDelta ttl) { | 2016 base::TimeDelta ttl) { |
2004 if (cache_.get()) | 2017 if (cache_.get()) |
2005 cache_->Set(key, net_error, addr_list, base::TimeTicks::Now(), ttl); | 2018 cache_->Set(key, entry, base::TimeTicks::Now(), ttl); |
2006 } | 2019 } |
2007 | 2020 |
2008 void HostResolverImpl::RemoveJob(Job* job) { | 2021 void HostResolverImpl::RemoveJob(Job* job) { |
2009 DCHECK(job); | 2022 DCHECK(job); |
2010 JobMap::iterator it = jobs_.find(job->key()); | 2023 JobMap::iterator it = jobs_.find(job->key()); |
2011 if (it != jobs_.end() && it->second == job) | 2024 if (it != jobs_.end() && it->second == job) |
2012 jobs_.erase(it); | 2025 jobs_.erase(it); |
2013 } | 2026 } |
2014 | 2027 |
2015 void HostResolverImpl::DiscardIPv6ProbeJob() { | 2028 void HostResolverImpl::DiscardIPv6ProbeJob() { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2146 // |this| may be deleted inside AbortAllInProgressJobs(). | 2159 // |this| may be deleted inside AbortAllInProgressJobs(). |
2147 if (self) | 2160 if (self) |
2148 TryServingAllJobsFromHosts(); | 2161 TryServingAllJobsFromHosts(); |
2149 } | 2162 } |
2150 | 2163 |
2151 bool HostResolverImpl::HaveDnsConfig() const { | 2164 bool HostResolverImpl::HaveDnsConfig() const { |
2152 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); | 2165 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); |
2153 } | 2166 } |
2154 | 2167 |
2155 } // namespace net | 2168 } // namespace net |
OLD | NEW |