diff options
Diffstat (limited to 'chrome/browser/net/dns_master.h')
-rw-r--r-- | chrome/browser/net/dns_master.h | 134 |
1 files changed, 86 insertions, 48 deletions
diff --git a/chrome/browser/net/dns_master.h b/chrome/browser/net/dns_master.h index 78f5540..7620d7c 100644 --- a/chrome/browser/net/dns_master.h +++ b/chrome/browser/net/dns_master.h @@ -3,13 +3,16 @@ // found in the LICENSE file. // A DnsMaster object is instantiated once in the browser -// process, and manages asynchronous resolution of DNS hostnames. +// process, and delivers DNS prefetch assignments (hostnames) +// to any of several DnsSlave objects. // Most hostname lists are sent out by renderer processes, and // involve lists of hostnames that *might* be used in the near // future by the browsing user. The goal of this class is to // cause the underlying DNS structure to lookup a hostname before // it is really needed, and hence reduce latency in the standard -// lookup paths. +// lookup paths. Since some DNS lookups may take a LONG time, we +// use several DnsSlave threads to concurrently perform the +// lookups. #ifndef CHROME_BROWSER_NET_DNS_MASTER_H_ #define CHROME_BROWSER_NET_DNS_MASTER_H_ @@ -18,27 +21,40 @@ #include <queue> #include <string> -#include "base/lock.h" -#include "base/revocable_store.h" +#include "base/condition_variable.h" +#include "base/scoped_ptr.h" #include "chrome/browser/net/dns_host_info.h" #include "chrome/browser/net/referrer.h" #include "chrome/common/net/dns.h" #include "googleurl/src/url_canon.h" -#include "testing/gtest/include/gtest/gtest_prod.h" namespace chrome_browser_net { +class DnsSlave; + typedef chrome_common_net::NameList NameList; typedef std::map<std::string, DnsHostInfo> Results; class DnsMaster { public: - // Too many concurrent lookups negate benefits of prefetching - // by trashing the OS cache. - static const size_t kMaxConcurrentLookups; + // The number of slave processes that will do DNS prefetching + static const size_t kSlaveCountMax = 8; + + explicit DnsMaster(base::TimeDelta shutdown_wait_time); + + ~DnsMaster() { + if (!shutdown_) + ShutdownSlaves(); // Ensure we did our cleanup. + } - DnsMaster(); - ~DnsMaster(); + // ShutdownSlaves() gets all spawned threads to terminate, closes + // their handles, and deletes their DnsSlave instances. + // Return value of true means all operations succeeded. + // Return value of false means that the threads wouldn't terminate, + // and that resources may leak. If this returns false, it is best + // to NOT delete this DnsMaster, as slave threads may still call into + // this object. + bool ShutdownSlaves(); // In some circumstances, for privacy reasons, all results should be // discarded. This method gracefully handles that activity. @@ -47,7 +63,7 @@ class DnsMaster { // (cache hits etc.). void DiscardAllResults(); - // Add hostname(s) to the queue for processing. + // Add hostname(s) to the queue for processing by slaves void ResolveList(const NameList& hostnames, DnsHostInfo::ResolutionMotivation motivation); void Resolve(const std::string& hostname, @@ -72,62 +88,72 @@ class DnsMaster { // domains. void GetHtmlInfo(std::string* output); - private: - FRIEND_TEST(DnsMasterTest, BenefitLookupTest); - FRIEND_TEST(DnsMasterTest, ShutdownWhenResolutionIsPendingTest); - FRIEND_TEST(DnsMasterTest, SingleLookupTest); - FRIEND_TEST(DnsMasterTest, ConcurrentLookupTest); - FRIEND_TEST(DnsMasterTest, MassiveConcurrentLookupTest); - friend class WaitForResolutionHelper; // For testing. - - class LookupRequest; - - // A map that is keyed with the hostnames that we've learned were the cause - // of loading additional hostnames. The list of additional hostnames in held - // in a Referrer instance, which is found in this type. - typedef std::map<std::string, Referrer> Referrers; - - // Only for testing. Returns true if hostname has been successfully resolved - // (name found). + // For testing only... + // Currently testing only provides a crude measure of success. bool WasFound(const std::string& hostname) { AutoLock auto_lock(lock_); return (results_.find(hostname) != results_.end()) && results_[hostname].was_found(); } - // Only for testing. Return how long was the resolution - // or DnsHostInfo::kNullDuration if it hasn't been resolved yet. - base::TimeDelta GetResolutionDuration(const std::string& hostname) { + // Accessor methods, used mostly for testing. + // Both functions return DnsHostInfo::kNullDuration if name was not yet + // processed enough. + base::TimeDelta GetResolutionDuration(const std::string hostname) { AutoLock auto_lock(lock_); if (results_.find(hostname) == results_.end()) return DnsHostInfo::kNullDuration; return results_[hostname].resolve_duration(); } - // Only for testing; - size_t peak_pending_lookups() const { return peak_pending_lookups_; } + base::TimeDelta GetQueueDuration(const std::string hostname) { + AutoLock auto_lock(lock_); + if (results_.find(hostname) == results_.end()) + return DnsHostInfo::kNullDuration; + return results_[hostname].queue_duration(); + } + + size_t running_slave_count() { + AutoLock auto_lock(lock_); + return running_slave_count_; + } + + //---------------------------------------------------------------------------- + // Methods below this line should only be called by slave processes. + + // GetNextAssignment() gets the next hostname from queue for processing + // It is not meant to be public, and should only be used by the slave. + // GetNextAssignment() waits on a condition variable if there are no more + // names in queue. + // Return false if slave thread should terminate. + // Return true if slave thread should process the value. + bool GetNextAssignment(std::string* hostname); - // Access methods for use by lookup callbacks to pass resolution result. + // Access methods for use by slave threads to callback with state updates. void SetFoundState(const std::string hostname); void SetNoSuchNameState(const std::string hostname); + // Notification during ShutdownSlaves. + void SetSlaveHasTerminated(int slave_index); + + private: + // A map that is keyed with the hostnames that we've learned were the cause + // of loading additional hostnames. The list of additional hostnames in held + // in a Referrer instance, which is found in this type. + typedef std::map<std::string, Referrer> Referrers; + // "PreLocked" means that the caller has already Acquired lock_ in the // following method names. // Queue hostname for resolution. If queueing was done, return the pointer // to the queued instance, otherwise return NULL. DnsHostInfo* PreLockedResolve(const std::string& hostname, DnsHostInfo::ResolutionMotivation motivation); + bool PreLockedCreateNewSlaveIfNeeded(); // Lazy slave processes creation. - // Take lookup requests from name_buffer_ and tell HostResolver - // to look them up asynchronously, provided we don't exceed - // concurrent resolution limit. - void PreLockedScheduleLookups(); + // Number of slave processes started early (to help with startup prefetch). + static const size_t kSlaveCountMin = 4; - // Synchronize access to results_, referrers_, pending_lookups_. - // TODO(phajdan.jr): Re-evaluate usage of this lock. After restructuring - // the code to run only on the IO thread and using PostTask from other threads - // the lock should not be needed. If that's not possible, then at least its - // usage can be reduced. + // Synchronize access to results_, referrers_, and slave control data. Lock lock_; // name_buffer_ holds a list of names we need to look up. @@ -141,13 +167,25 @@ class DnsMaster { // pre-resolve when there is a navigation to the orginial hostname. Referrers referrers_; - // Count of started, but not yet finished dns lookups - size_t pending_lookups_; + // Signaling slaves to process elements in the queue, or to terminate, + // is done using ConditionVariables. + ConditionVariable slaves_have_work_; + + size_t slave_count_; // Count of slave processes started. + size_t running_slave_count_; // Count of slaves process still running. + + // The following arrays are only initialized as + // slave_count_ grows (up to the indicated max). + DWORD thread_ids_[kSlaveCountMax]; + HANDLE thread_handles_[kSlaveCountMax]; + DnsSlave* slaves_[kSlaveCountMax]; - // For testing, to verify that we don't exceed the limit; - size_t peak_pending_lookups_; + // shutdown_ is set to tell the slaves to terminate. + bool shutdown_; - RevocableStore pending_callbacks_; // We'll cancel them on shutdown. + // The following is the maximum time the ShutdownSlaves method + // will wait for all the slave processes to terminate. + const base::TimeDelta kShutdownWaitTime_; // A list of successful events resulting from pre-fetching. DnsHostInfo::DnsInfoTable cache_hits_; |