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

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: Tweak histograms per asvitkine's suggestions on another CL. 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/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 {
Randy Smith (Not in Mondays) 2016/04/28 17:48:25 nit, suggestion (I'll stop making these once you a
Julia Tuttle 2016/04/29 18:04:29 Happily done, as I still get my 80 characters to w
25 // Served from (valid) cache, hosts file, IP literal, etc.
26 SYNCHRONOUS = 0,
27 // Network responded; there was no usable stale data.
28 NETWORK_WITHOUT_STALE = 1,
29 // Network responded before stale delay; there was usable stale data.
30 NETWORK_WITH_STALE = 2,
31 // Stale data returned; network didn't respond before the stale delay.
32 STALE_BEFORE_NETWORK = 3,
33 // Request canceled; there was no usable stale data.
34 CANCELED_WITHOUT_STALE = 4,
35 // Request canceled; there was usable stale data.
36 CANCELED_WITH_STALE = 5,
37 MAX_REQUEST_OUTCOME
38 };
39
40 void HistogramRequestOutcome(RequestOutcome outcome) {
41 STALE_HISTOGRAM_ENUM("RequestOutcome", outcome, MAX_REQUEST_OUTCOME);
42 }
43
44 void HistogramAddressListDelta(AddressListDeltaType delta) {
Randy Smith (Not in Mondays) 2016/04/28 17:48:25 Ah. Feel free to ignore my comment on the other C
Julia Tuttle 2016/04/29 18:04:29 Done.
45 STALE_HISTOGRAM_ENUM("StaleAddressListDelta", delta, MAX_DELTA_TYPE);
46 }
47
48 void HistogramTimeDelta(base::TimeTicks network_time,
49 base::TimeTicks stale_time) {
50 if (network_time < stale_time)
51 STALE_HISTOGRAM_TIME("NetworkEarly", stale_time - network_time);
52 else
53 STALE_HISTOGRAM_TIME("NetworkLate", network_time - stale_time);
54 }
55
56 } // namespace
57
58 // A request made by the StaleHostResolver. May return fresh cached data,
59 // network data, or stale cached data.
60 class StaleHostResolver::Request {
61 public:
62 Request();
63
64 // A callback for the caller to decide whether a stale entry is usable or not.
65 typedef base::Callback<bool(const HostCache::StaleEntryInfo&)>
66 StaleEntryUsableCallback;
67
68 // Starts the request. May call |usable_callback| inline if |resolver| returns
Randy Smith (Not in Mondays) 2016/04/28 17:48:25 I'm scared about interfaces that are variations (e
Julia Tuttle 2016/04/29 18:04:29 |usable_callback| isn't a completion callback; it'
69 // stale data. May call the callback passed into the constructor inline if
Randy Smith (Not in Mondays) 2016/04/28 17:48:25 What callback passed into the constructor?
Julia Tuttle 2016/04/29 18:04:29 Done.
70 // |resolver| returns valid data synchronously.
71 int Start(HostResolver* resolver,
72 const RequestInfo& info,
73 RequestPriority priority,
74 AddressList* addresses,
75 const CompletionCallback& callback,
76 const BoundNetLog& net_log,
77 const StaleEntryUsableCallback& usable_callback,
Randy Smith (Not in Mondays) 2016/04/28 17:48:25 I'm having a hard time mapping the implementation
Julia Tuttle 2016/04/29 18:04:29 Done.
78 base::TimeDelta stale_delay);
79
80 // Cancels the request. |resolver| must be the same resolver passed to
81 // |Start()|. Does not call the callback passed t othe constructor.
82 void Cancel(HostResolver* resolver);
83
84 // Callback for the timer to return stale data.
85 void OnStaleDelayElapsed();
Ryan Sleevi 2016/04/29 01:04:09 Pedantry: Seems like it could be private?
Julia Tuttle 2016/04/29 18:04:29 Done.
86
87 // Callback for the underlying network request.
88 void OnNetworkRequestComplete(int error);
Ryan Sleevi 2016/04/29 01:04:09 Pedantry: Seems like it could be private?
Julia Tuttle 2016/04/29 18:04:29 Done.
89
90 bool has_network_request() const { return !!network_handle_; }
91 bool returned_stale_result() const { return callback_.is_null(); }
92
93 private:
94 ~Request();
95
96 // Populates |addresses_| from |addresses| if and only if rv is OK, clears
97 // |addresses_| to make sure the request doesn't return twice, and then
98 // returns |rv|.
99 int HandleResult(int rv, const AddressList& addresses);
100
101 void HistogramSynchronousRequest();
102 void HistogramNetworkRequest(int error);
103 void HistogramCanceledRequest();
104
105 AddressList* addresses_;
106 CompletionCallback callback_;
107
108 int stale_error_;
109 AddressList stale_addresses_;
110 base::OneShotTimer stale_timer_;
111
112 AddressList network_addresses_;
113 HostResolver::RequestHandle network_handle_;
114 };
115
116 StaleHostResolver::Request::Request()
117 : addresses_(nullptr), network_handle_(nullptr) {}
118
119 StaleHostResolver::Request::~Request() {
120 DCHECK(!has_network_request());
121 }
122
123 int StaleHostResolver::Request::Start(
124 HostResolver* resolver,
125 const RequestInfo& info,
126 RequestPriority priority,
127 AddressList* addresses,
128 const CompletionCallback& callback,
129 const BoundNetLog& net_log,
130 const StaleEntryUsableCallback& usable_callback,
131 base::TimeDelta stale_delay) {
132 DCHECK(!callback.is_null());
133 DCHECK(!usable_callback.is_null());
134
135 callback_ = callback;
136 addresses_ = addresses;
137
138 CompletionCallback network_callback =
139 base::Bind(&StaleHostResolver::Request::OnNetworkRequestComplete,
140 base::Unretained(this));
141 base::Callback<void()> stale_callback = base::Bind(
142 &StaleHostResolver::Request::OnStaleDelayElapsed, base::Unretained(this));
143
144 HostCache::StaleEntryInfo stale_info;
145 int rv = resolver->ResolveStale(
146 info, priority, &network_addresses_, network_callback, &network_handle_,
147 &stale_error_, &stale_addresses_, &stale_info, net_log);
148 if (rv != ERR_IO_PENDING) {
149 DCHECK(!network_handle_);
150 rv = HandleResult(rv, network_addresses_);
151 HistogramSynchronousRequest();
152 delete this;
153 return rv;
154 }
155
156 if (stale_error_ != ERR_DNS_CACHE_MISS && usable_callback.Run(stale_info))
157 stale_timer_.Start(FROM_HERE, stale_delay, stale_callback);
158 else
159 stale_addresses_.clear();
160
161 return ERR_IO_PENDING;
162 }
163
164 void StaleHostResolver::Request::Cancel(HostResolver* resolver) {
165 DCHECK(has_network_request());
166 DCHECK(!returned_stale_result());
167
168 resolver->CancelRequest(network_handle_);
169 network_handle_ = nullptr;
170
171 HistogramCanceledRequest();
172 delete this;
173 }
174
175 void StaleHostResolver::Request::OnStaleDelayElapsed() {
176 DCHECK(has_network_request());
177 DCHECK(!returned_stale_result());
178
179 callback_.Run(HandleResult(stale_error_, stale_addresses_));
180 callback_.Reset();
Ryan Sleevi 2016/04/29 01:04:08 Maybe add a note as to why you don't delete this
Julia Tuttle 2016/04/29 18:04:29 Done.
181 }
182
183 void StaleHostResolver::Request::OnNetworkRequestComplete(int error) {
184 DCHECK(has_network_request());
185
186 network_handle_ = nullptr;
187
188 if (!returned_stale_result())
189 callback_.Run(HandleResult(error, network_addresses_));
190
191 HistogramNetworkRequest(error);
192 delete this;
193 }
194
195 int StaleHostResolver::Request::HandleResult(int rv,
196 const AddressList& addresses) {
197 DCHECK(addresses_);
198
199 if (rv == OK)
200 *addresses_ = addresses;
201 addresses_ = nullptr;
202 return rv;
203 }
204
205 void StaleHostResolver::Request::HistogramSynchronousRequest() {
206 HistogramRequestOutcome(SYNCHRONOUS);
207 }
208
209 void StaleHostResolver::Request::HistogramNetworkRequest(int error) {
210 if (stale_timer_.IsRunning() || returned_stale_result()) {
Ryan Sleevi 2016/04/29 01:04:09 nit: no braces for consistency with the rest of th
Julia Tuttle 2016/04/29 18:04:29 Done.
211 HistogramTimeDelta(base::TimeTicks::Now(), stale_timer_.desired_run_time());
212 }
213
214 if (returned_stale_result() && stale_error_ == OK && error == OK) {
215 HistogramAddressListDelta(
216 FindAddressListDeltaType(stale_addresses_, network_addresses_));
217 }
218
219 if (returned_stale_result())
220 HistogramRequestOutcome(STALE_BEFORE_NETWORK);
221 else if (stale_timer_.IsRunning())
222 HistogramRequestOutcome(NETWORK_WITH_STALE);
223 else
224 HistogramRequestOutcome(NETWORK_WITHOUT_STALE);
225 }
226
227 void StaleHostResolver::Request::HistogramCanceledRequest() {
228 if (stale_timer_.IsRunning())
229 HistogramRequestOutcome(CANCELED_WITH_STALE);
230 else
231 HistogramRequestOutcome(CANCELED_WITHOUT_STALE);
232 }
233
234 namespace {
235
236 bool StaleEntryIsUsable(const StaleHostResolver::StaleOptions& options,
237 const HostCache::StaleEntryInfo& entry) {
238 if (options.max_expired_time != base::TimeDelta() &&
239 entry.expired_by > options.max_expired_time) {
240 return false;
241 }
242 if (options.max_stale_uses > 0u &&
243 entry.stale_hits > options.max_stale_uses) {
244 return false;
245 }
246 if (!options.allow_other_network && entry.network_changes > 0u)
247 return false;
248 return true;
249 }
250
251 } // namespace
252
253 StaleHostResolver::StaleHostResolver(
254 std::unique_ptr<HostResolver> inner_resolver,
255 const StaleOptions& stale_options)
256 : resolver_(std::move(inner_resolver)), options_(stale_options) {}
257
258 StaleHostResolver::~StaleHostResolver() {
259 for (auto request : pending_requests_)
Ryan Sleevi 2016/04/29 01:04:09 Shouldn't this be "auto&" or "auto*" (based on htt
Julia Tuttle 2016/04/29 18:04:29 Done.
260 request->Cancel(resolver_.get());
261 pending_requests_.clear();
262 }
263
264 int StaleHostResolver::Resolve(const RequestInfo& info,
265 RequestPriority priority,
266 AddressList* addresses,
267 const CompletionCallback& callback,
268 RequestHandle* out_req,
269 const BoundNetLog& net_log) {
270 StaleHostResolver::Request::StaleEntryUsableCallback usable_callback =
271 base::Bind(&StaleEntryIsUsable, options_);
272
273 Request* request = new Request();
274 pending_requests_.insert(request);
275 CompletionCallback wrapped_callback =
276 base::Bind(&StaleHostResolver::OnRequestComplete, base::Unretained(this),
277 request, callback);
278
279 int rv = request->Start(resolver_.get(), info, priority, addresses,
280 wrapped_callback, net_log, usable_callback,
281 options_.delay);
282 if (rv == ERR_IO_PENDING && out_req)
283 *out_req = reinterpret_cast<RequestHandle>(request);
284 return rv;
285 }
286
287 void StaleHostResolver::CancelRequest(RequestHandle req_handle) {
288 Request* request = reinterpret_cast<Request*>(req_handle);
289 DCHECK(request);
290 DCHECK_EQ(1u, pending_requests_.count(request));
291
292 request->Cancel(resolver_.get());
293 pending_requests_.erase(request);
294 }
295
296 int StaleHostResolver::ResolveFromCache(const RequestInfo& info,
297 AddressList* addresses,
298 const BoundNetLog& net_log) {
299 return resolver_->ResolveFromCache(info, addresses, net_log);
300 }
301
302 int StaleHostResolver::ResolveStaleFromCache(
303 const RequestInfo& info,
304 AddressList* addresses,
305 HostCache::StaleEntryInfo* stale_info,
306 const BoundNetLog& net_log) {
307 return resolver_->ResolveStaleFromCache(info, addresses, stale_info, net_log);
308 }
309
310 void StaleHostResolver::SetDnsClientEnabled(bool enabled) {
311 resolver_->SetDnsClientEnabled(enabled);
312 }
313
314 HostCache* StaleHostResolver::GetHostCache() {
315 return resolver_->GetHostCache();
316 }
317
318 std::unique_ptr<base::Value> StaleHostResolver::GetDnsConfigAsValue() const {
319 return resolver_->GetDnsConfigAsValue();
320 }
321
322 void StaleHostResolver::OnRequestComplete(
323 StaleHostResolver::Request* request,
324 const CompletionCallback& outer_callback,
325 int error) {
326 DCHECK(request);
327 DCHECK_NE(ERR_IO_PENDING, error);
328
329 DCHECK_EQ(1u, pending_requests_.count(request));
330 pending_requests_.erase(request);
331
332 outer_callback.Run(error);
333 }
334
335 } // 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