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

Side by Side Diff: net/http/http_cache.cc

Issue 455623003: stale-while-revalidate experimental implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 4 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
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/http/http_cache.h" 5 #include "net/http/http_cache.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 10
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 virtual QuicServerInfo* GetForServer( 285 virtual QuicServerInfo* GetForServer(
286 const QuicServerId& server_id) OVERRIDE { 286 const QuicServerId& server_id) OVERRIDE {
287 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_); 287 return new DiskCacheBasedQuicServerInfo(server_id, http_cache_);
288 } 288 }
289 289
290 private: 290 private:
291 HttpCache* const http_cache_; 291 HttpCache* const http_cache_;
292 }; 292 };
293 293
294 //----------------------------------------------------------------------------- 294 //-----------------------------------------------------------------------------
295
296 class HttpCache::AsyncValidation {
297 public:
298 AsyncValidation(const HttpRequestInfo& original_request, HttpCache* cache)
299 : request_(original_request), cache_(cache) {}
300 ~AsyncValidation() {}
301
302 void Start(const BoundNetLog& net_log);
303
304 private:
305 void OnStarted(int result);
306 void DoRead();
307 void OnRead(int result);
308
309 // Terminate this request with net error code |result|. Logs the transaction
310 // result and asks HttpCache to delete this object.
311 // If there was a client or server certificate error, it cannot be recovered
312 // asynchronously, so we need to prevent futures attempts to asynchronously
313 // fetch the resource. In this case, the cache entry is doomed.
314 void Terminate(int result);
315
316 HttpRequestInfo request_;
317 scoped_refptr<IOBuffer> buf_;
318 CompletionCallback read_callback_;
319 scoped_ptr<Transaction> transaction_;
320
321 // The HttpCache object owns this object. This object is always deleted before
322 // the pointer to the cache becomes invalid.
323 HttpCache* cache_;
324
325 DISALLOW_COPY_AND_ASSIGN(AsyncValidation);
326 };
327
328 void HttpCache::AsyncValidation::Start(const BoundNetLog& net_log) {
329 transaction_.reset(new Transaction(IDLE, cache_));
330 request_.load_flags |= LOAD_VALIDATE_CACHE;
331 // This use of base::Unretained is safe because |transaction_| is owned by
332 // this object.
333 read_callback_ = base::Bind(&AsyncValidation::OnRead, base::Unretained(this));
334 // This use of base::Unretained is safe as above.
335 int rv = transaction_->Start(
336 &request_,
337 base::Bind(&AsyncValidation::OnStarted, base::Unretained(this)),
338 net_log);
339
340 if (rv == ERR_IO_PENDING)
341 return;
342
343 OnStarted(rv);
344 }
345
346 void HttpCache::AsyncValidation::OnStarted(int result) {
347 if (result != OK) {
348 DVLOG(1) << "Asynchronous transaction start failed for " << request_.url;
349 Terminate(result);
350 return;
351 }
352
353 DoRead();
354 }
355
356 void HttpCache::AsyncValidation::DoRead() {
357 const size_t kBufSize = 4096;
358 if (!buf_)
359 buf_ = new IOBuffer(kBufSize);
360
361 int rv = 0;
362 while (rv > 0) {
yhirano 2014/08/26 07:52:01 dead code :)
Adam Rice 2014/08/26 13:38:41 Amazing! This doesn't seem to make any difference
363 rv = transaction_->Read(buf_.get(), kBufSize, read_callback_);
364 }
365
366 if (rv == ERR_IO_PENDING)
367 return;
368
369 OnRead(rv);
370 }
371
372 void HttpCache::AsyncValidation::OnRead(int result) {
373 if (result > 0) {
374 DoRead();
375 return;
376 }
377 Terminate(result);
378 }
379
380 void HttpCache::AsyncValidation::Terminate(int result) {
381 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED || IsCertificateError(result))
382 cache_->DoomEntry(transaction_->key(), transaction_.get());
383 transaction_->net_log().EndEventWithNetErrorCode(
384 NetLog::TYPE_ASYNC_REVALIDATION, result);
385 cache_->DeleteAsyncValidation(this);
386 // |this| is deleted.
387 }
388
389 //-----------------------------------------------------------------------------
295 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, 390 HttpCache::HttpCache(const net::HttpNetworkSession::Params& params,
296 BackendFactory* backend_factory) 391 BackendFactory* backend_factory)
297 : net_log_(params.net_log), 392 : net_log_(params.net_log),
298 backend_factory_(backend_factory), 393 backend_factory_(backend_factory),
299 building_backend_(false), 394 building_backend_(false),
300 bypass_lock_for_test_(false), 395 bypass_lock_for_test_(false),
396 use_stale_while_revalidate_(params.use_stale_while_revalidate),
301 mode_(NORMAL), 397 mode_(NORMAL),
302 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))), 398 network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))),
303 weak_factory_(this) { 399 weak_factory_(this) {
304 SetupQuicServerInfoFactory(network_layer_->GetSession()); 400 SetupQuicServerInfoFactory(network_layer_->GetSession());
305 } 401 }
306 402
307 403
308 // This call doesn't change the shared |session|'s QuicServerInfoFactory because 404 // This call doesn't change the shared |session|'s QuicServerInfoFactory because
309 // |session| is shared. 405 // |session| is shared.
310 HttpCache::HttpCache(HttpNetworkSession* session, 406 HttpCache::HttpCache(HttpNetworkSession* session,
311 BackendFactory* backend_factory) 407 BackendFactory* backend_factory)
312 : net_log_(session->net_log()), 408 : net_log_(session->net_log()),
313 backend_factory_(backend_factory), 409 backend_factory_(backend_factory),
314 building_backend_(false), 410 building_backend_(false),
315 bypass_lock_for_test_(false), 411 bypass_lock_for_test_(false),
412 use_stale_while_revalidate_(session->params().use_stale_while_revalidate),
316 mode_(NORMAL), 413 mode_(NORMAL),
317 network_layer_(new HttpNetworkLayer(session)), 414 network_layer_(new HttpNetworkLayer(session)),
318 weak_factory_(this) { 415 weak_factory_(this) {
319 } 416 }
320 417
321 HttpCache::HttpCache(HttpTransactionFactory* network_layer, 418 HttpCache::HttpCache(HttpTransactionFactory* network_layer,
322 NetLog* net_log, 419 NetLog* net_log,
323 BackendFactory* backend_factory) 420 BackendFactory* backend_factory)
324 : net_log_(net_log), 421 : net_log_(net_log),
325 backend_factory_(backend_factory), 422 backend_factory_(backend_factory),
326 building_backend_(false), 423 building_backend_(false),
327 bypass_lock_for_test_(false), 424 bypass_lock_for_test_(false),
425 use_stale_while_revalidate_(false),
328 mode_(NORMAL), 426 mode_(NORMAL),
329 network_layer_(network_layer), 427 network_layer_(network_layer),
330 weak_factory_(this) { 428 weak_factory_(this) {
331 SetupQuicServerInfoFactory(network_layer_->GetSession()); 429 SetupQuicServerInfoFactory(network_layer_->GetSession());
430 HttpNetworkSession* session = network_layer_->GetSession();
431 if (session)
432 use_stale_while_revalidate_ = session->params().use_stale_while_revalidate;
332 } 433 }
333 434
334 HttpCache::~HttpCache() { 435 HttpCache::~HttpCache() {
335 // Transactions should see an invalid cache after this point; otherwise they 436 // Transactions should see an invalid cache after this point; otherwise they
336 // could see an inconsistent object (half destroyed). 437 // could see an inconsistent object (half destroyed).
337 weak_factory_.InvalidateWeakPtrs(); 438 weak_factory_.InvalidateWeakPtrs();
338 439
339 // If we have any active entries remaining, then we need to deactivate them. 440 // If we have any active entries remaining, then we need to deactivate them.
340 // We may have some pending calls to OnProcessPendingQueue, but since those 441 // We may have some pending calls to OnProcessPendingQueue, but since those
341 // won't run (due to our destruction), we can simply ignore the corresponding 442 // won't run (due to our destruction), we can simply ignore the corresponding
342 // will_process_pending_queue flag. 443 // will_process_pending_queue flag.
343 while (!active_entries_.empty()) { 444 while (!active_entries_.empty()) {
344 ActiveEntry* entry = active_entries_.begin()->second; 445 ActiveEntry* entry = active_entries_.begin()->second;
345 entry->will_process_pending_queue = false; 446 entry->will_process_pending_queue = false;
346 entry->pending_queue.clear(); 447 entry->pending_queue.clear();
347 entry->readers.clear(); 448 entry->readers.clear();
348 entry->writer = NULL; 449 entry->writer = NULL;
349 DeactivateEntry(entry); 450 DeactivateEntry(entry);
350 } 451 }
351 452
352 STLDeleteElements(&doomed_entries_); 453 STLDeleteElements(&doomed_entries_);
454 STLDeleteElements(&async_validations_);
353 455
354 // Before deleting pending_ops_, we have to make sure that the disk cache is 456 // Before deleting pending_ops_, we have to make sure that the disk cache is
355 // done with said operations, or it will attempt to use deleted data. 457 // done with said operations, or it will attempt to use deleted data.
356 cert_cache_.reset(); 458 cert_cache_.reset();
357 disk_cache_.reset(); 459 disk_cache_.reset();
358 460
359 PendingOpsMap::iterator pending_it = pending_ops_.begin(); 461 PendingOpsMap::iterator pending_it = pending_ops_.begin();
360 for (; pending_it != pending_ops_.end(); ++pending_it) { 462 for (; pending_it != pending_ops_.end(); ++pending_it) {
361 // We are not notifying the transactions about the cache going away, even 463 // We are not notifying the transactions about the cache going away, even
362 // though they are waiting for a callback that will never fire. 464 // though they are waiting for a callback that will never fire.
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 // not delete the entry before OnProcessPendingQueue runs. 1133 // not delete the entry before OnProcessPendingQueue runs.
1032 if (entry->will_process_pending_queue) 1134 if (entry->will_process_pending_queue)
1033 return; 1135 return;
1034 entry->will_process_pending_queue = true; 1136 entry->will_process_pending_queue = true;
1035 1137
1036 base::MessageLoop::current()->PostTask( 1138 base::MessageLoop::current()->PostTask(
1037 FROM_HERE, 1139 FROM_HERE,
1038 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); 1140 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
1039 } 1141 }
1040 1142
1143 void HttpCache::PerformAsyncValidation(const HttpRequestInfo& original_request,
1144 const BoundNetLog& net_log) {
yhirano 2014/08/26 07:52:01 DCHECK(use_stale_while_revalidate_)?
Adam Rice 2014/08/26 13:38:41 Done.
1145 scoped_ptr<AsyncValidation> job(new AsyncValidation(original_request, this));
1146 job->Start(net_log);
yhirano 2014/08/26 07:52:01 When all operations are done synchronously, |this-
Adam Rice 2014/08/26 13:38:41 Good catch! Thanks! I have added a test (Synchron
1147 bool insert_ok = async_validations_.insert(job.release()).second;
1148 DCHECK(insert_ok);
1149 }
1150
1151 void HttpCache::DeleteAsyncValidation(AsyncValidation* async_validation) {
1152 size_t erased = async_validations_.erase(async_validation);
1153 DCHECK_EQ(1U, erased);
1154 delete async_validation;
1155 }
1156
1041 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { 1157 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
1042 entry->will_process_pending_queue = false; 1158 entry->will_process_pending_queue = false;
1043 DCHECK(!entry->writer); 1159 DCHECK(!entry->writer);
1044 1160
1045 // If no one is interested in this entry, then we can deactivate it. 1161 // If no one is interested in this entry, then we can deactivate it.
1046 if (entry->pending_queue.empty()) { 1162 if (entry->pending_queue.empty()) {
1047 if (entry->readers.empty()) 1163 if (entry->readers.empty())
1048 DestroyEntry(entry); 1164 DestroyEntry(entry);
1049 return; 1165 return;
1050 } 1166 }
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 building_backend_ = false; 1317 building_backend_ = false;
1202 DeletePendingOp(pending_op); 1318 DeletePendingOp(pending_op);
1203 } 1319 }
1204 1320
1205 // The cache may be gone when we return from the callback. 1321 // The cache may be gone when we return from the callback.
1206 if (!item->DoCallback(result, disk_cache_.get())) 1322 if (!item->DoCallback(result, disk_cache_.get()))
1207 item->NotifyTransaction(result, NULL); 1323 item->NotifyTransaction(result, NULL);
1208 } 1324 }
1209 1325
1210 } // namespace net 1326 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698