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

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: Fix missing #include >.< 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
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/callback_helpers.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/timer/timer.h"
10 #include "base/values.h"
11 #include "net/base/net_errors.h"
12 #include "net/dns/dns_util.h"
13
14 #define STALE_HISTOGRAM_ENUM(name, value, max) \
15 UMA_HISTOGRAM_ENUMERATION("DNS.StaleHostResolver." name, value, max)
16
17 #define STALE_HISTOGRAM_TIME(name, time) \
18 UMA_HISTOGRAM_MEDIUM_TIMES("DNS.StaleHostResolver." name, time)
19
20 namespace net {
21
22 namespace {
23
24 // Used in histograms; do not modify existing values.
25 enum RequestOutcome {
26 // Served from (valid) cache, hosts file, IP literal, etc.
27 SYNCHRONOUS = 0,
28
29 // Network responded; there was no usable stale data.
30 NETWORK_WITHOUT_STALE = 1,
31
32 // Network responded before stale delay; there was usable stale data.
33 NETWORK_WITH_STALE = 2,
34
35 // Stale data returned; network didn't respond before the stale delay.
36 STALE_BEFORE_NETWORK = 3,
37
38 // Request canceled; there was no usable stale data.
39 CANCELED_WITHOUT_STALE = 4,
40
41 // Request canceled; there was usable stale data.
42 CANCELED_WITH_STALE = 5,
43
44 MAX_REQUEST_OUTCOME
45 };
46
47 void HistogramRequestOutcome(RequestOutcome outcome) {
48 STALE_HISTOGRAM_ENUM("RequestOutcome", outcome, MAX_REQUEST_OUTCOME);
49 }
50
51 void HistogramAddressListDelta(AddressListDeltaType delta) {
52 STALE_HISTOGRAM_ENUM("StaleAddressListDelta", delta, MAX_DELTA_TYPE);
53 }
54
55 void HistogramTimeDelta(base::TimeTicks network_time,
56 base::TimeTicks stale_time) {
57 if (network_time < stale_time)
58 STALE_HISTOGRAM_TIME("NetworkEarly", stale_time - network_time);
59 else
60 STALE_HISTOGRAM_TIME("NetworkLate", network_time - stale_time);
61 }
62
63 } // namespace
64
65 // A request made by the StaleHostResolver. May return fresh cached data,
66 // network data, or stale cached data.
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 Please document the ownership and lifetime model f
Julia Tuttle 2016/05/11 20:35:10 It is a little of both :) Request is self-owned,
67 class StaleHostResolver::Request {
68 public:
69 Request();
70
71 // A callback for the caller to decide whether a stale entry is usable or not.
72 typedef base::Callback<bool(const HostCache::EntryStaleness&)>
73 StaleEntryUsableCallback;
74
75 // Starts the request. May call |usable_callback| inline if |resolver| returns
76 // stale data to let the caller decide whether the data is usable.
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 I'm assuming that this is the standard "return OK+
Julia Tuttle 2016/05/11 20:35:10 Done.
77 int Start(HostResolver* resolver,
78 const RequestInfo& info,
79 RequestPriority priority,
80 AddressList* addresses,
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 nit: Could you document that the caller must guara
Julia Tuttle 2016/05/11 20:35:10 Done.
81 const CompletionCallback& callback,
82 const BoundNetLog& net_log,
83 const StaleEntryUsableCallback& usable_callback,
84 base::TimeDelta stale_delay);
85
86 // Cancels the request. |resolver| must be the same resolver passed to
87 // |Start()|. Does not call the callback passed to |Start()|.
88 //
89 // |Start()| must have been called and returned ERR_IO_PENDING; the request
90 // must not have been canceled already.
91 void Cancel(HostResolver* resolver);
92
93 bool has_network_request() const { return !!network_handle_; }
94 bool returned_stale_result() const { return callback_.is_null(); }
95
96 private:
97 ~Request();
98
99 // Callback for the timer to return stale data.
100 void OnStaleDelayElapsed();
101
102 // Callback for the underlying network request.
103 void OnNetworkRequestComplete(int error);
104
105 // Populates |addresses_| from |addresses| if and only if rv is OK, clears
106 // |addresses_| to make sure the request doesn't return twice, and then
107 // returns |rv|.
108 int HandleResult(int rv, const AddressList& addresses);
109
110 void HistogramSynchronousRequest();
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 nit, suggestion: Change these names to match the o
Julia Tuttle 2016/05/11 20:35:09 Done.
111 void HistogramNetworkRequest(int error);
112 void HistogramCanceledRequest();
113
114 AddressList* addresses_;
115 CompletionCallback callback_;
116
117 int stale_error_;
118 AddressList stale_addresses_;
119 base::OneShotTimer stale_timer_;
120
121 AddressList network_addresses_;
122 HostResolver::RequestHandle network_handle_;
123 };
124
125 StaleHostResolver::Request::Request()
126 : addresses_(nullptr), network_handle_(nullptr) {}
127
128 int StaleHostResolver::Request::Start(
129 HostResolver* resolver,
130 const RequestInfo& info,
131 RequestPriority priority,
132 AddressList* addresses,
133 const CompletionCallback& callback,
134 const BoundNetLog& net_log,
135 const StaleEntryUsableCallback& usable_callback,
136 base::TimeDelta stale_delay) {
137 DCHECK(!callback.is_null());
138 DCHECK(!usable_callback.is_null());
139
140 callback_ = callback;
141 addresses_ = addresses;
142
143 CompletionCallback network_callback =
144 base::Bind(&StaleHostResolver::Request::OnNetworkRequestComplete,
145 base::Unretained(this));
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 What guarantees that the Request will stick around
146 base::Callback<void()> stale_callback = base::Bind(
147 &StaleHostResolver::Request::OnStaleDelayElapsed, base::Unretained(this));
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 nit, suggestion: If you don't bother with a local
Julia Tuttle 2016/05/11 20:35:10 Done.
148
149 HostCache::EntryStaleness stale_info;
150 int rv = resolver->ResolveStale(
151 info, priority, &network_addresses_, network_callback, &network_handle_,
152 &stale_error_, &stale_addresses_, &stale_info, net_log);
153 if (rv != ERR_IO_PENDING) {
154 DCHECK(!network_handle_);
155 rv = HandleResult(rv, network_addresses_);
156 HistogramSynchronousRequest();
157 delete this;
158 return rv;
159 }
160
161 if (stale_error_ != ERR_DNS_CACHE_MISS && usable_callback.Run(stale_info))
162 stale_timer_.Start(FROM_HERE, stale_delay, stale_callback);
163 else
164 stale_addresses_.clear();
165
166 return ERR_IO_PENDING;
167 }
168
169 void StaleHostResolver::Request::Cancel(HostResolver* resolver) {
170 DCHECK(has_network_request());
171 DCHECK(!returned_stale_result());
172
173 resolver->CancelRequest(network_handle_);
174 network_handle_ = nullptr;
175
176 HistogramCanceledRequest();
177 delete this;
178 }
179
180 StaleHostResolver::Request::~Request() {
181 DCHECK(!has_network_request());
182 }
183
184 void StaleHostResolver::Request::OnStaleDelayElapsed() {
185 DCHECK(has_network_request());
186 DCHECK(!returned_stale_result());
187
188 base::ResetAndReturn(&callback_)
189 .Run(HandleResult(stale_error_, stale_addresses_));
190
191 // Don't delete |this|; let the underlying request continue to backfill the
192 // host cache.
193 }
194
195 void StaleHostResolver::Request::OnNetworkRequestComplete(int error) {
196 DCHECK(has_network_request());
197
198 network_handle_ = nullptr;
199
200 if (!returned_stale_result())
201 callback_.Run(HandleResult(error, network_addresses_));
202
203 HistogramNetworkRequest(error);
204 delete this;
205 }
206
207 int StaleHostResolver::Request::HandleResult(int rv,
208 const AddressList& addresses) {
209 DCHECK(addresses_);
210
211 if (rv == OK)
212 *addresses_ = addresses;
213 addresses_ = nullptr;
214 return rv;
215 }
216
217 void StaleHostResolver::Request::HistogramSynchronousRequest() {
218 HistogramRequestOutcome(SYNCHRONOUS);
219 }
220
221 void StaleHostResolver::Request::HistogramNetworkRequest(int error) {
222 if (stale_timer_.IsRunning() || returned_stale_result())
223 HistogramTimeDelta(base::TimeTicks::Now(), stale_timer_.desired_run_time());
224
225 if (returned_stale_result() && stale_error_ == OK && error == OK) {
226 HistogramAddressListDelta(
227 FindAddressListDeltaType(stale_addresses_, network_addresses_));
228 }
229
230 if (returned_stale_result())
231 HistogramRequestOutcome(STALE_BEFORE_NETWORK);
232 else if (stale_timer_.IsRunning())
233 HistogramRequestOutcome(NETWORK_WITH_STALE);
234 else
235 HistogramRequestOutcome(NETWORK_WITHOUT_STALE);
236 }
237
238 void StaleHostResolver::Request::HistogramCanceledRequest() {
239 if (stale_timer_.IsRunning())
240 HistogramRequestOutcome(CANCELED_WITH_STALE);
241 else
242 HistogramRequestOutcome(CANCELED_WITHOUT_STALE);
243 }
244
245 namespace {
246
247 bool StaleEntryIsUsable(const StaleHostResolver::StaleOptions& options,
248 const HostCache::EntryStaleness& entry) {
249 if (options.max_expired_time != base::TimeDelta() &&
250 entry.expired_by > options.max_expired_time) {
251 return false;
252 }
253 if (options.max_stale_uses > 0 && entry.stale_hits > options.max_stale_uses)
254 return false;
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);
296 return rv;
Randy Smith (Not in Mondays) 2016/05/04 21:00:28 Doesn't this leak request if request->Start() retu
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
« net/dns/stale_host_resolver.h ('K') | « 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