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

Side by Side Diff: net/base/async_host_resolver.cc

Issue 7466031: AsyncHostResolver: integrated HostCache, temporarily, until we have RR cache. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed comment. Created 9 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/base/async_host_resolver.h" 5 #include "net/base/async_host_resolver.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 dict->Set("source_dependency", source_.ToValue()); 59 dict->Set("source_dependency", source_.ToValue());
60 60
61 return dict; 61 return dict;
62 } 62 }
63 63
64 private: 64 private:
65 const HostResolver::RequestInfo info_; 65 const HostResolver::RequestInfo info_;
66 const NetLog::Source source_; 66 const NetLog::Source source_;
67 }; 67 };
68 68
69 HostCache* CreateDefaultCache() {
cbentzel 2011/07/21 15:31:10 This should be shared with the one in host_resolve
agayev 2011/07/21 17:48:03 Done.
70 static const size_t kMaxHostCacheEntries = 100;
71
72 HostCache* cache = new HostCache(
73 kMaxHostCacheEntries,
74 base::TimeDelta::FromMinutes(1),
75 base::TimeDelta::FromSeconds(0)); // Disable caching of failed DNS.
76
77 return cache;
78 }
79
69 } // namespace 80 } // namespace
70 81
71 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, 82 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves,
72 const IPAddressNumber& dns_ip, 83 const IPAddressNumber& dns_ip,
73 NetLog* net_log) { 84 NetLog* net_log) {
74 size_t max_transactions = max_concurrent_resolves; 85 size_t max_transactions = max_concurrent_resolves;
75 if (max_transactions == 0) 86 if (max_transactions == 0)
76 max_transactions = 20; 87 max_transactions = 20;
77 size_t max_pending_requests = max_transactions * 100; 88 size_t max_pending_requests = max_transactions * 100;
78 HostResolver* resolver = new AsyncHostResolver( 89 HostResolver* resolver = new AsyncHostResolver(
79 IPEndPoint(dns_ip, 53), 90 IPEndPoint(dns_ip, 53),
80 max_transactions, 91 max_transactions,
81 max_pending_requests, 92 max_pending_requests,
82 base::Bind(&base::RandInt), 93 base::Bind(&base::RandInt),
94 CreateDefaultCache(),
83 NULL, 95 NULL,
84 net_log); 96 net_log);
85 return resolver; 97 return resolver;
86 } 98 }
87 99
88 //----------------------------------------------------------------------------- 100 //-----------------------------------------------------------------------------
89 class AsyncHostResolver::Request { 101 class AsyncHostResolver::Request {
90 public: 102 public:
91 Request(const BoundNetLog& source_net_log, 103 Request(const BoundNetLog& source_net_log,
92 const BoundNetLog& request_net_log, 104 const BoundNetLog& request_net_log,
(...skipping 11 matching lines...) Expand all
104 addresses_(addresses) { 116 addresses_(addresses) {
105 DCHECK(addresses_); 117 DCHECK(addresses_);
106 } 118 }
107 119
108 int id() const { return id_; } 120 int id() const { return id_; }
109 const HostResolver::RequestInfo& info() const { return info_; } 121 const HostResolver::RequestInfo& info() const { return info_; }
110 const Key& key() const { return key_; } 122 const Key& key() const { return key_; }
111 RequestPriority priority() const { return info_.priority(); } 123 RequestPriority priority() const { return info_.priority(); }
112 const BoundNetLog& source_net_log() const { return source_net_log_; } 124 const BoundNetLog& source_net_log() const { return source_net_log_; }
113 const BoundNetLog& request_net_log() const { return request_net_log_; } 125 const BoundNetLog& request_net_log() const { return request_net_log_; }
114 const AddressList* addresses() const { return addresses_; } 126 void set_addresses(const AddressList& addresses) { *addresses_ = addresses; }
115 127
116 void OnComplete(int result, const IPAddressList& ip_addresses) { 128 void OnComplete(int result, const IPAddressList& ip_addresses) {
117 DCHECK(callback_); 129 DCHECK(callback_);
118 if (result == OK) 130 if (result == OK)
119 *addresses_ = 131 *addresses_ =
120 AddressList::CreateFromIPAddressList(ip_addresses, info_.port()); 132 AddressList::CreateFromIPAddressList(ip_addresses, info_.port());
121 callback_->Run(result); 133 callback_->Run(result);
122 } 134 }
123 135
124 private: 136 private:
125 BoundNetLog source_net_log_; 137 BoundNetLog source_net_log_;
126 BoundNetLog request_net_log_; 138 BoundNetLog request_net_log_;
127 const int id_; 139 const int id_;
128 const HostResolver::RequestInfo info_; 140 const HostResolver::RequestInfo info_;
129 const Key key_; 141 const Key key_;
130 CompletionCallback* callback_; 142 CompletionCallback* callback_;
131 AddressList* addresses_; 143 AddressList* addresses_;
132 }; 144 };
133 145
134 //----------------------------------------------------------------------------- 146 //-----------------------------------------------------------------------------
135 AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server, 147 AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server,
136 size_t max_transactions, 148 size_t max_transactions,
137 size_t max_pending_requests, 149 size_t max_pending_requests,
138 const RandIntCallback& rand_int_cb, 150 const RandIntCallback& rand_int_cb,
151 HostCache* cache,
139 ClientSocketFactory* factory, 152 ClientSocketFactory* factory,
140 NetLog* net_log) 153 NetLog* net_log)
141 : max_transactions_(max_transactions), 154 : max_transactions_(max_transactions),
142 max_pending_requests_(max_pending_requests), 155 max_pending_requests_(max_pending_requests),
143 dns_server_(dns_server), 156 dns_server_(dns_server),
144 rand_int_cb_(rand_int_cb), 157 rand_int_cb_(rand_int_cb),
158 cache_(cache),
145 factory_(factory), 159 factory_(factory),
146 next_request_id_(0), 160 next_request_id_(0),
147 net_log_(net_log) { 161 net_log_(net_log) {
148 } 162 }
149 163
150 AsyncHostResolver::~AsyncHostResolver() { 164 AsyncHostResolver::~AsyncHostResolver() {
165 // Destroy request lists.
151 for (KeyRequestListMap::iterator it = requestlist_map_.begin(); 166 for (KeyRequestListMap::iterator it = requestlist_map_.begin();
152 it != requestlist_map_.end(); ++it) 167 it != requestlist_map_.end(); ++it)
153 STLDeleteElements(&it->second); 168 STLDeleteElements(&it->second);
169
170 // Destroy transactions.
154 STLDeleteElements(&transactions_); 171 STLDeleteElements(&transactions_);
172
173 // Destroy pending requests.
174 for (size_t i = 0; i < arraysize(pending_requests_); ++i)
175 STLDeleteElements(&pending_requests_[i]);
155 } 176 }
156 177
157 int AsyncHostResolver::Resolve(const RequestInfo& info, 178 int AsyncHostResolver::Resolve(const RequestInfo& info,
158 AddressList* addresses, 179 AddressList* addresses,
159 CompletionCallback* callback, 180 CompletionCallback* callback,
160 RequestHandle* out_req, 181 RequestHandle* out_req,
161 const BoundNetLog& source_net_log) { 182 const BoundNetLog& source_net_log) {
162 DCHECK(addresses); 183 DCHECK(addresses);
163
164 IPAddressNumber ip_number; 184 IPAddressNumber ip_number;
165 std::string dns_name; 185 std::string dns_name;
166 int rv = ERR_UNEXPECTED; 186 int rv = ERR_UNEXPECTED;
167 if (info.hostname().empty()) 187 if (info.hostname().empty())
168 rv = ERR_NAME_NOT_RESOLVED; 188 rv = ERR_NAME_NOT_RESOLVED;
169 else if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) 189 else if (ParseIPLiteralToNumber(info.hostname(), &ip_number))
170 rv = ResolveAsIp(info, ip_number, addresses); 190 rv = ResolveAsIp(info, ip_number, addresses);
171 else if (!DNSDomainFromDot(info.hostname(), &dns_name)) 191 else if (!DNSDomainFromDot(info.hostname(), &dns_name))
172 rv = ERR_NAME_NOT_RESOLVED; 192 rv = ERR_NAME_NOT_RESOLVED;
173 else if (info.only_use_cached_response()) // TODO(agayev): support caching
174 rv = ERR_NAME_NOT_RESOLVED;
175 193
176 Request* request = CreateNewRequest( 194 Request* request = CreateNewRequest(
177 info, dns_name, callback, addresses, source_net_log); 195 info, dns_name, callback, addresses, source_net_log);
178 196
179 OnStart(request); 197 OnStart(request);
198 if (rv == ERR_UNEXPECTED) {
199 if (ServeFromCache(request))
200 rv = OK;
201 else if (info.only_use_cached_response())
202 rv = ERR_NAME_NOT_RESOLVED;
203 }
204
180 if (rv != ERR_UNEXPECTED) { 205 if (rv != ERR_UNEXPECTED) {
181 OnFinish(request, rv); 206 OnFinish(request, rv);
182 delete request; 207 delete request;
183 return rv; 208 return rv; // Synchronous resolution ends here.
184 } 209 }
185 210
186 if (out_req) 211 if (out_req)
187 *out_req = reinterpret_cast<RequestHandle>(request); 212 *out_req = reinterpret_cast<RequestHandle>(request);
188
189 if (AttachToRequestList(request)) 213 if (AttachToRequestList(request))
190 return ERR_IO_PENDING; 214 return ERR_IO_PENDING;
191 if (transactions_.size() < max_transactions_) 215 if (transactions_.size() < max_transactions_)
192 return StartNewTransactionFor(request); 216 return StartNewTransactionFor(request);
193 return Enqueue(request); 217 return Enqueue(request);
194 } 218 }
195 219
196 void AsyncHostResolver::OnStart(Request* request) { 220 void AsyncHostResolver::OnStart(Request* request) {
197 DCHECK(request); 221 DCHECK(request);
198 222
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 } 296 }
273 297
274 HostResolverImpl* AsyncHostResolver::GetAsHostResolverImpl() { 298 HostResolverImpl* AsyncHostResolver::GetAsHostResolverImpl() {
275 return NULL; 299 return NULL;
276 } 300 }
277 301
278 void AsyncHostResolver::OnTransactionComplete( 302 void AsyncHostResolver::OnTransactionComplete(
279 int result, 303 int result,
280 const DnsTransaction* transaction, 304 const DnsTransaction* transaction,
281 const IPAddressList& ip_addresses) { 305 const IPAddressList& ip_addresses) {
282
283 DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction) 306 DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction)
284 != transactions_.end()); 307 != transactions_.end());
285 DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end()); 308 DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end());
286 309
287 // Run callback of every request that was depending on this transaction, 310 // Run callback of every request that was depending on this transaction,
288 // also notify observers. 311 // also notify observers.
289 RequestList& requests = requestlist_map_[transaction->key()]; 312 RequestList& requests = requestlist_map_[transaction->key()];
290 for (RequestList::iterator it = requests.begin(); it != requests.end(); 313 for (RequestList::iterator it = requests.begin(); it != requests.end();
291 ++it) { 314 ++it) {
292 Request* request = *it; 315 Request* request = *it;
293 OnFinish(request, result); 316 OnFinish(request, result);
294 request->OnComplete(result, ip_addresses); 317 request->OnComplete(result, ip_addresses);
295 } 318 }
296 319
320 // It is possible that the requests that caused |transaction| to be
321 // created are cancelled by the time |transaction| completes. In that
322 // case |requests| would be empty. We are knowingly throwing away the
323 // result of a DNS resolution in that case, because (a) if there are no
324 // requests, we do not have info to obtain a key from, (b) DnsTransaction
325 // does not have info(), adding one into it just temporarily doesn't make
326 // sense, since HostCache will be replaced with RR cache soon, (c)
327 // recreating info from DnsTransaction::Key adds a lot of temporary
cbentzel 2011/07/21 15:31:10 It seems like it should still be possible to cache
agayev 2011/07/21 17:48:03 Well, it doesn't have host_resolver_flags, whose u
cbentzel 2011/07/21 18:22:15 Yes, I agree that's how it would be done. I think
328 // code/functions (like converting back from qtype to AddressFamily.)
329 // Also, we only cache positive results. All of this will change when RR
330 // cache is added.
331 if (result == OK && cache_.get() && !requests.empty()) {
332 Request* request = requests.front();
333 HostResolver::RequestInfo info = request->info();
334 HostCache::Key key(
335 info.hostname(), info.address_family(), info.host_resolver_flags());
336 AddressList addrlist =
337 AddressList::CreateFromIPAddressList(ip_addresses, info.port());
338 cache_->Set(key, result, addrlist, base::TimeTicks::Now());
339 }
340
297 // Cleanup requests. 341 // Cleanup requests.
298 STLDeleteElements(&requests); 342 STLDeleteElements(&requests);
299 requestlist_map_.erase(transaction->key()); 343 requestlist_map_.erase(transaction->key());
300 344
301 // Cleanup transaction and start a new one if there are pending requests. 345 // Cleanup transaction and start a new one if there are pending requests.
302 delete transaction; 346 delete transaction;
303 transactions_.remove(transaction); 347 transactions_.remove(transaction);
304 ProcessPending(); 348 ProcessPending();
305 } 349 }
306 350
351 bool AsyncHostResolver::ServeFromCache(Request* request) const {
352 // Sanity check -- it shouldn't be the case that allow_cached_response is
353 // false while only_use_cached_response is true.
354 DCHECK(request->info().allow_cached_response() ||
355 !request->info().only_use_cached_response());
356
357 if (!cache_.get() || !request->info().allow_cached_response())
358 return false;
359
360 HostResolver::RequestInfo info = request->info();
361 HostCache::Key key(info.hostname(), info.address_family(),
362 info.host_resolver_flags());
363 const HostCache::Entry* cache_entry = cache_->Lookup(
364 key, base::TimeTicks::Now());
365 if (cache_entry) {
366 request->request_net_log().AddEvent(
367 NetLog::TYPE_ASYNC_HOST_RESOLVER_CACHE_HIT, NULL);
368 DCHECK_EQ(OK, cache_entry->error);
cbentzel 2011/07/21 15:31:10 Ah - I was going to ask you to handle non-OK error
369 request->set_addresses(
370 CreateAddressListUsingPort(cache_entry->addrlist, info.port()));
371 return true;
372 }
373 return false;
374 }
375
307 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( 376 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest(
308 const RequestInfo& info, 377 const RequestInfo& info,
309 const std::string& dns_name, 378 const std::string& dns_name,
310 CompletionCallback* callback, 379 CompletionCallback* callback,
311 AddressList* addresses, 380 AddressList* addresses,
312 const BoundNetLog& source_net_log) { 381 const BoundNetLog& source_net_log) {
313 382
314 uint16 query_type = QueryTypeFromAddressFamily(info.address_family()); 383 uint16 query_type = QueryTypeFromAddressFamily(info.address_family());
315 Key key(dns_name, query_type); 384 Key key(dns_name, query_type);
316 385
317 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 386 BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
318 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); 387 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST);
319 388
320 int id = next_request_id_++; 389 int id = next_request_id_++;
321 Request* request = new Request( 390 return new Request(
322 source_net_log, request_net_log, id, info, key, callback, addresses); 391 source_net_log, request_net_log, id, info, key, callback, addresses);
323 return request;
324 } 392 }
325 393
326 bool AsyncHostResolver::AttachToRequestList(Request* request) { 394 bool AsyncHostResolver::AttachToRequestList(Request* request) {
327 KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); 395 KeyRequestListMap::iterator it = requestlist_map_.find(request->key());
328 if (it == requestlist_map_.end()) 396 if (it == requestlist_map_.end())
329 return false; 397 return false;
330 it->second.push_back(request); 398 it->second.push_back(request);
331 return true; 399 return true;
332 } 400 }
333 401
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 AsyncHostResolver::Request* AsyncHostResolver::Insert(Request* request) { 434 AsyncHostResolver::Request* AsyncHostResolver::Insert(Request* request) {
367 pending_requests_[request->priority()].push_back(request); 435 pending_requests_[request->priority()].push_back(request);
368 if (GetNumPending() > max_pending_requests_) { 436 if (GetNumPending() > max_pending_requests_) {
369 Request* req = RemoveLowest(); 437 Request* req = RemoveLowest();
370 DCHECK(req); 438 DCHECK(req);
371 return req; 439 return req;
372 } 440 }
373 return NULL; 441 return NULL;
374 } 442 }
375 443
376 size_t AsyncHostResolver::GetNumPending() { 444 size_t AsyncHostResolver::GetNumPending() const {
377 size_t num_pending = 0; 445 size_t num_pending = 0;
378 for (size_t i = 0; i < arraysize(pending_requests_); ++i) 446 for (size_t i = 0; i < arraysize(pending_requests_); ++i)
379 num_pending += pending_requests_[i].size(); 447 num_pending += pending_requests_[i].size();
380 return num_pending; 448 return num_pending;
381 } 449 }
382 450
383 AsyncHostResolver::Request* AsyncHostResolver::RemoveLowest() { 451 AsyncHostResolver::Request* AsyncHostResolver::RemoveLowest() {
384 for (int i = static_cast<int>(arraysize(pending_requests_)) - 1; 452 for (int i = static_cast<int>(arraysize(pending_requests_)) - 1;
385 i >= 0; --i) { 453 i >= 0; --i) {
386 RequestList& requests = pending_requests_[i]; 454 RequestList& requests = pending_requests_[i];
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 it = requests.erase(it); 486 it = requests.erase(it);
419 } else { 487 } else {
420 ++it; 488 ++it;
421 } 489 }
422 } 490 }
423 } 491 }
424 StartNewTransactionFor(request); 492 StartNewTransactionFor(request);
425 } 493 }
426 494
427 } // namespace net 495 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698