Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: net/dns/stale_host_resolver.cc

Issue 1898873006: Cronet: Use stale DNS cache entries experimentally. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@dns_stale2
Patch Set: Make requested changes. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/dns/stale_host_resolver.h ('k') | net/net.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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.
4
5 #include "net/dns/stale_host_resolver.h"
6
7 #include "base/metrics/histogram_macros.h"
8 #include "base/timer/timer.h"
9 #include "base/values.h"
10 #include "net/base/net_errors.h"
11 #include "net/dns/dns_util.h"
12
13 #define STALE_HISTOGRAM_ENUM(name, value, max) \
14 UMA_HISTOGRAM_ENUMERATION("DNS.StaleHostResolver." name, value, max)
15
16 #define STALE_HISTOGRAM_TIME(name, time) \
17 UMA_HISTOGRAM_MEDIUM_TIMES("DNS.StaleHostResolver." name, time)
18
19 namespace net {
20
21 namespace {
22
23 // Used in histograms; do not modify existing values.
24 enum RequestOutcome {
25 // Served from (valid) cache, hosts file, IP literal, etc.
26 SYNCHRONOUS = 0,
27
28 // Network responded; there was no usable stale data.
29 NETWORK_WITHOUT_STALE = 1,
30
31 // Network responded before stale delay; there was usable stale data.
32 NETWORK_WITH_STALE = 2,
33
34 // Stale data returned; network didn't respond before the stale delay.
35 STALE_BEFORE_NETWORK = 3,
36
37 // Request canceled; there was no usable stale data.
38 CANCELED_WITHOUT_STALE = 4,
39
40 // Request canceled; there was usable stale data.
41 CANCELED_WITH_STALE = 5,
42
43 MAX_REQUEST_OUTCOME
44 };
45
46 void HistogramRequestOutcome(RequestOutcome outcome) {
47 STALE_HISTOGRAM_ENUM("RequestOutcome", outcome, MAX_REQUEST_OUTCOME);
48 }
49
50 void HistogramAddressListDelta(AddressListDeltaType delta) {
51 STALE_HISTOGRAM_ENUM("StaleAddressListDelta", delta, MAX_DELTA_TYPE);
52 }
53
54 void HistogramTimeDelta(base::TimeTicks network_time,
55 base::TimeTicks stale_time) {
56 if (network_time < stale_time)
57 STALE_HISTOGRAM_TIME("NetworkEarly", stale_time - network_time);
58 else
59 STALE_HISTOGRAM_TIME("NetworkLate", network_time - stale_time);
60 }
61
62 } // namespace
63
64 // A request made by the StaleHostResolver. May return fresh cached data,
65 // network data, or stale cached data.
66 class StaleHostResolver::Request {
67 public:
68 Request();
69
70 // A callback for the caller to decide whether a stale entry is usable or not.
71 typedef base::Callback<bool(const HostCache::EntryStaleness&)>
72 StaleEntryUsableCallback;
73
74 // Starts the request. May call |usable_callback| inline if |resolver| returns
75 // stale data to let the caller decide whether the data is usable.
76 int Start(HostResolver* resolver,
77 const RequestInfo& info,
78 RequestPriority priority,
79 AddressList* addresses,
80 const CompletionCallback& callback,
81 const BoundNetLog& net_log,
82 const StaleEntryUsableCallback& usable_callback,
83 base::TimeDelta stale_delay);
84
85 // Cancels the request. |resolver| must be the same resolver passed to
86 // |Start()|. Does not call the callback passed to |Start()|.
87 //
88 // |Start()| must have been called and returned ERR_IO_PENDING; the request
89 // must not have been canceled already.
90 void Cancel(HostResolver* resolver);
91
92 bool has_network_request() const { return !!network_handle_; }
93 bool returned_stale_result() const { return callback_.is_null(); }
94
95 private:
96 ~Request();
97
98 // Callback for the timer to return stale data.
99 void OnStaleDelayElapsed();
100
101 // Callback for the underlying network request.
102 void OnNetworkRequestComplete(int error);
103
104 // Populates |addresses_| from |addresses| if and only if rv is OK, clears
105 // |addresses_| to make sure the request doesn't return twice, and then
106 // returns |rv|.
107 int HandleResult(int rv, const AddressList& addresses);
108
109 void HistogramSynchronousRequest();
110 void HistogramNetworkRequest(int error);
111 void HistogramCanceledRequest();
112
113 AddressList* addresses_;
114 CompletionCallback callback_;
115
116 int stale_error_;
117 AddressList stale_addresses_;
118 base::OneShotTimer stale_timer_;
119
120 AddressList network_addresses_;
121 HostResolver::RequestHandle network_handle_;
122 };
123
124 StaleHostResolver::Request::Request()
125 : addresses_(nullptr), network_handle_(nullptr) {}
126
127 int StaleHostResolver::Request::Start(
128 HostResolver* resolver,
129 const RequestInfo& info,
130 RequestPriority priority,
131 AddressList* addresses,
132 const CompletionCallback& callback,
133 const BoundNetLog& net_log,
134 const StaleEntryUsableCallback& usable_callback,
135 base::TimeDelta stale_delay) {
136 DCHECK(!callback.is_null());
137 DCHECK(!usable_callback.is_null());
138
139 callback_ = callback;
140 addresses_ = addresses;
141
142 CompletionCallback network_callback =
143 base::Bind(&StaleHostResolver::Request::OnNetworkRequestComplete,
144 base::Unretained(this));
145 base::Callback<void()> stale_callback = base::Bind(
146 &StaleHostResolver::Request::OnStaleDelayElapsed, base::Unretained(this));
147
148 HostCache::EntryStaleness stale_info;
149 int rv = resolver->ResolveStale(
150 info, priority, &network_addresses_, network_callback, &network_handle_,
151 &stale_error_, &stale_addresses_, &stale_info, net_log);
152 if (rv != ERR_IO_PENDING) {
153 DCHECK(!network_handle_);
154 rv = HandleResult(rv, network_addresses_);
155 HistogramSynchronousRequest();
156 delete this;
157 return rv;
158 }
159
160 if (stale_error_ != ERR_DNS_CACHE_MISS && usable_callback.Run(stale_info))
161 stale_timer_.Start(FROM_HERE, stale_delay, stale_callback);
162 else
163 stale_addresses_.clear();
164
165 return ERR_IO_PENDING;
166 }
167
168 void StaleHostResolver::Request::Cancel(HostResolver* resolver) {
169 DCHECK(has_network_request());
170 DCHECK(!returned_stale_result());
171
172 resolver->CancelRequest(network_handle_);
173 network_handle_ = nullptr;
174
175 HistogramCanceledRequest();
176 delete this;
177 }
178
179 StaleHostResolver::Request::~Request() {
180 DCHECK(!has_network_request());
181 }
182
183 void StaleHostResolver::Request::OnStaleDelayElapsed() {
184 DCHECK(has_network_request());
185 DCHECK(!returned_stale_result());
186
187 callback_.Run(HandleResult(stale_error_, stale_addresses_));
188 callback_.Reset();
Ryan Sleevi 2016/04/29 23:04:14 fwiw, you could use base::ResetAndReturn(&callbac
Julia Tuttle 2016/05/03 20:47:26 Awesome, thanks.
189
190 // Don't delete |this|; let the underlying request continue to backfill the
191 // host cache.
192 }
193
194 void StaleHostResolver::Request::OnNetworkRequestComplete(int error) {
195 DCHECK(has_network_request());
196
197 network_handle_ = nullptr;
198
199 if (!returned_stale_result())
200 callback_.Run(HandleResult(error, network_addresses_));
201
202 HistogramNetworkRequest(error);
203 delete this;
204 }
205
206 int StaleHostResolver::Request::HandleResult(int rv,
207 const AddressList& addresses) {
208 DCHECK(addresses_);
209
210 if (rv == OK)
211 *addresses_ = addresses;
212 addresses_ = nullptr;
213 return rv;
214 }
215
216 void StaleHostResolver::Request::HistogramSynchronousRequest() {
217 HistogramRequestOutcome(SYNCHRONOUS);
218 }
219
220 void StaleHostResolver::Request::HistogramNetworkRequest(int error) {
221 if (stale_timer_.IsRunning() || returned_stale_result())
222 HistogramTimeDelta(base::TimeTicks::Now(), stale_timer_.desired_run_time());
223
224 if (returned_stale_result() && stale_error_ == OK && error == OK) {
225 HistogramAddressListDelta(
226 FindAddressListDeltaType(stale_addresses_, network_addresses_));
227 }
228
229 if (returned_stale_result())
230 HistogramRequestOutcome(STALE_BEFORE_NETWORK);
231 else if (stale_timer_.IsRunning())
232 HistogramRequestOutcome(NETWORK_WITH_STALE);
233 else
234 HistogramRequestOutcome(NETWORK_WITHOUT_STALE);
235 }
236
237 void StaleHostResolver::Request::HistogramCanceledRequest() {
238 if (stale_timer_.IsRunning())
239 HistogramRequestOutcome(CANCELED_WITH_STALE);
240 else
241 HistogramRequestOutcome(CANCELED_WITHOUT_STALE);
242 }
243
244 namespace {
245
246 bool StaleEntryIsUsable(const StaleHostResolver::StaleOptions& options,
247 const HostCache::EntryStaleness& entry) {
248 if (options.max_expired_time != base::TimeDelta() &&
249 entry.expired_by > options.max_expired_time) {
250 return false;
251 }
252 if (options.max_stale_uses > 0 && entry.stale_hits > options.max_stale_uses) {
253 return false;
254 }
Ryan Sleevi 2016/04/29 23:04:14 consistency: no braces for single-line
Julia Tuttle 2016/05/03 20:47:26 Done.
255 if (!options.allow_other_network && entry.network_changes > 0)
256 return false;
257 return true;
258 }
259
260 } // namespace
261
262 StaleHostResolver::StaleHostResolver(
263 std::unique_ptr<HostResolver> inner_resolver,
264 const StaleOptions& stale_options)
265 : resolver_(std::move(inner_resolver)), options_(stale_options) {
266 DCHECK_GE(0, stale_options.max_expired_time.InMicroseconds());
267 DCHECK_GE(0, stale_options.max_stale_uses);
268 }
269
270 StaleHostResolver::~StaleHostResolver() {
271 for (auto* request : pending_requests_)
272 request->Cancel(resolver_.get());
273 pending_requests_.clear();
274 }
275
276 int StaleHostResolver::Resolve(const RequestInfo& info,
277 RequestPriority priority,
278 AddressList* addresses,
279 const CompletionCallback& callback,
280 RequestHandle* out_req,
281 const BoundNetLog& net_log) {
282 StaleHostResolver::Request::StaleEntryUsableCallback usable_callback =
283 base::Bind(&StaleEntryIsUsable, options_);
284
285 Request* request = new Request();
286 pending_requests_.insert(request);
287 CompletionCallback wrapped_callback =
288 base::Bind(&StaleHostResolver::OnRequestComplete, base::Unretained(this),
289 request, callback);
290
291 int rv = request->Start(resolver_.get(), info, priority, addresses,
292 wrapped_callback, net_log, usable_callback,
293 options_.delay);
294 if (rv == ERR_IO_PENDING && out_req)
295 *out_req = reinterpret_cast<RequestHandle>(request);
Ryan Sleevi 2016/04/29 23:04:14 What if rv == ERR_IO_PENDING and there is no |*out
Julia Tuttle 2016/05/03 20:47:26 It doesn't leak -- it just means the caller can't
296 return rv;
297 }
298
299 void StaleHostResolver::CancelRequest(RequestHandle req_handle) {
300 Request* request = reinterpret_cast<Request*>(req_handle);
301 DCHECK(request);
302 DCHECK_EQ(1u, pending_requests_.count(request));
303
304 request->Cancel(resolver_.get());
305 pending_requests_.erase(request);
306 }
307
308 int StaleHostResolver::ResolveFromCache(const RequestInfo& info,
309 AddressList* addresses,
310 const BoundNetLog& net_log) {
311 return resolver_->ResolveFromCache(info, addresses, net_log);
312 }
313
314 int StaleHostResolver::ResolveStaleFromCache(
315 const RequestInfo& info,
316 AddressList* addresses,
317 HostCache::EntryStaleness* stale_info,
318 const BoundNetLog& net_log) {
319 return resolver_->ResolveStaleFromCache(info, addresses, stale_info, net_log);
320 }
321
322 void StaleHostResolver::SetDnsClientEnabled(bool enabled) {
323 resolver_->SetDnsClientEnabled(enabled);
324 }
325
326 HostCache* StaleHostResolver::GetHostCache() {
327 return resolver_->GetHostCache();
328 }
329
330 std::unique_ptr<base::Value> StaleHostResolver::GetDnsConfigAsValue() const {
331 return resolver_->GetDnsConfigAsValue();
332 }
333
334 void StaleHostResolver::OnRequestComplete(
335 StaleHostResolver::Request* request,
336 const CompletionCallback& outer_callback,
337 int error) {
338 DCHECK(request);
339 DCHECK_NE(ERR_IO_PENDING, error);
340
341 DCHECK_EQ(1u, pending_requests_.count(request));
342 pending_requests_.erase(request);
343
344 outer_callback.Run(error);
345 }
346
347 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/stale_host_resolver.h ('k') | net/net.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698