Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // A DnsMaster object is instantiated once in the browser | 5 // A DnsMaster object is instantiated once in the browser |
| 6 // process, and delivers DNS prefetch assignments (hostnames) | 6 // process, and manages asynchronous resolution of DNS hostnames. |
| 7 // to any of several DnsSlave objects. | |
| 8 // Most hostname lists are sent out by renderer processes, and | 7 // Most hostname lists are sent out by renderer processes, and |
| 9 // involve lists of hostnames that *might* be used in the near | 8 // involve lists of hostnames that *might* be used in the near |
| 10 // future by the browsing user. The goal of this class is to | 9 // future by the browsing user. The goal of this class is to |
| 11 // cause the underlying DNS structure to lookup a hostname before | 10 // cause the underlying DNS structure to lookup a hostname before |
| 12 // it is really needed, and hence reduce latency in the standard | 11 // it is really needed, and hence reduce latency in the standard |
| 13 // lookup paths. Since some DNS lookups may take a LONG time, we | 12 // lookup paths. |
| 14 // use several DnsSlave threads to concurrently perform the | |
| 15 // lookups. | |
| 16 | 13 |
| 17 #ifndef CHROME_BROWSER_NET_DNS_MASTER_H_ | 14 #ifndef CHROME_BROWSER_NET_DNS_MASTER_H_ |
| 18 #define CHROME_BROWSER_NET_DNS_MASTER_H_ | 15 #define CHROME_BROWSER_NET_DNS_MASTER_H_ |
| 19 | 16 |
| 20 #include <map> | 17 #include <map> |
| 21 #include <queue> | 18 #include <queue> |
| 19 #include <set> | |
| 22 #include <string> | 20 #include <string> |
| 23 | 21 |
| 24 #include "base/condition_variable.h" | 22 #include "base/lock.h" |
| 25 #include "base/scoped_ptr.h" | |
| 26 #include "base/values.h" | |
| 27 #include "chrome/browser/net/dns_host_info.h" | 23 #include "chrome/browser/net/dns_host_info.h" |
| 28 #include "chrome/browser/net/referrer.h" | 24 #include "chrome/browser/net/referrer.h" |
| 29 #include "chrome/common/net/dns.h" | 25 #include "chrome/common/net/dns.h" |
| 30 #include "googleurl/src/url_canon.h" | 26 #include "googleurl/src/url_canon.h" |
| 27 #include "testing/gtest/include/gtest/gtest_prod.h" | |
| 31 | 28 |
| 32 namespace chrome_browser_net { | 29 namespace chrome_browser_net { |
| 33 | 30 |
| 34 class DnsSlave; | |
| 35 | |
| 36 typedef chrome_common_net::NameList NameList; | 31 typedef chrome_common_net::NameList NameList; |
| 37 typedef std::map<std::string, DnsHostInfo> Results; | 32 typedef std::map<std::string, DnsHostInfo> Results; |
| 38 | 33 |
| 39 class DnsMaster { | 34 class DnsMaster { |
| 40 public: | 35 public: |
| 41 // The number of slave processes that will do DNS prefetching | 36 // Too many concurrent lookups negate benefits of prefetching |
| 42 static const size_t kSlaveCountMax = 8; | 37 // by trashing the OS cache. |
| 38 static const size_t kMaxConcurrentLookups; | |
| 43 | 39 |
| 44 explicit DnsMaster(base::TimeDelta shutdown_wait_time); | 40 DnsMaster(); |
| 41 ~DnsMaster(); | |
| 45 | 42 |
| 46 ~DnsMaster() { | 43 // Cancel pending requests and prevent new ones from being made. |
| 47 if (!shutdown_) | 44 void Shutdown(); |
| 48 ShutdownSlaves(); // Ensure we did our cleanup. | |
| 49 } | |
| 50 | |
| 51 // ShutdownSlaves() gets all spawned threads to terminate, closes | |
| 52 // their handles, and deletes their DnsSlave instances. | |
| 53 // Return value of true means all operations succeeded. | |
| 54 // Return value of false means that the threads wouldn't terminate, | |
| 55 // and that resources may leak. If this returns false, it is best | |
| 56 // to NOT delete this DnsMaster, as slave threads may still call into | |
| 57 // this object. | |
| 58 bool ShutdownSlaves(); | |
| 59 | 45 |
| 60 // In some circumstances, for privacy reasons, all results should be | 46 // In some circumstances, for privacy reasons, all results should be |
| 61 // discarded. This method gracefully handles that activity. | 47 // discarded. This method gracefully handles that activity. |
| 62 // Destroy all our internal state, which shows what names we've looked up, and | 48 // Destroy all our internal state, which shows what names we've looked up, and |
| 63 // how long each has taken, etc. etc. We also destroy records of suggesses | 49 // how long each has taken, etc. etc. We also destroy records of suggesses |
| 64 // (cache hits etc.). | 50 // (cache hits etc.). |
| 65 void DiscardAllResults(); | 51 void DiscardAllResults(); |
| 66 | 52 |
| 67 // Add hostname(s) to the queue for processing by slaves | 53 // Add hostname(s) to the queue for processing. |
| 68 void ResolveList(const NameList& hostnames, | 54 void ResolveList(const NameList& hostnames, |
| 69 DnsHostInfo::ResolutionMotivation motivation); | 55 DnsHostInfo::ResolutionMotivation motivation); |
| 70 void Resolve(const std::string& hostname, | 56 void Resolve(const std::string& hostname, |
| 71 DnsHostInfo::ResolutionMotivation motivation); | 57 DnsHostInfo::ResolutionMotivation motivation); |
| 72 | 58 |
| 73 // Get latency benefit of the prefetch that we are navigating to. | 59 // Get latency benefit of the prefetch that we are navigating to. |
| 74 bool AccruePrefetchBenefits(const GURL& referrer, | 60 bool AccruePrefetchBenefits(const GURL& referrer, |
| 75 DnsHostInfo* navigation_info); | 61 DnsHostInfo* navigation_info); |
| 76 | 62 |
| 77 // Instigate prefetch of any domains we predict will be needed after this | 63 // Instigate prefetch of any domains we predict will be needed after this |
| 78 // navigation. | 64 // navigation. |
| 79 void NavigatingTo(const std::string& host_name); | 65 void NavigatingTo(const std::string& host_name); |
| 80 | 66 |
| 81 // Record details of a navigation so that we can preresolve the host name | 67 // Record details of a navigation so that we can preresolve the host name |
| 82 // ahead of time the next time the users navigates to the indicated host. | 68 // ahead of time the next time the users navigates to the indicated host. |
| 83 void NonlinkNavigation(const GURL& referrer, DnsHostInfo* navigation_info); | 69 void NonlinkNavigation(const GURL& referrer, DnsHostInfo* navigation_info); |
| 84 | 70 |
| 85 // Dump HTML table containing list of referrers for about:dns. | 71 // Dump HTML table containing list of referrers for about:dns. |
| 86 void GetHtmlReferrerLists(std::string* output); | 72 void GetHtmlReferrerLists(std::string* output); |
| 87 | 73 |
| 88 // Dump the list of currently know referrer domains and related prefetchable | 74 // Dump the list of currently know referrer domains and related prefetchable |
| 89 // domains. | 75 // domains. |
| 90 void GetHtmlInfo(std::string* output); | 76 void GetHtmlInfo(std::string* output); |
| 91 | 77 |
| 92 // For testing only... | |
| 93 // Currently testing only provides a crude measure of success. | |
| 94 bool WasFound(const std::string& hostname) { | |
| 95 AutoLock auto_lock(lock_); | |
| 96 return (results_.find(hostname) != results_.end()) && | |
| 97 results_[hostname].was_found(); | |
| 98 } | |
| 99 | |
| 100 // Accessor methods, used mostly for testing. | |
| 101 // Both functions return DnsHostInfo::kNullDuration if name was not yet | |
| 102 // processed enough. | |
| 103 base::TimeDelta GetResolutionDuration(const std::string hostname) { | |
| 104 AutoLock auto_lock(lock_); | |
| 105 if (results_.find(hostname) == results_.end()) | |
| 106 return DnsHostInfo::kNullDuration; | |
| 107 return results_[hostname].resolve_duration(); | |
| 108 } | |
| 109 | |
| 110 base::TimeDelta GetQueueDuration(const std::string hostname) { | |
| 111 AutoLock auto_lock(lock_); | |
| 112 if (results_.find(hostname) == results_.end()) | |
| 113 return DnsHostInfo::kNullDuration; | |
| 114 return results_[hostname].queue_duration(); | |
| 115 } | |
| 116 | |
| 117 size_t running_slave_count() { | |
| 118 AutoLock auto_lock(lock_); | |
| 119 return running_slave_count_; | |
| 120 } | |
| 121 | |
| 122 // Discard any referrer for which all the suggested host names are currently | 78 // Discard any referrer for which all the suggested host names are currently |
| 123 // annotated with no user latency reduction. Also scale down (diminish) the | 79 // annotated with no user latency reduction. Also scale down (diminish) the |
| 124 // total benefit of those that did help, so that their reported contribution | 80 // total benefit of those that did help, so that their reported contribution |
| 125 // wll go done by a factor of 2 each time we trim (moving the referrer closer | 81 // wll go done by a factor of 2 each time we trim (moving the referrer closer |
| 126 // to being discarded at a future Trim). | 82 // to being discarded at a future Trim). |
| 127 void TrimReferrers(); | 83 void TrimReferrers(); |
| 128 | 84 |
| 129 // Construct a ListValue object that contains all the data in the referrers_ | 85 // Construct a ListValue object that contains all the data in the referrers_ |
| 130 // so that it can be persisted in a pref. | 86 // so that it can be persisted in a pref. |
| 131 void SerializeReferrers(ListValue* referral_list); | 87 void SerializeReferrers(ListValue* referral_list); |
| 132 | 88 |
| 133 // Process a ListValue that contains all the data from a previous reference | 89 // Process a ListValue that contains all the data from a previous reference |
| 134 // list, as constructed by SerializeReferrers(), and add all the identified | 90 // list, as constructed by SerializeReferrers(), and add all the identified |
| 135 // values into the current referrer list. | 91 // values into the current referrer list. |
| 136 void DeserializeReferrers(const ListValue& referral_list); | 92 void DeserializeReferrers(const ListValue& referral_list); |
| 137 | 93 |
| 138 //---------------------------------------------------------------------------- | 94 private: |
| 139 // Methods below this line should only be called by slave processes. | 95 FRIEND_TEST(DnsMasterTest, BenefitLookupTest); |
| 96 FRIEND_TEST(DnsMasterTest, ShutdownWhenResolutionIsPendingTest); | |
| 97 FRIEND_TEST(DnsMasterTest, SingleLookupTest); | |
| 98 FRIEND_TEST(DnsMasterTest, ConcurrentLookupTest); | |
| 99 FRIEND_TEST(DnsMasterTest, MassiveConcurrentLookupTest); | |
| 100 friend class WaitForResolutionHelper; // For testing. | |
| 140 | 101 |
| 141 // GetNextAssignment() gets the next hostname from queue for processing | 102 class LookupRequest; |
| 142 // It is not meant to be public, and should only be used by the slave. | |
| 143 // GetNextAssignment() waits on a condition variable if there are no more | |
| 144 // names in queue. | |
| 145 // Return false if slave thread should terminate. | |
| 146 // Return true if slave thread should process the value. | |
| 147 bool GetNextAssignment(std::string* hostname); | |
| 148 | 103 |
| 149 // Access methods for use by slave threads to callback with state updates. | |
| 150 void SetFoundState(const std::string hostname); | |
| 151 void SetNoSuchNameState(const std::string hostname); | |
| 152 | |
| 153 // Notification during ShutdownSlaves. | |
| 154 void SetSlaveHasTerminated(int slave_index); | |
| 155 | |
| 156 private: | |
| 157 // A map that is keyed with the hostnames that we've learned were the cause | 104 // A map that is keyed with the hostnames that we've learned were the cause |
| 158 // of loading additional hostnames. The list of additional hostnames in held | 105 // of loading additional hostnames. The list of additional hostnames in held |
| 159 // in a Referrer instance, which is found in this type. | 106 // in a Referrer instance, which is found in this type. |
| 160 typedef std::map<std::string, Referrer> Referrers; | 107 typedef std::map<std::string, Referrer> Referrers; |
| 161 | 108 |
| 109 // Only for testing. Returns true if hostname has been successfully resolved | |
| 110 // (name found). | |
| 111 bool WasFound(const std::string& hostname) { | |
| 112 AutoLock auto_lock(lock_); | |
| 113 return (results_.find(hostname) != results_.end()) && | |
| 114 results_[hostname].was_found(); | |
| 115 } | |
| 116 | |
| 117 // Only for testing. Return how long was the resolution | |
| 118 // or DnsHostInfo::kNullDuration if it hasn't been resolved yet. | |
| 119 base::TimeDelta GetResolutionDuration(const std::string& hostname) { | |
| 120 AutoLock auto_lock(lock_); | |
| 121 if (results_.find(hostname) == results_.end()) | |
| 122 return DnsHostInfo::kNullDuration; | |
| 123 return results_[hostname].resolve_duration(); | |
| 124 } | |
| 125 | |
| 126 // Only for testing; | |
| 127 size_t peak_pending_lookups() const { return peak_pending_lookups_; } | |
| 128 | |
| 129 // Access method for use by lookup request to pass resolution result. | |
| 130 void OnLookupFinished(LookupRequest* request, | |
| 131 const std::string& hostname, bool found); | |
| 132 | |
| 162 // "PreLocked" means that the caller has already Acquired lock_ in the | 133 // "PreLocked" means that the caller has already Acquired lock_ in the |
| 163 // following method names. | 134 // following method names. |
| 164 // Queue hostname for resolution. If queueing was done, return the pointer | 135 // Queue hostname for resolution. If queueing was done, return the pointer |
| 165 // to the queued instance, otherwise return NULL. | 136 // to the queued instance, otherwise return NULL. |
| 166 DnsHostInfo* PreLockedResolve(const std::string& hostname, | 137 DnsHostInfo* PreLockedResolve(const std::string& hostname, |
| 167 DnsHostInfo::ResolutionMotivation motivation); | 138 DnsHostInfo::ResolutionMotivation motivation); |
| 168 bool PreLockedCreateNewSlaveIfNeeded(); // Lazy slave processes creation. | |
| 169 | 139 |
| 170 // Number of slave processes started early (to help with startup prefetch). | 140 // Take lookup requests from name_buffer_ and tell HostResolver |
| 171 static const size_t kSlaveCountMin = 4; | 141 // to look them up asynchronously, provided we don't exceed |
| 142 // concurrent resolution limit. | |
| 143 void PreLockedScheduleLookups(); | |
| 172 | 144 |
| 173 // Synchronize access to results_, referrers_, and slave control data. | 145 // Synchronize access to variables listed below. |
|
darin (slow to review)
2009/02/18 21:49:17
looks like a good comment to me.
| |
| 174 Lock lock_; | 146 Lock lock_; |
| 175 | 147 |
| 176 // name_buffer_ holds a list of names we need to look up. | 148 // name_buffer_ holds a list of names we need to look up. |
| 177 std::queue<std::string> name_buffer_; | 149 std::queue<std::string> name_buffer_; |
| 178 | 150 |
| 179 // results_ contains information for existing/prior prefetches. | 151 // results_ contains information for existing/prior prefetches. |
| 180 Results results_; | 152 Results results_; |
| 181 | 153 |
| 182 // For each hostname that we might navigate to (that we've "learned about") | 154 // For each hostname that we might navigate to (that we've "learned about") |
| 183 // we have a Referrer list. Each Referrer list has all hostnames we need to | 155 // we have a Referrer list. Each Referrer list has all hostnames we need to |
| 184 // pre-resolve when there is a navigation to the orginial hostname. | 156 // pre-resolve when there is a navigation to the orginial hostname. |
| 185 Referrers referrers_; | 157 Referrers referrers_; |
| 186 | 158 |
| 187 // Signaling slaves to process elements in the queue, or to terminate, | 159 std::set<LookupRequest*> pending_lookups_; |
| 188 // is done using ConditionVariables. | |
| 189 ConditionVariable slaves_have_work_; | |
| 190 | 160 |
| 191 size_t slave_count_; // Count of slave processes started. | 161 // For testing, to verify that we don't exceed the limit. |
| 192 size_t running_slave_count_; // Count of slaves process still running. | 162 size_t peak_pending_lookups_; |
| 193 | 163 |
| 194 // TODO(jrg): wait for CL 15076 from _ph to come in which resolves | 164 // When true, we don't make new lookup requests. |
| 195 // this. In the short term this file is hacked to be happy when | |
| 196 // included in render_process.h. | |
| 197 #if defined(OS_WIN) | |
| 198 // The following arrays are only initialized as | |
| 199 // slave_count_ grows (up to the indicated max). | |
| 200 DWORD thread_ids_[kSlaveCountMax]; | |
| 201 HANDLE thread_handles_[kSlaveCountMax]; | |
| 202 DnsSlave* slaves_[kSlaveCountMax]; | |
| 203 #endif | |
| 204 | |
| 205 // shutdown_ is set to tell the slaves to terminate. | |
| 206 bool shutdown_; | 165 bool shutdown_; |
| 207 | 166 |
| 208 // The following is the maximum time the ShutdownSlaves method | |
| 209 // will wait for all the slave processes to terminate. | |
| 210 const base::TimeDelta kShutdownWaitTime_; | |
| 211 | |
| 212 // A list of successful events resulting from pre-fetching. | 167 // A list of successful events resulting from pre-fetching. |
| 213 DnsHostInfo::DnsInfoTable cache_hits_; | 168 DnsHostInfo::DnsInfoTable cache_hits_; |
| 214 // A map of hosts that were evicted from our cache (after we prefetched them) | 169 // A map of hosts that were evicted from our cache (after we prefetched them) |
| 215 // and before the HTTP stack tried to look them up. | 170 // and before the HTTP stack tried to look them up. |
| 216 Results cache_eviction_map_; | 171 Results cache_eviction_map_; |
| 217 | 172 |
| 218 DISALLOW_COPY_AND_ASSIGN(DnsMaster); | 173 DISALLOW_COPY_AND_ASSIGN(DnsMaster); |
| 219 }; | 174 }; |
| 220 | 175 |
| 221 } // namespace chrome_browser_net | 176 } // namespace chrome_browser_net |
| 222 | 177 |
| 223 #endif // CHROME_BROWSER_NET_DNS_MASTER_H_ | 178 #endif // CHROME_BROWSER_NET_DNS_MASTER_H_ |
| 224 | 179 |
| OLD | NEW |