| 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 |