blob: 4bc61ee72731ae12cc4e60941a82eee55ccbc540 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5// A DnsMaster object is instantiated once in the browser
6// process, and delivers DNS prefetch assignments (hostnames)
7// to any of several DnsSlave objects.
8// Most hostname lists are sent out by renderer processes, and
9// involve lists of hostnames that *might* be used in the near
10// future by the browsing user. The goal of this class is to
11// cause the underlying DNS structure to lookup a hostname before
12// it is really needed, and hence reduce latency in the standard
13// lookup paths. Since some DNS lookups may take a LONG time, we
14// use several DnsSlave threads to concurrently perform the
15// lookups.
16
[email protected]e8013b32008-10-27 18:55:5217#ifndef CHROME_BROWSER_NET_DNS_MASTER_H_
18#define CHROME_BROWSER_NET_DNS_MASTER_H_
initial.commit09911bf2008-07-26 23:55:2919
20#include <map>
21#include <queue>
22#include <string>
23
24#include "base/condition_variable.h"
25#include "base/scoped_ptr.h"
26#include "chrome/browser/net/dns_host_info.h"
[email protected]21dae9b2008-11-06 23:32:5327#include "chrome/browser/net/referrer.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/common/net/dns.h"
29#include "googleurl/src/url_canon.h"
30
31namespace chrome_browser_net {
32
33class DnsSlave;
34
35typedef chrome_common_net::NameList NameList;
36typedef std::map<std::string, DnsHostInfo> Results;
37
38class DnsMaster {
39 public:
[email protected]65ae4bc2008-08-22 11:38:1740 // The number of slave processes that will do DNS prefetching
41 static const int kSlaveCountMax = 8;
initial.commit09911bf2008-07-26 23:55:2942
[email protected]e1acf6f2008-10-27 20:43:3343 explicit DnsMaster(base::TimeDelta shutdown_wait_time);
initial.commit09911bf2008-07-26 23:55:2944
45 ~DnsMaster() {
46 if (!shutdown_)
47 ShutdownSlaves(); // Ensure we did our cleanup.
48 }
49
50 // ShutdownSlaves() gets all spawned threads to terminate, closes
51 // their handles, and deletes their DnsSlave instances.
52 // Return value of true means all operations succeeded.
53 // Return value of false means that the threads wouldn't terminate,
54 // and that resources may leak. If this returns false, it is best
55 // to NOT delete this DnsMaster, as slave threads may still call into
56 // this object.
57 bool ShutdownSlaves();
58
59 // In some circumstances, for privacy reasons, all results should be
60 // discarded. This method gracefully handles that activity.
61 // Destroy all our internal state, which shows what names we've looked up, and
62 // how long each has taken, etc. etc. We also destroy records of suggesses
63 // (cache hits etc.).
64 void DiscardAllResults();
65
66 // Add hostname(s) to the queue for processing by slaves
[email protected]21dae9b2008-11-06 23:32:5367 void ResolveList(const NameList& hostnames,
68 DnsHostInfo::ResolutionMotivation motivation);
69 void Resolve(const std::string& hostname,
70 DnsHostInfo::ResolutionMotivation motivation);
initial.commit09911bf2008-07-26 23:55:2971
72 // Get latency benefit of the prefetch that we are navigating to.
[email protected]21dae9b2008-11-06 23:32:5373 bool AccruePrefetchBenefits(const GURL& referrer,
74 DnsHostInfo* navigation_info);
initial.commit09911bf2008-07-26 23:55:2975
[email protected]21dae9b2008-11-06 23:32:5376 // Instigate prefetch of any domains we predict will be needed after this
77 // navigation.
78 void NavigatingTo(const std::string& host_name);
79
80 // Record details of a navigation so that we can preresolve the host name
81 // ahead of time the next time the users navigates to the indicated host.
82 void NonlinkNavigation(const GURL& referrer, DnsHostInfo* navigation_info);
83
84 // Dump HTML table containing list of referrers for about:dns.
85 void GetHtmlReferrerLists(std::string* output);
86
87 // Dump the list of currently know referrer domains and related prefetchable
88 // domains.
initial.commit09911bf2008-07-26 23:55:2989 void GetHtmlInfo(std::string* output);
90
91 // For testing only...
92 // Currently testing only provides a crude measure of success.
93 bool WasFound(const std::string& hostname) {
94 AutoLock auto_lock(lock_);
95 return (results_.find(hostname) != results_.end()) &&
96 results_[hostname].was_found();
97 }
98
99 // Accessor methods, used mostly for testing.
100 // Both functions return DnsHostInfo::kNullDuration if name was not yet
101 // processed enough.
[email protected]e1acf6f2008-10-27 20:43:33102 base::TimeDelta GetResolutionDuration(const std::string hostname) {
initial.commit09911bf2008-07-26 23:55:29103 AutoLock auto_lock(lock_);
104 if (results_.find(hostname) == results_.end())
105 return DnsHostInfo::kNullDuration;
106 return results_[hostname].resolve_duration();
107 }
108
[email protected]e1acf6f2008-10-27 20:43:33109 base::TimeDelta GetQueueDuration(const std::string hostname) {
initial.commit09911bf2008-07-26 23:55:29110 AutoLock auto_lock(lock_);
111 if (results_.find(hostname) == results_.end())
112 return DnsHostInfo::kNullDuration;
113 return results_[hostname].queue_duration();
114 }
115
116 int running_slave_count() {
117 AutoLock auto_lock(lock_);
118 return running_slave_count_;
119 }
120
121 //----------------------------------------------------------------------------
122 // Methods below this line should only be called by slave processes.
123
initial.commit09911bf2008-07-26 23:55:29124 // GetNextAssignment() gets the next hostname from queue for processing
125 // It is not meant to be public, and should only be used by the slave.
126 // GetNextAssignment() waits on a condition variable if there are no more
127 // names in queue.
128 // Return false if slave thread should terminate.
129 // Return true if slave thread should process the value.
130 bool GetNextAssignment(std::string* hostname);
131
132 // Access methods for use by slave threads to callback with state updates.
133 void SetFoundState(const std::string hostname);
134 void SetNoSuchNameState(const std::string hostname);
135
136 // Notification during ShutdownSlaves.
137 void SetSlaveHasTerminated(int slave_index);
138
139 private:
[email protected]21dae9b2008-11-06 23:32:53140 // A map that is keyed with the hostnames that we've learned were the cause
141 // of loading additional hostnames. The list of additional hostnames in held
142 // in a Referrer instance, which is found in this type.
143 typedef std::map<std::string, Referrer> Referrers;
initial.commit09911bf2008-07-26 23:55:29144
145 // "PreLocked" means that the caller has already Acquired lock_ in the
146 // following method names.
[email protected]21dae9b2008-11-06 23:32:53147 // Queue hostname for resolution. If queueing was done, return the pointer
148 // to the queued instance, otherwise return NULL.
149 DnsHostInfo* PreLockedResolve(const std::string& hostname,
150 DnsHostInfo::ResolutionMotivation motivation);
initial.commit09911bf2008-07-26 23:55:29151 bool PreLockedCreateNewSlaveIfNeeded(); // Lazy slave processes creation.
152
initial.commit09911bf2008-07-26 23:55:29153 // Number of slave processes started early (to help with startup prefetch).
154 static const int kSlaveCountMin = 4;
155
[email protected]21dae9b2008-11-06 23:32:53156 // Synchronize access to results_, referrers_, and slave control data.
initial.commit09911bf2008-07-26 23:55:29157 Lock lock_;
158
159 // name_buffer_ holds a list of names we need to look up.
160 std::queue<std::string> name_buffer_;
161
[email protected]21dae9b2008-11-06 23:32:53162 // results_ contains information for existing/prior prefetches.
initial.commit09911bf2008-07-26 23:55:29163 Results results_;
164
[email protected]21dae9b2008-11-06 23:32:53165 // For each hostname that we might navigate to (that we've "learned about")
166 // we have a Referrer list. Each Referrer list has all hostnames we need to
167 // pre-resolve when there is a navigation to the orginial hostname.
168 Referrers referrers_;
169
initial.commit09911bf2008-07-26 23:55:29170 // Signaling slaves to process elements in the queue, or to terminate,
171 // is done using ConditionVariables.
172 ConditionVariable slaves_have_work_;
173
174 int slave_count_; // Count of slave processes started.
175 int running_slave_count_; // Count of slaves process still running.
176
177 // The following arrays are only initialized as
178 // slave_count_ grows (up to the indicated max).
179 DWORD thread_ids_[kSlaveCountMax];
180 HANDLE thread_handles_[kSlaveCountMax];
181 DnsSlave* slaves_[kSlaveCountMax];
182
183 // shutdown_ is set to tell the slaves to terminate.
184 bool shutdown_;
185
186 // The following is the maximum time the ShutdownSlaves method
187 // will wait for all the slave processes to terminate.
[email protected]e1acf6f2008-10-27 20:43:33188 const base::TimeDelta kShutdownWaitTime_;
initial.commit09911bf2008-07-26 23:55:29189
190 // A list of successful events resulting from pre-fetching.
191 DnsHostInfo::DnsInfoTable cache_hits_;
192 // A map of hosts that were evicted from our cache (after we prefetched them)
193 // and before the HTTP stack tried to look them up.
194 Results cache_eviction_map_;
195
[email protected]e8013b32008-10-27 18:55:52196 DISALLOW_COPY_AND_ASSIGN(DnsMaster);
initial.commit09911bf2008-07-26 23:55:29197};
198
199} // namespace chrome_browser_net
200
[email protected]e8013b32008-10-27 18:55:52201#endif // CHROME_BROWSER_NET_DNS_MASTER_H_
license.botbf09a502008-08-24 00:55:55202