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/dns/dns_config_service.h" | 5 #include "net/dns/dns_config_service.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
9 #include "base/values.h" | 9 #include "base/values.h" |
10 #include "net/base/ip_endpoint.h" | 10 #include "net/base/ip_endpoint.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 } | 86 } |
87 | 87 |
88 DnsConfigService::DnsConfigService() | 88 DnsConfigService::DnsConfigService() |
89 : watch_failed_(false), | 89 : watch_failed_(false), |
90 have_config_(false), | 90 have_config_(false), |
91 have_hosts_(false), | 91 have_hosts_(false), |
92 need_update_(false), | 92 need_update_(false), |
93 last_sent_empty_(true) {} | 93 last_sent_empty_(true) {} |
94 | 94 |
95 DnsConfigService::~DnsConfigService() { | 95 DnsConfigService::~DnsConfigService() { |
| 96 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
96 } | 97 } |
97 | 98 |
98 void DnsConfigService::ReadConfig(const CallbackType& callback) { | 99 void DnsConfigService::ReadConfig(const CallbackType& callback) { |
99 DCHECK(CalledOnValidThread()); | 100 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
100 DCHECK(!callback.is_null()); | 101 DCHECK(!callback.is_null()); |
101 DCHECK(callback_.is_null()); | 102 DCHECK(callback_.is_null()); |
102 callback_ = callback; | 103 callback_ = callback; |
103 ReadNow(); | 104 ReadNow(); |
104 } | 105 } |
105 | 106 |
106 void DnsConfigService::WatchConfig(const CallbackType& callback) { | 107 void DnsConfigService::WatchConfig(const CallbackType& callback) { |
107 DCHECK(CalledOnValidThread()); | 108 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
108 DCHECK(!callback.is_null()); | 109 DCHECK(!callback.is_null()); |
109 DCHECK(callback_.is_null()); | 110 DCHECK(callback_.is_null()); |
110 callback_ = callback; | 111 callback_ = callback; |
111 watch_failed_ = !StartWatching(); | 112 watch_failed_ = !StartWatching(); |
112 ReadNow(); | 113 ReadNow(); |
113 } | 114 } |
114 | 115 |
115 void DnsConfigService::InvalidateConfig() { | 116 void DnsConfigService::InvalidateConfig() { |
116 DCHECK(CalledOnValidThread()); | 117 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
117 base::TimeTicks now = base::TimeTicks::Now(); | 118 base::TimeTicks now = base::TimeTicks::Now(); |
118 if (!last_invalidate_config_time_.is_null()) { | 119 if (!last_invalidate_config_time_.is_null()) { |
119 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.ConfigNotifyInterval", | 120 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.ConfigNotifyInterval", |
120 now - last_invalidate_config_time_); | 121 now - last_invalidate_config_time_); |
121 } | 122 } |
122 last_invalidate_config_time_ = now; | 123 last_invalidate_config_time_ = now; |
123 if (!have_config_) | 124 if (!have_config_) |
124 return; | 125 return; |
125 have_config_ = false; | 126 have_config_ = false; |
126 StartTimer(); | 127 StartTimer(); |
127 } | 128 } |
128 | 129 |
129 void DnsConfigService::InvalidateHosts() { | 130 void DnsConfigService::InvalidateHosts() { |
130 DCHECK(CalledOnValidThread()); | 131 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
131 base::TimeTicks now = base::TimeTicks::Now(); | 132 base::TimeTicks now = base::TimeTicks::Now(); |
132 if (!last_invalidate_hosts_time_.is_null()) { | 133 if (!last_invalidate_hosts_time_.is_null()) { |
133 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.HostsNotifyInterval", | 134 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.HostsNotifyInterval", |
134 now - last_invalidate_hosts_time_); | 135 now - last_invalidate_hosts_time_); |
135 } | 136 } |
136 last_invalidate_hosts_time_ = now; | 137 last_invalidate_hosts_time_ = now; |
137 if (!have_hosts_) | 138 if (!have_hosts_) |
138 return; | 139 return; |
139 have_hosts_ = false; | 140 have_hosts_ = false; |
140 StartTimer(); | 141 StartTimer(); |
141 } | 142 } |
142 | 143 |
143 void DnsConfigService::OnConfigRead(const DnsConfig& config) { | 144 void DnsConfigService::OnConfigRead(const DnsConfig& config) { |
144 DCHECK(CalledOnValidThread()); | 145 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
145 DCHECK(config.IsValid()); | 146 DCHECK(config.IsValid()); |
146 | 147 |
147 bool changed = false; | 148 bool changed = false; |
148 if (!config.EqualsIgnoreHosts(dns_config_)) { | 149 if (!config.EqualsIgnoreHosts(dns_config_)) { |
149 dns_config_.CopyIgnoreHosts(config); | 150 dns_config_.CopyIgnoreHosts(config); |
150 need_update_ = true; | 151 need_update_ = true; |
151 changed = true; | 152 changed = true; |
152 } | 153 } |
153 if (!changed && !last_sent_empty_time_.is_null()) { | 154 if (!changed && !last_sent_empty_time_.is_null()) { |
154 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.UnchangedConfigInterval", | 155 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.UnchangedConfigInterval", |
155 base::TimeTicks::Now() - last_sent_empty_time_); | 156 base::TimeTicks::Now() - last_sent_empty_time_); |
156 } | 157 } |
157 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigChange", changed); | 158 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigChange", changed); |
158 | 159 |
159 have_config_ = true; | 160 have_config_ = true; |
160 if (have_hosts_ || watch_failed_) | 161 if (have_hosts_ || watch_failed_) |
161 OnCompleteConfig(); | 162 OnCompleteConfig(); |
162 } | 163 } |
163 | 164 |
164 void DnsConfigService::OnHostsRead(const DnsHosts& hosts) { | 165 void DnsConfigService::OnHostsRead(const DnsHosts& hosts) { |
165 DCHECK(CalledOnValidThread()); | 166 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
166 | 167 |
167 bool changed = false; | 168 bool changed = false; |
168 if (hosts != dns_config_.hosts) { | 169 if (hosts != dns_config_.hosts) { |
169 dns_config_.hosts = hosts; | 170 dns_config_.hosts = hosts; |
170 need_update_ = true; | 171 need_update_ = true; |
171 changed = true; | 172 changed = true; |
172 } | 173 } |
173 if (!changed && !last_sent_empty_time_.is_null()) { | 174 if (!changed && !last_sent_empty_time_.is_null()) { |
174 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.UnchangedHostsInterval", | 175 UMA_HISTOGRAM_LONG_TIMES("AsyncDNS.UnchangedHostsInterval", |
175 base::TimeTicks::Now() - last_sent_empty_time_); | 176 base::TimeTicks::Now() - last_sent_empty_time_); |
176 } | 177 } |
177 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostsChange", changed); | 178 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostsChange", changed); |
178 | 179 |
179 have_hosts_ = true; | 180 have_hosts_ = true; |
180 if (have_config_ || watch_failed_) | 181 if (have_config_ || watch_failed_) |
181 OnCompleteConfig(); | 182 OnCompleteConfig(); |
182 } | 183 } |
183 | 184 |
184 void DnsConfigService::StartTimer() { | 185 void DnsConfigService::StartTimer() { |
185 DCHECK(CalledOnValidThread()); | 186 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
186 if (last_sent_empty_) { | 187 if (last_sent_empty_) { |
187 DCHECK(!timer_.IsRunning()); | 188 DCHECK(!timer_.IsRunning()); |
188 return; // No need to withdraw again. | 189 return; // No need to withdraw again. |
189 } | 190 } |
190 timer_.Stop(); | 191 timer_.Stop(); |
191 | 192 |
192 // Give it a short timeout to come up with a valid config. Otherwise withdraw | 193 // Give it a short timeout to come up with a valid config. Otherwise withdraw |
193 // the config from the receiver. The goal is to avoid perceivable network | 194 // the config from the receiver. The goal is to avoid perceivable network |
194 // outage (when using the wrong config) but at the same time avoid | 195 // outage (when using the wrong config) but at the same time avoid |
195 // unnecessary Job aborts in HostResolverImpl. The signals come from multiple | 196 // unnecessary Job aborts in HostResolverImpl. The signals come from multiple |
196 // sources so it might receive multiple events during a config change. | 197 // sources so it might receive multiple events during a config change. |
197 | 198 |
198 // DHCP and user-induced changes are on the order of seconds, so 150ms should | 199 // DHCP and user-induced changes are on the order of seconds, so 150ms should |
199 // not add perceivable delay. On the other hand, config readers should finish | 200 // not add perceivable delay. On the other hand, config readers should finish |
200 // within 150ms with the rare exception of I/O block or extra large HOSTS. | 201 // within 150ms with the rare exception of I/O block or extra large HOSTS. |
201 const base::TimeDelta kTimeout = base::TimeDelta::FromMilliseconds(150); | 202 const base::TimeDelta kTimeout = base::TimeDelta::FromMilliseconds(150); |
202 | 203 |
203 timer_.Start(FROM_HERE, | 204 timer_.Start(FROM_HERE, |
204 kTimeout, | 205 kTimeout, |
205 this, | 206 this, |
206 &DnsConfigService::OnTimeout); | 207 &DnsConfigService::OnTimeout); |
207 } | 208 } |
208 | 209 |
209 void DnsConfigService::OnTimeout() { | 210 void DnsConfigService::OnTimeout() { |
210 DCHECK(CalledOnValidThread()); | 211 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
211 DCHECK(!last_sent_empty_); | 212 DCHECK(!last_sent_empty_); |
212 // Indicate that even if there is no change in On*Read, we will need to | 213 // Indicate that even if there is no change in On*Read, we will need to |
213 // update the receiver when the config becomes complete. | 214 // update the receiver when the config becomes complete. |
214 need_update_ = true; | 215 need_update_ = true; |
215 // Empty config is considered invalid. | 216 // Empty config is considered invalid. |
216 last_sent_empty_ = true; | 217 last_sent_empty_ = true; |
217 last_sent_empty_time_ = base::TimeTicks::Now(); | 218 last_sent_empty_time_ = base::TimeTicks::Now(); |
218 callback_.Run(DnsConfig()); | 219 callback_.Run(DnsConfig()); |
219 } | 220 } |
220 | 221 |
221 void DnsConfigService::OnCompleteConfig() { | 222 void DnsConfigService::OnCompleteConfig() { |
222 timer_.Stop(); | 223 timer_.Stop(); |
223 if (!need_update_) | 224 if (!need_update_) |
224 return; | 225 return; |
225 need_update_ = false; | 226 need_update_ = false; |
226 last_sent_empty_ = false; | 227 last_sent_empty_ = false; |
227 if (watch_failed_) { | 228 if (watch_failed_) { |
228 // If a watch failed, the config may not be accurate, so report empty. | 229 // If a watch failed, the config may not be accurate, so report empty. |
229 callback_.Run(DnsConfig()); | 230 callback_.Run(DnsConfig()); |
230 } else { | 231 } else { |
231 callback_.Run(dns_config_); | 232 callback_.Run(dns_config_); |
232 } | 233 } |
233 } | 234 } |
234 | 235 |
235 } // namespace net | 236 } // namespace net |
OLD | NEW |