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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Initial patch Created 4 years 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_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" // For OS_POSIX 7 #include "build/build_config.h" // For OS_POSIX
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 truncated_(false), 173 truncated_(false),
174 is_sparse_(false), 174 is_sparse_(false),
175 range_requested_(false), 175 range_requested_(false),
176 handling_206_(false), 176 handling_206_(false),
177 cache_pending_(false), 177 cache_pending_(false),
178 done_reading_(false), 178 done_reading_(false),
179 vary_mismatch_(false), 179 vary_mismatch_(false),
180 couldnt_conditionalize_request_(false), 180 couldnt_conditionalize_request_(false),
181 bypass_lock_for_test_(false), 181 bypass_lock_for_test_(false),
182 fail_conditionalization_for_test_(false), 182 fail_conditionalization_for_test_(false),
183 shared_(false),
184 finalize_doomed_(false),
185 orphaned_(false),
183 io_buf_len_(0), 186 io_buf_len_(0),
184 read_offset_(0), 187 read_offset_(0),
185 effective_load_flags_(0), 188 effective_load_flags_(0),
186 write_len_(0), 189 write_len_(0),
187 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED), 190 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED),
188 validation_cause_(VALIDATION_CAUSE_UNDEFINED), 191 validation_cause_(VALIDATION_CAUSE_UNDEFINED),
189 total_received_bytes_(0), 192 total_received_bytes_(0),
190 total_sent_bytes_(0), 193 total_sent_bytes_(0),
191 websocket_handshake_stream_base_create_helper_(NULL), 194 websocket_handshake_stream_base_create_helper_(NULL),
195 have_full_request_headers_(false),
192 weak_factory_(this) { 196 weak_factory_(this) {
193 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction"); 197 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction");
194 static_assert(HttpCache::Transaction::kNumValidationHeaders == 198 static_assert(HttpCache::Transaction::kNumValidationHeaders ==
195 arraysize(kValidationHeaders), 199 arraysize(kValidationHeaders),
196 "invalid number of validation headers"); 200 "invalid number of validation headers");
197 201
198 io_callback_ = base::Bind(&Transaction::OnIOComplete, 202 io_callback_ = base::Bind(&Transaction::OnIOComplete,
199 weak_factory_.GetWeakPtr()); 203 weak_factory_.GetWeakPtr());
200 } 204 }
201 205
202 HttpCache::Transaction::~Transaction() { 206 HttpCache::Transaction::~Transaction() {
203 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction"); 207 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction");
208
209 // Assert to make sure that any owner of HttpCache::Transaction always invokes
210 // Orphan and not the destructor directly.
211 DCHECK(orphaned_);
212
204 // We may have to issue another IO, but we should never invoke the callback_ 213 // We may have to issue another IO, but we should never invoke the callback_
205 // after this point. 214 // after this point.
206 callback_.Reset(); 215 callback_.Reset();
216 weak_factory_.InvalidateWeakPtrs();
207 217
208 if (cache_) { 218 if (cache_) {
209 if (entry_) { 219 if (entry_ && !finalize_doomed_) {
210 bool cancel_request = reading_ && response_.headers.get(); 220 bool cancel_request = reading_ && response_.headers.get();
211 if (cancel_request) { 221 if (cancel_request) {
212 if (partial_) { 222 if (partial_) {
213 entry_->disk_entry->CancelSparseIO(); 223 entry_->disk_entry->CancelSparseIO();
214 } else { 224 } else {
215 cancel_request &= (response_.headers->response_code() == 200); 225 cancel_request &= (response_.headers->response_code() == 200);
216 } 226 }
217 } 227 }
218
219 cache_->DoneWithEntry(entry_, this, cancel_request); 228 cache_->DoneWithEntry(entry_, this, cancel_request);
220 } else if (cache_pending_) { 229 } else if (cache_pending_) {
221 cache_->RemovePendingTransaction(this); 230 cache_->RemovePendingTransaction(this);
222 } 231 }
223 } 232 }
224 } 233 }
225 234
226 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 235 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
227 const CompletionCallback& callback) { 236 const CompletionCallback& callback) {
228 DCHECK(buf); 237 DCHECK(buf);
(...skipping 26 matching lines...) Expand all
255 264
256 truncated_ = true; 265 truncated_ = true;
257 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; 266 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
258 DoLoop(OK); 267 DoLoop(OK);
259 return true; 268 return true;
260 } 269 }
261 270
262 LoadState HttpCache::Transaction::GetWriterLoadState() const { 271 LoadState HttpCache::Transaction::GetWriterLoadState() const {
263 if (network_trans_.get()) 272 if (network_trans_.get())
264 return network_trans_->GetLoadState(); 273 return network_trans_->GetLoadState();
274 if (shared_ && entry_)
275 return entry_->shared_writers->GetLoadState();
265 if (entry_ || !request_) 276 if (entry_ || !request_)
266 return LOAD_STATE_IDLE; 277 return LOAD_STATE_IDLE;
267 return LOAD_STATE_WAITING_FOR_CACHE; 278 return LOAD_STATE_WAITING_FOR_CACHE;
268 } 279 }
269 280
270 const NetLogWithSource& HttpCache::Transaction::net_log() const { 281 const NetLogWithSource& HttpCache::Transaction::net_log() const {
271 return net_log_; 282 return net_log_;
272 } 283 }
273 284
274 int HttpCache::Transaction::Start(const HttpRequestInfo* request, 285 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 375 }
365 376
366 bool HttpCache::Transaction::IsReadyToRestartForAuth() { 377 bool HttpCache::Transaction::IsReadyToRestartForAuth() {
367 if (!network_trans_.get()) 378 if (!network_trans_.get())
368 return false; 379 return false;
369 return network_trans_->IsReadyToRestartForAuth(); 380 return network_trans_->IsReadyToRestartForAuth();
370 } 381 }
371 382
372 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 383 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
373 const CompletionCallback& callback) { 384 const CompletionCallback& callback) {
385 if (next_state_ == STATE_SHARED_READ_WRITE_FAILED) {
386 return ERR_CACHE_WRITE_FAILURE;
387 }
388
374 DCHECK_EQ(next_state_, STATE_NONE); 389 DCHECK_EQ(next_state_, STATE_NONE);
375 DCHECK(buf); 390 DCHECK(buf);
376 DCHECK_GT(buf_len, 0); 391 DCHECK_GT(buf_len, 0);
377 DCHECK(!callback.is_null()); 392 DCHECK(!callback.is_null());
378 393
379 DCHECK(callback_.is_null()); 394 DCHECK(callback_.is_null());
380 395
381 if (!cache_.get()) 396 if (!cache_.get())
382 return ERR_UNEXPECTED; 397 return ERR_UNEXPECTED;
383 398
384 // If we have an intermediate auth response at this point, then it means the 399 // If we have an intermediate auth response at this point, then it means the
385 // user wishes to read the network response (the error page). If there is a 400 // user wishes to read the network response (the error page). If there is a
386 // previous response in the cache then we should leave it intact. 401 // previous response in the cache then we should leave it intact.
387 if (auth_response_.headers.get() && mode_ != NONE) { 402 if (auth_response_.headers.get() && mode_ != NONE) {
388 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); 403 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
389 DCHECK(mode_ & WRITE); 404 DCHECK(mode_ & WRITE);
390 DoneWritingToEntry(mode_ == READ_WRITE); 405 DoneWritingToEntry(mode_ == READ_WRITE);
391 mode_ = NONE; 406 mode_ = NONE;
392 } 407 }
393 408
394 reading_ = true; 409 reading_ = true;
395 read_buf_ = buf; 410 read_buf_ = buf;
396 io_buf_len_ = buf_len; 411 io_buf_len_ = buf_len;
397 if (network_trans_) { 412 if (network_trans_) {
413 DCHECK(!shared_);
398 DCHECK(mode_ == WRITE || mode_ == NONE || 414 DCHECK(mode_ == WRITE || mode_ == NONE ||
399 (mode_ == READ_WRITE && partial_)); 415 (mode_ == READ_WRITE && partial_));
400 next_state_ = STATE_NETWORK_READ; 416 next_state_ = STATE_NETWORK_READ;
401 } else { 417 } else if (!shared_) {
402 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); 418 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
403 next_state_ = STATE_CACHE_READ_DATA; 419 next_state_ = STATE_CACHE_READ_DATA;
420 } else { // uses SharedWriters
421 if (read_offset_ == entry_->disk_entry->GetDataSize(kResponseContentIndex))
422 next_state_ = STATE_SHARED_NETWORK_READ;
423 else {
424 DCHECK_LT(read_offset_,
425 entry_->disk_entry->GetDataSize(kResponseContentIndex));
426 next_state_ = STATE_CACHE_READ_DATA;
427 }
404 } 428 }
405 429
406 int rv = DoLoop(OK); 430 int rv = DoLoop(OK);
407 431
408 if (rv == ERR_IO_PENDING) { 432 if (rv == ERR_IO_PENDING) {
409 DCHECK(callback_.is_null()); 433 DCHECK(callback_.is_null());
410 callback_ = callback; 434 callback_ = callback;
411 } 435 }
412 return rv; 436 return rv;
413 } 437 }
414 438
415 void HttpCache::Transaction::StopCaching() { 439 void HttpCache::Transaction::StopCaching() {
416 // We really don't know where we are now. Hopefully there is no operation in 440 // We really don't know where we are now. Hopefully there is no operation in
417 // progress, but nothing really prevents this method to be called after we 441 // progress, but nothing really prevents this method to be called after we
418 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this 442 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
419 // point because we need the state machine for that (and even if we are really 443 // point because we need the state machine for that (and even if we are really
420 // free, that would be an asynchronous operation). In other words, keep the 444 // free, that would be an asynchronous operation). In other words, keep the
421 // entry how it is (it will be marked as truncated at destruction), and let 445 // entry how it is (it will be marked as truncated at destruction), and let
422 // the next piece of code that executes know that we are now reading directly 446 // the next piece of code that executes know that we are now reading directly
423 // from the net. 447 // from the net.
424 // TODO(mmenke): This doesn't release the lock on the cache entry, so a 448 // TODO(mmenke): This doesn't release the lock on the cache entry, so a
425 // future request for the resource will be blocked on this one. 449 // future request for the resource will be blocked on this one.
426 // Fix this. 450 // Fix this.
427 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() && 451 if (shared_) {
428 !is_sparse_ && !range_requested_) { 452 // This might or might not stop caching based on whether other consumers
453 // exist for this resource or not. If it does, shared_ will be set to false.
454 network_trans_ = cache_->StopCachingSharedWriters(this, entry_);
455 }
456 if (!shared_ && cache_.get() && entry_ && (mode_ & WRITE) &&
457 network_trans_.get() && !is_sparse_ && !range_requested_) {
429 mode_ = NONE; 458 mode_ = NONE;
430 } 459 }
431 } 460 }
432 461
433 bool HttpCache::Transaction::GetFullRequestHeaders( 462 bool HttpCache::Transaction::GetFullRequestHeaders(
434 HttpRequestHeaders* headers) const { 463 HttpRequestHeaders* headers) const {
435 if (network_trans_) 464 if (network_trans_)
436 return network_trans_->GetFullRequestHeaders(headers); 465 return network_trans_->GetFullRequestHeaders(headers);
437 466 else if (shared_) {
467 return entry_->shared_writers->GetFullRequestHeaders(headers);
468 } else if (have_full_request_headers_) {
469 *headers = full_request_headers_;
470 return true;
471 }
438 // TODO(juliatuttle): Read headers from cache. 472 // TODO(juliatuttle): Read headers from cache.
439 return false; 473 return false;
440 } 474 }
441 475
442 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const { 476 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
443 int64_t total_received_bytes = total_received_bytes_; 477 int64_t total_received_bytes = total_received_bytes_;
444 if (network_trans_) 478 if (network_trans_)
445 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 479 total_received_bytes += network_trans_->GetTotalReceivedBytes();
480 else if (shared_) {
481 total_received_bytes += entry_->shared_writers->GetTotalReceivedBytes();
482 }
446 return total_received_bytes; 483 return total_received_bytes;
447 } 484 }
448 485
449 int64_t HttpCache::Transaction::GetTotalSentBytes() const { 486 int64_t HttpCache::Transaction::GetTotalSentBytes() const {
450 int64_t total_sent_bytes = total_sent_bytes_; 487 int64_t total_sent_bytes = total_sent_bytes_;
451 if (network_trans_) 488 if (network_trans_)
452 total_sent_bytes += network_trans_->GetTotalSentBytes(); 489 total_sent_bytes += network_trans_->GetTotalSentBytes();
490 else if (shared_) {
491 total_sent_bytes += entry_->shared_writers->GetTotalSentBytes();
492 }
453 return total_sent_bytes; 493 return total_sent_bytes;
454 } 494 }
455 495
456 void HttpCache::Transaction::DoneReading() { 496 void HttpCache::Transaction::DoneReading() {
457 if (cache_.get() && entry_) { 497 if (cache_.get() && entry_) {
458 DCHECK_NE(mode_, UPDATE); 498 DCHECK_NE(mode_, UPDATE);
499 bool perform_entry_cleanup = true;
500 if (shared_) {
501 cache_->DoneReadingSharedWriters(this, entry_);
502 // entry_ cleanup already performed, if any.
503 perform_entry_cleanup = false;
504 }
459 if (mode_ & WRITE) { 505 if (mode_ & WRITE) {
460 DoneWritingToEntry(true); 506 DoneWritingToEntry(true, perform_entry_cleanup);
461 } else if (mode_ & READ) { 507 } else if (mode_ & READ) {
462 // It is necessary to check mode_ & READ because it is possible 508 // It is necessary to check mode_ & READ because it is possible
463 // for mode_ to be NONE and entry_ non-NULL with a write entry 509 // for mode_ to be NONE and entry_ non-NULL with a write entry
464 // if StopCaching was called. 510 // if StopCaching was called.
465 cache_->DoneReadingFromEntry(entry_, this); 511 cache_->DoneReadingFromEntry(entry_, this);
466 entry_ = NULL; 512 entry_ = NULL;
467 } 513 }
468 } 514 }
469 } 515 }
470 516
(...skipping 20 matching lines...) Expand all
491 return LOAD_STATE_IDLE; 537 return LOAD_STATE_IDLE;
492 } 538 }
493 539
494 void HttpCache::Transaction::SetQuicServerInfo( 540 void HttpCache::Transaction::SetQuicServerInfo(
495 QuicServerInfo* quic_server_info) {} 541 QuicServerInfo* quic_server_info) {}
496 542
497 bool HttpCache::Transaction::GetLoadTimingInfo( 543 bool HttpCache::Transaction::GetLoadTimingInfo(
498 LoadTimingInfo* load_timing_info) const { 544 LoadTimingInfo* load_timing_info) const {
499 if (network_trans_) 545 if (network_trans_)
500 return network_trans_->GetLoadTimingInfo(load_timing_info); 546 return network_trans_->GetLoadTimingInfo(load_timing_info);
547 else if (shared_)
548 return entry_->shared_writers->GetLoadTimingInfo(load_timing_info);
501 549
502 if (old_network_trans_load_timing_) { 550 if (old_network_trans_load_timing_) {
503 *load_timing_info = *old_network_trans_load_timing_; 551 *load_timing_info = *old_network_trans_load_timing_;
504 return true; 552 return true;
505 } 553 }
506 554
507 if (first_cache_access_since_.is_null()) 555 if (first_cache_access_since_.is_null())
508 return false; 556 return false;
509 557
510 // If the cache entry was opened, return that time. 558 // If the cache entry was opened, return that time.
511 load_timing_info->send_start = first_cache_access_since_; 559 load_timing_info->send_start = first_cache_access_since_;
512 // This time doesn't make much sense when reading from the cache, so just use 560 // This time doesn't make much sense when reading from the cache, so just use
513 // the same time as send_start. 561 // the same time as send_start.
514 load_timing_info->send_end = first_cache_access_since_; 562 load_timing_info->send_end = first_cache_access_since_;
515 return true; 563 return true;
516 } 564 }
517 565
518 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { 566 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
519 if (network_trans_) 567 if (network_trans_)
520 return network_trans_->GetRemoteEndpoint(endpoint); 568 return network_trans_->GetRemoteEndpoint(endpoint);
569 else if (shared_)
570 return entry_->shared_writers->GetRemoteEndpoint(endpoint);
521 571
522 if (!old_remote_endpoint_.address().empty()) { 572 if (!old_remote_endpoint_.address().empty()) {
523 *endpoint = old_remote_endpoint_; 573 *endpoint = old_remote_endpoint_;
524 return true; 574 return true;
525 } 575 }
526 576
527 return false; 577 return false;
528 } 578 }
529 579
530 void HttpCache::Transaction::PopulateNetErrorDetails( 580 void HttpCache::Transaction::PopulateNetErrorDetails(
531 NetErrorDetails* details) const { 581 NetErrorDetails* details) const {
532 if (network_trans_) 582 if (network_trans_)
533 return network_trans_->PopulateNetErrorDetails(details); 583 return network_trans_->PopulateNetErrorDetails(details);
584 else if (shared_)
585 return entry_->shared_writers->PopulateNetErrorDetails(details);
534 return; 586 return;
535 } 587 }
536 588
537 void HttpCache::Transaction::SetPriority(RequestPriority priority) { 589 void HttpCache::Transaction::SetPriority(RequestPriority priority) {
538 priority_ = priority; 590 priority_ = priority;
539 if (network_trans_) 591 if (network_trans_)
540 network_trans_->SetPriority(priority_); 592 network_trans_->SetPriority(priority_);
593 else if (shared_)
594 return entry_->shared_writers->SetPriority(priority_);
541 } 595 }
542 596
543 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper( 597 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
544 WebSocketHandshakeStreamBase::CreateHelper* create_helper) { 598 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
545 websocket_handshake_stream_base_create_helper_ = create_helper; 599 websocket_handshake_stream_base_create_helper_ = create_helper;
546 if (network_trans_) 600 if (network_trans_)
547 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper); 601 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
602 else if (shared_) {
603 return entry_->shared_writers->SetWebSocketHandshakeStreamCreateHelper(
604 create_helper);
605 }
548 } 606 }
549 607
550 void HttpCache::Transaction::SetBeforeNetworkStartCallback( 608 void HttpCache::Transaction::SetBeforeNetworkStartCallback(
551 const BeforeNetworkStartCallback& callback) { 609 const BeforeNetworkStartCallback& callback) {
552 DCHECK(!network_trans_); 610 DCHECK(!network_trans_);
553 before_network_start_callback_ = callback; 611 before_network_start_callback_ = callback;
554 } 612 }
555 613
556 void HttpCache::Transaction::SetBeforeHeadersSentCallback( 614 void HttpCache::Transaction::SetBeforeHeadersSentCallback(
557 const BeforeHeadersSentCallback& callback) { 615 const BeforeHeadersSentCallback& callback) {
558 DCHECK(!network_trans_); 616 DCHECK(!network_trans_);
559 before_headers_sent_callback_ = callback; 617 before_headers_sent_callback_ = callback;
560 } 618 }
561 619
562 int HttpCache::Transaction::ResumeNetworkStart() { 620 int HttpCache::Transaction::ResumeNetworkStart() {
563 if (network_trans_) 621 if (network_trans_)
564 return network_trans_->ResumeNetworkStart(); 622 return network_trans_->ResumeNetworkStart();
623 else if (shared_)
624 return entry_->shared_writers->ResumeNetworkStart();
565 return ERR_UNEXPECTED; 625 return ERR_UNEXPECTED;
566 } 626 }
567 627
568 void HttpCache::Transaction::GetConnectionAttempts( 628 void HttpCache::Transaction::GetConnectionAttempts(
569 ConnectionAttempts* out) const { 629 ConnectionAttempts* out) const {
570 ConnectionAttempts new_connection_attempts; 630 ConnectionAttempts new_connection_attempts;
571 if (network_trans_) 631 if (network_trans_)
572 network_trans_->GetConnectionAttempts(&new_connection_attempts); 632 network_trans_->GetConnectionAttempts(&new_connection_attempts);
633 else if (shared_) {
634 entry_->shared_writers->GetConnectionAttempts(&new_connection_attempts);
635 }
573 636
574 out->swap(new_connection_attempts); 637 out->swap(new_connection_attempts);
575 out->insert(out->begin(), old_connection_attempts_.begin(), 638 out->insert(out->begin(), old_connection_attempts_.begin(),
576 old_connection_attempts_.end()); 639 old_connection_attempts_.end());
577 } 640 }
578 641
579 //----------------------------------------------------------------------------- 642 //-----------------------------------------------------------------------------
580 643
581 // A few common patterns: (Foo* means Foo -> FooComplete) 644 // A few common patterns: (Foo* means Foo -> FooComplete)
jkarlin 2016/12/06 18:08:18 Need to update this comment with a typical flow th
582 // 645 //
583 // 1. Not-cached entry: 646 // 1. Not-cached entry:
584 // Start(): 647 // Start():
585 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* -> 648 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
586 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> 649 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
587 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* -> 650 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
588 // PartialHeadersReceived 651 // PartialHeadersReceived
589 // 652 //
590 // Read(): 653 // Read():
591 // NetworkRead* -> CacheWriteData* 654 // NetworkRead* -> CacheWriteData*
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 case STATE_CACHE_READ_METADATA_COMPLETE: 908 case STATE_CACHE_READ_METADATA_COMPLETE:
846 rv = DoCacheReadMetadataComplete(rv); 909 rv = DoCacheReadMetadataComplete(rv);
847 break; 910 break;
848 case STATE_NETWORK_READ: 911 case STATE_NETWORK_READ:
849 DCHECK_EQ(OK, rv); 912 DCHECK_EQ(OK, rv);
850 rv = DoNetworkRead(); 913 rv = DoNetworkRead();
851 break; 914 break;
852 case STATE_NETWORK_READ_COMPLETE: 915 case STATE_NETWORK_READ_COMPLETE:
853 rv = DoNetworkReadComplete(rv); 916 rv = DoNetworkReadComplete(rv);
854 break; 917 break;
918 case STATE_SHARED_NETWORK_READ:
919 DCHECK_EQ(OK, rv);
920 rv = DoSharedNetworkRead();
921 break;
922 case STATE_SHARED_NETWORK_READ_COMPLETE:
923 rv = DoSharedNetworkReadComplete(rv);
924 break;
925 case STATE_SHARED_NETWORK_READ_WAIT_COMPLETE:
926 rv = DoSharedNetworkReadWaitComplete(rv);
927 break;
855 case STATE_CACHE_READ_DATA: 928 case STATE_CACHE_READ_DATA:
856 DCHECK_EQ(OK, rv); 929 DCHECK_EQ(OK, rv);
857 rv = DoCacheReadData(); 930 rv = DoCacheReadData();
858 break; 931 break;
859 case STATE_CACHE_READ_DATA_COMPLETE: 932 case STATE_CACHE_READ_DATA_COMPLETE:
860 rv = DoCacheReadDataComplete(rv); 933 rv = DoCacheReadDataComplete(rv);
861 break; 934 break;
862 case STATE_CACHE_WRITE_DATA: 935 case STATE_CACHE_WRITE_DATA:
863 rv = DoCacheWriteData(rv); 936 rv = DoCacheWriteData(rv);
864 break; 937 break;
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 1574
1502 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1575 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
1503 1576
1504 if (new_response_->headers->response_code() == 416 && 1577 if (new_response_->headers->response_code() == 416 &&
1505 (request_->method == "GET" || request_->method == "POST")) { 1578 (request_->method == "GET" || request_->method == "POST")) {
1506 // If there is an active entry it may be destroyed with this transaction. 1579 // If there is an active entry it may be destroyed with this transaction.
1507 SetResponse(*new_response_); 1580 SetResponse(*new_response_);
1508 return OK; 1581 return OK;
1509 } 1582 }
1510 1583
1584 // If the transaction is shared and it is a 200 or an error response, then
1585 // doom the entry and let this transaction continue without writing to the
1586 // cache if shared writers contain more transactions. If not, continue
1587 // writing to the cache and also transfer the network transaction to shared
1588 // writers.
1589 if (shared_ && new_response->headers->response_code() != 304) {
1590 network_trans_ = cache_->ValidationNoMatchSharedWriters(
1591 cache_key_, this, std::move(network_trans_), priority_, entry_);
1592 if (!shared_) {
1593 DCHECK(network_trans_);
1594 if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) {
1595 UpdateCacheEntryStatus(
1596 CacheEntryStatus::ENTRY_VALIDATED_DOOM_SHARED_WRITING);
1597 }
1598 DoneWritingToEntry(false, false);
1599 return OK;
1600 } else {
1601 DCHECK(!network_trans_);
1602 }
1603 }
1604
1511 // Are we expecting a response to a conditional query? 1605 // Are we expecting a response to a conditional query?
1512 if (mode_ == READ_WRITE || mode_ == UPDATE) { 1606 if (mode_ == READ_WRITE || mode_ == UPDATE) {
1513 if (new_response->headers->response_code() == 304 || handling_206_) { 1607 if (new_response->headers->response_code() == 304 || handling_206_) {
1514 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED); 1608 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
1515 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 1609 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
1516 return OK; 1610 return OK;
1517 } 1611 }
1518 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED); 1612 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
1519 mode_ = WRITE; 1613 mode_ = WRITE;
1520 } 1614 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 1740
1647 int HttpCache::Transaction::DoCacheWriteResponse() { 1741 int HttpCache::Transaction::DoCacheWriteResponse() {
1648 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse"); 1742 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
1649 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1743 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1650 return WriteResponseInfoToEntry(truncated_); 1744 return WriteResponseInfoToEntry(truncated_);
1651 } 1745 }
1652 1746
1653 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1747 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1654 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete"); 1748 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
1655 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1749 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1656 return OnWriteResponseInfoToEntryComplete(result); 1750 int res = OnWriteResponseInfoToEntryComplete(result);
1751
1752 if (res != OK)
1753 return result;
1754
1755 return OK;
1756 }
1757
1758 void HttpCache::Transaction::ResetShared(bool continue_network_reading,
1759 bool continue_cache_reading) {
1760 if (!continue_network_reading) {
1761 SaveSharedNetworkTransInfo();
1762 }
1763 if (continue_cache_reading) {
1764 mode_ = READ;
1765 }
1766 shared_ = false;
1767 }
1768
1769 void HttpCache::Transaction::SetFinalizeDoomed() {
1770 finalize_doomed_ = true;
1771 }
1772
1773 void HttpCache::Transaction::SetShared() {
1774 shared_ = true;
1775 }
1776
1777 bool HttpCache::Transaction::shared() const {
1778 return shared_;
1779 }
1780
1781 bool HttpCache::Transaction::validating_shared() const {
1782 return shared_ && next_state_ != STATE_NONE &&
1783 next_state_ <= STATE_START_STATE_MACHINE_FINAL;
1657 } 1784 }
1658 1785
1659 int HttpCache::Transaction::DoTruncateCachedData() { 1786 int HttpCache::Transaction::DoTruncateCachedData() {
1660 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData"); 1787 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
1661 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1788 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1662 if (!entry_) 1789 if (!entry_)
1663 return OK; 1790 return OK;
1664 if (net_log_.IsCapturing()) 1791 if (net_log_.IsCapturing())
1665 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 1792 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1666 // Truncate the stream. 1793 // Truncate the stream.
(...skipping 30 matching lines...) Expand all
1697 if (net_log_.IsCapturing()) { 1824 if (net_log_.IsCapturing()) {
1698 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 1825 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
1699 result); 1826 result);
1700 } 1827 }
1701 } 1828 }
1702 1829
1703 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1830 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1704 return OK; 1831 return OK;
1705 } 1832 }
1706 1833
1834 void HttpCache::Transaction::ProcessForSharedWriting() {
1835 // Should not be already reading.
1836 if (reading_)
1837 return;
1838
1839 // If not already part of SharedWriters, then check if one should be
1840 // created.
1841 if (!shared_ && !IsEligibleForSharedWriting())
1842 return;
1843
1844 if (shared_) {
1845 // Non 304 case is already handled in DoSuccessfulSendRequest.
1846 if (response_.headers->response_code() != 304) {
1847 return;
1848 }
1849 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED_DO_SHARED_WRITING);
1850 cache_->ValidationMatchSharedWriters(this, priority_, entry_);
1851 network_trans_.reset();
1852 return;
1853 }
1854
1855 // Do not create a SharedWriters if its a Redirect response.
1856 if (response_.headers->response_code() != 200)
1857 return;
1858
1859 // or if its a no-store response.
1860 if (!entry_)
1861 return;
1862
1863 DCHECK(entry_ && network_trans_);
1864 cache_->CreateSharedWriters(this, std::move(network_trans_), priority_);
1865 }
1866
1707 int HttpCache::Transaction::DoPartialHeadersReceived() { 1867 int HttpCache::Transaction::DoPartialHeadersReceived() {
1708 new_response_ = NULL; 1868 new_response_ = NULL;
1709 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) 1869 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
1710 next_state_ = STATE_CACHE_READ_METADATA; 1870 next_state_ = STATE_CACHE_READ_METADATA;
1711 1871
1872 ProcessForSharedWriting();
1873
1712 if (!partial_) 1874 if (!partial_)
1713 return OK; 1875 return OK;
1714 1876
1715 if (reading_) { 1877 if (reading_) {
1716 if (network_trans_.get()) { 1878 if (network_trans_.get()) {
1717 next_state_ = STATE_NETWORK_READ; 1879 next_state_ = STATE_NETWORK_READ;
1718 } else { 1880 } else {
1719 next_state_ = STATE_CACHE_READ_DATA; 1881 next_state_ = STATE_CACHE_READ_DATA;
1720 } 1882 }
1721 } else if (mode_ != NONE) { 1883 } else if (mode_ != NONE) {
(...skipping 25 matching lines...) Expand all
1747 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO, 1909 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
1748 result); 1910 result);
1749 if (result != response_.metadata->size()) 1911 if (result != response_.metadata->size())
1750 return OnCacheReadError(result, false); 1912 return OnCacheReadError(result, false);
1751 return OK; 1913 return OK;
1752 } 1914 }
1753 1915
1754 int HttpCache::Transaction::DoNetworkRead() { 1916 int HttpCache::Transaction::DoNetworkRead() {
1755 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead"); 1917 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
1756 next_state_ = STATE_NETWORK_READ_COMPLETE; 1918 next_state_ = STATE_NETWORK_READ_COMPLETE;
1919
1757 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1920 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
1758 } 1921 }
1759 1922
1760 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1923 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1761 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete"); 1924 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete");
1762 DCHECK(mode_ & WRITE || mode_ == NONE); 1925 DCHECK(mode_ & WRITE || mode_ == NONE);
1763 1926
1764 if (!cache_.get()) 1927 if (!cache_.get())
1765 return ERR_UNEXPECTED; 1928 return ERR_UNEXPECTED;
1766 1929
1767 // If there is an error or we aren't saving the data, we are done; just wait 1930 // If there is an error or we aren't saving the data, we are done; just wait
1768 // until the destructor runs to see if we can keep the data. 1931 // until the destructor runs to see if we can keep the data.
1769 if (mode_ == NONE || result < 0) 1932 if (mode_ == NONE || result < 0)
1770 return result; 1933 return result;
1771 1934
1772 next_state_ = STATE_CACHE_WRITE_DATA; 1935 next_state_ = STATE_CACHE_WRITE_DATA;
1773 return result; 1936 return result;
1774 } 1937 }
1775 1938
1939 int HttpCache::Transaction::DoSharedNetworkRead() {
1940 next_state_ = STATE_SHARED_NETWORK_READ_COMPLETE;
1941 bool shared_read_in_progress = false;
1942 int result =
1943 entry_->shared_writers->Read(read_buf_.get(), io_buf_len_, io_callback_,
1944 this, shared_read_in_progress);
1945 if (shared_read_in_progress) {
1946 next_state_ = STATE_SHARED_NETWORK_READ_WAIT_COMPLETE;
1947 }
1948 return result;
1949 }
1950
1951 int HttpCache::Transaction::DoSharedNetworkReadComplete(int result) {
1952 if (result < 0) {
1953 cache_->NetworkReadFailedSharedWriters(this, entry_, result);
1954
1955 // Set entry as null so that the destructor does not invoke DoneWithEntry
1956 // again as we have already processed the entry_ in
1957 // NetworkReadFailedSharedWriters
1958 entry_ = nullptr;
1959 return result;
1960 }
1961
1962 read_offset_ += result;
1963 entry_->shared_writers->OnNetworkReadSuccess(this, read_buf_, result);
1964
1965 next_state_ = STATE_CACHE_WRITE_DATA;
1966 return result;
1967 }
1968
1969 int HttpCache::Transaction::DoSharedNetworkReadWaitComplete(int result) {
1970 // If its a network read failure, we just return the result.
1971 // If its a cache write failure, we return the result which is filled as -1
1972 // by SharedWriters,
1973 // If its a cache write success, read_buf_ would have been filled
1974 // with the read data by SharedWriters, so just return from here.
1975
1976 if (result == 0) { // response is complete.
1977 DoneWritingToEntry(true, false); // changes the mode_ to NONE.
1978 } else if (result > 0) {
1979 read_offset_ += result;
1980 } else {
1981 // Set entry as null so that the destructor does not invoke DoneWithEntry
1982 // again as we have already processed the entry_ in
1983 // NetworkReadFailedSharedWriters
1984 entry_ = nullptr;
1985 }
1986
1987 return result;
1988 }
1989
1776 int HttpCache::Transaction::DoCacheReadData() { 1990 int HttpCache::Transaction::DoCacheReadData() {
1777 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData"); 1991 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
1778 if (request_->method == "HEAD") 1992 if (request_->method == "HEAD")
1779 return 0; 1993 return 0;
1780 1994
1781 DCHECK(entry_); 1995 DCHECK(entry_);
1782 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 1996 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1783 1997
1784 if (net_log_.IsCapturing()) 1998 if (net_log_.IsCapturing())
1785 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA); 1999 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1845 if (net_log_.IsCapturing()) { 2059 if (net_log_.IsCapturing()) {
1846 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA, 2060 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
1847 result); 2061 result);
1848 } 2062 }
1849 } 2063 }
1850 if (!cache_.get()) 2064 if (!cache_.get())
1851 return ERR_UNEXPECTED; 2065 return ERR_UNEXPECTED;
1852 2066
1853 if (result != write_len_) { 2067 if (result != write_len_) {
1854 DLOG(ERROR) << "failed to write response data to cache"; 2068 DLOG(ERROR) << "failed to write response data to cache";
1855 DoneWritingToEntry(false); 2069 if (shared_) {
2070 // Fail any shared writers.
2071 network_trans_.reset(cache_->CacheWriteFailedSharedWriters(this, entry_));
2072 DCHECK(network_trans_);
2073 DoneWritingToEntry(false, false);
2074 } else {
2075 DoneWritingToEntry(false);
2076 }
1856 2077
1857 // We want to ignore errors writing to disk and just keep reading from 2078 // We want to ignore errors writing to disk and just keep reading from
1858 // the network. 2079 // the network.
1859 result = write_len_; 2080 result = write_len_;
1860 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) { 2081 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
1861 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2082 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1862 int64_t body_size = response_.headers->GetContentLength(); 2083 int64_t body_size = response_.headers->GetContentLength();
1863 if (body_size >= 0 && body_size <= current_size) 2084 if (body_size >= 0 && body_size <= current_size)
1864 done_reading_ = true; 2085 done_reading_ = true;
1865 } 2086 }
1866 2087
1867 if (partial_) { 2088 if (partial_) {
1868 // This may be the last request. 2089 // This may be the last request.
1869 if (result != 0 || truncated_ || 2090 if (result != 0 || truncated_ ||
1870 !(partial_->IsLastRange() || mode_ == WRITE)) { 2091 !(partial_->IsLastRange() || mode_ == WRITE)) {
1871 return DoPartialNetworkReadCompleted(result); 2092 return DoPartialNetworkReadCompleted(result);
1872 } 2093 }
1873 } 2094 }
1874 2095
2096 bool complete = false;
1875 if (result == 0) { 2097 if (result == 0) {
1876 // End of file. This may be the result of a connection problem so see if we 2098 // End of file. This may be the result of a connection problem so see if we
1877 // have to keep the entry around to be flagged as truncated later on. 2099 // have to keep the entry around to be flagged as truncated later on.
1878 if (done_reading_ || !entry_ || partial_ || 2100 if (done_reading_ || !entry_ || partial_ ||
1879 response_.headers->GetContentLength() <= 0) { 2101 response_.headers->GetContentLength() <= 0) {
1880 DoneWritingToEntry(true); 2102 complete = true;
1881 } 2103 }
1882 } 2104 }
1883 2105
2106 bool perform_entry_cleanup = true;
2107 if (shared_) {
2108 if (result || (!result && complete)) {
2109 cache_->CacheWriteSuccessSharedWriters(this, entry_, result);
2110 // entry_ cleanup already performed, if any.
2111 perform_entry_cleanup = false;
2112 }
2113 }
2114 if (complete) {
2115 DoneWritingToEntry(true, perform_entry_cleanup);
2116 }
2117
1884 return result; 2118 return result;
1885 } 2119 }
1886 2120
1887 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 2121 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1888 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2122 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1889 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; 2123 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1890 return WriteResponseInfoToEntry(true); 2124 return WriteResponseInfoToEntry(true);
1891 } 2125 }
1892 2126
1893 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) { 2127 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 2316
2083 if (partial_ && (is_sparse_ || truncated_) && 2317 if (partial_ && (is_sparse_ || truncated_) &&
2084 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 2318 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
2085 // Force revalidation for sparse or truncated entries. Note that we don't 2319 // Force revalidation for sparse or truncated entries. Note that we don't
2086 // want to ignore the regular validation logic just because a byte range was 2320 // want to ignore the regular validation logic just because a byte range was
2087 // part of the request. 2321 // part of the request.
2088 skip_validation = false; 2322 skip_validation = false;
2089 } 2323 }
2090 2324
2091 if (skip_validation) { 2325 if (skip_validation) {
2092 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED); 2326 if (shared_) {
2093 return SetupEntryForRead(); 2327 UpdateCacheEntryStatus(
2328 CacheEntryStatus::ENTRY_SKIP_VALIDATION_DO_SHARED_WRITING);
2329 entry_->shared_writers->OnValidationMatch(this, priority_);
2330 } else {
2331 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
2332 return SetupEntryForRead();
2333 }
2094 } else { 2334 } else {
2095 // Make the network request conditional, to see if we may reuse our cached 2335 // Make the network request conditional, to see if we may reuse our cached
2096 // response. If we cannot do so, then we just resort to a normal fetch. 2336 // response. If we cannot do so, then we just resort to a normal fetch.
2097 // Our mode remains READ_WRITE for a conditional request. Even if the 2337 // Our mode remains READ_WRITE for a conditional request. Even if the
2098 // conditionalization fails, we don't switch to WRITE mode until we 2338 // conditionalization fails, we don't switch to WRITE mode until we
2099 // know we won't be falling back to using the cache entry in the 2339 // know we won't be falling back to using the cache entry in the
2100 // LOAD_FROM_CACHE_IF_OFFLINE case. 2340 // LOAD_FROM_CACHE_IF_OFFLINE case.
2101 if (!ConditionalizeRequest()) { 2341 if (!ConditionalizeRequest()) {
2102 couldnt_conditionalize_request_ = true; 2342 couldnt_conditionalize_request_ = true;
2103 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE); 2343 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2234 DCHECK(network_trans_.get()); 2474 DCHECK(network_trans_.get());
2235 DCHECK_EQ(STATE_NONE, next_state_); 2475 DCHECK_EQ(STATE_NONE, next_state_);
2236 2476
2237 next_state_ = STATE_SEND_REQUEST_COMPLETE; 2477 next_state_ = STATE_SEND_REQUEST_COMPLETE;
2238 int rv = network_trans_->RestartWithAuth(credentials, io_callback_); 2478 int rv = network_trans_->RestartWithAuth(credentials, io_callback_);
2239 if (rv != ERR_IO_PENDING) 2479 if (rv != ERR_IO_PENDING)
2240 return DoLoop(rv); 2480 return DoLoop(rv);
2241 return rv; 2481 return rv;
2242 } 2482 }
2243 2483
2484 void HttpCache::Transaction::Orphan(std::unique_ptr<HttpTransaction> trans) {
2485 DCHECK_EQ(trans.get(), this);
2486 orphaned_ = true;
2487
2488 // Reset consumer's callback.
2489 callback_.Reset();
2490
2491 if (shared_) {
2492 if (next_state_ == STATE_SHARED_NETWORK_READ_COMPLETE ||
2493 next_state_ == STATE_CACHE_WRITE_DATA_COMPLETE) {
2494 // Might lead to setting shared_ to false if this is the only transaction
2495 // in SharedWriters.
2496 cache_->DoomCurrentSharedWriter(std::move(trans), entry_);
2497 } else if (next_state_ == STATE_SHARED_NETWORK_READ_WAIT_COMPLETE) {
2498 entry_->shared_writers->RemoveWaitingWriter(this);
2499 } else if (next_state_ != STATE_NONE &&
2500 next_state_ <= STATE_ADD_TO_ENTRY_COMPLETE) {
2501 cache_->RemovePendingTransaction(this);
2502 // Set cache_pending_ to false so that more cleanup is not attempted in
2503 // the destructor.
2504 cache_pending_ = false;
2505 } else if (validating_shared()) {
2506 cache_->RemoveValidatingTransSharedWriters(this, entry_);
2507 } else {
2508 bool cancel_request = reading_ && response_.headers.get();
2509 if (cancel_request) {
2510 cancel_request &= (response_.headers->response_code() == 200);
2511 }
2512 cache_->RemoveIdleSharedWriter(this, entry_, cancel_request);
2513 }
2514
2515 if (!shared_) {
2516 // Since any cleanup needed in entry_ and shared_writers is already done,
2517 // set entry_ to null.
2518 entry_ = nullptr;
2519 }
2520 }
2521
2522 if (!shared_) {
2523 trans.reset();
2524 }
2525 }
2526
2244 ValidationType HttpCache::Transaction::RequiresValidation() { 2527 ValidationType HttpCache::Transaction::RequiresValidation() {
2245 // TODO(darin): need to do more work here: 2528 // TODO(darin): need to do more work here:
2246 // - make sure we have a matching request method 2529 // - make sure we have a matching request method
2247 // - watch out for cached responses that depend on authentication 2530 // - watch out for cached responses that depend on authentication
2248 2531
2249 if (response_.vary_data.is_valid() && 2532 if (response_.vary_data.is_valid() &&
2250 !response_.vary_data.MatchesRequest(*request_, 2533 !response_.vary_data.MatchesRequest(*request_,
2251 *response_.headers.get())) { 2534 *response_.headers.get())) {
2252 vary_mismatch_ = true; 2535 vary_mismatch_ = true;
2253 validation_cause_ = VALIDATION_CAUSE_VARY_MISMATCH; 2536 validation_cause_ = VALIDATION_CAUSE_VARY_MISMATCH;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
2566 } 2849 }
2567 2850
2568 int HttpCache::Transaction::WriteToEntry(int index, int offset, 2851 int HttpCache::Transaction::WriteToEntry(int index, int offset,
2569 IOBuffer* data, int data_len, 2852 IOBuffer* data, int data_len,
2570 const CompletionCallback& callback) { 2853 const CompletionCallback& callback) {
2571 if (!entry_) 2854 if (!entry_)
2572 return data_len; 2855 return data_len;
2573 2856
2574 int rv = 0; 2857 int rv = 0;
2575 if (!partial_ || !data_len) { 2858 if (!partial_ || !data_len) {
2576 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, 2859 CompletionCallback io_callback = callback;
2577 true); 2860
2861 rv = entry_->disk_entry->WriteData(index, offset, data, data_len,
2862 io_callback, true);
2578 } else { 2863 } else {
2579 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); 2864 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
2580 } 2865 }
2581 return rv; 2866 return rv;
2582 } 2867 }
2583 2868
2584 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { 2869 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
2585 if (!entry_) 2870 if (!entry_)
2586 return OK; 2871 return OK;
2587 2872
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2627 result); 2912 result);
2628 } 2913 }
2629 2914
2630 if (result != io_buf_len_) { 2915 if (result != io_buf_len_) {
2631 DLOG(ERROR) << "failed to write response info to cache"; 2916 DLOG(ERROR) << "failed to write response info to cache";
2632 DoneWritingToEntry(false); 2917 DoneWritingToEntry(false);
2633 } 2918 }
2634 return OK; 2919 return OK;
2635 } 2920 }
2636 2921
2637 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2922 void HttpCache::Transaction::DoneWritingToEntry(bool success,
2923 bool perform_entry_cleanup) {
2638 if (!entry_) 2924 if (!entry_)
2639 return; 2925 return;
2640 2926
2641 RecordHistograms(); 2927 RecordHistograms();
2642 2928
2643 cache_->DoneWritingToEntry(entry_, success); 2929 if (perform_entry_cleanup) {
2644 entry_ = NULL; 2930 cache_->DoneWritingToEntry(entry_, success);
2931 }
2932 entry_ = nullptr;
2645 mode_ = NONE; // switch to 'pass through' mode 2933 mode_ = NONE; // switch to 'pass through' mode
2646 } 2934 }
2647 2935
2936 void HttpCache::Transaction::ContinueWithoutSharedWriting() {
2937 // Should own a network transaction to continue.
2938 DCHECK(network_trans_);
2939 shared_ = false;
2940 entry_ = nullptr;
2941 mode_ = NONE;
2942 }
2943
2648 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2944 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2649 DLOG(ERROR) << "ReadData failed: " << result; 2945 DLOG(ERROR) << "ReadData failed: " << result;
2650 const int result_for_histogram = std::max(0, -result); 2946 const int result_for_histogram = std::max(0, -result);
2651 if (restart) { 2947 if (restart) {
2652 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2948 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2653 result_for_histogram); 2949 result_for_histogram);
2654 } else { 2950 } else {
2655 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 2951 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2656 result_for_histogram); 2952 result_for_histogram);
2657 } 2953 }
2658 2954
2659 // Avoid using this entry in the future. 2955 // Avoid using this entry in the future.
2660 if (cache_.get()) 2956 if (cache_.get())
2661 cache_->DoomActiveEntry(cache_key_); 2957 cache_->DoomActiveEntry(cache_key_);
2662 2958
2663 if (restart) { 2959 if (restart) {
2664 DCHECK(!reading_); 2960 DCHECK(!reading_);
2665 DCHECK(!network_trans_.get()); 2961 DCHECK(!network_trans_.get());
2666 cache_->DoneWithEntry(entry_, this, false); 2962 if (shared_) {
2963 cache_->RemoveValidatingTransSharedWriters(this, entry_);
2964 } else {
2965 cache_->DoneWithEntry(entry_, this, false);
2966 }
2667 entry_ = NULL; 2967 entry_ = NULL;
2668 is_sparse_ = false; 2968 is_sparse_ = false;
2669 partial_.reset(); 2969 partial_.reset();
2670 next_state_ = STATE_GET_BACKEND; 2970 next_state_ = STATE_GET_BACKEND;
2671 return OK; 2971 return OK;
2672 } 2972 }
2673 2973
2674 return ERR_CACHE_READ_FAILURE; 2974 return ERR_CACHE_READ_FAILURE;
2675 } 2975 }
2676 2976
2677 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 2977 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2678 if (entry_lock_waiting_since_ != start_time) 2978 if (entry_lock_waiting_since_ != start_time)
2679 return; 2979 return;
2680 2980
2681 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 2981 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2682 2982
2683 if (!cache_) 2983 if (!cache_)
2684 return; 2984 return;
2685 2985
2686 cache_->RemovePendingTransaction(this); 2986 cache_->RemovePendingTransaction(this);
2687 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 2987 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2688 } 2988 }
2689 2989
2690 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 2990 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
2991 // Partial requests not supported with shared writing as of now.
2992 DCHECK(!shared_);
2691 DVLOG(2) << "DoomPartialEntry"; 2993 DVLOG(2) << "DoomPartialEntry";
2692 int rv = cache_->DoomEntry(cache_key_, NULL); 2994 int rv = cache_->DoomEntry(cache_key_, NULL);
2693 DCHECK_EQ(OK, rv); 2995 DCHECK_EQ(OK, rv);
2694 cache_->DoneWithEntry(entry_, this, false); 2996 cache_->DoneWithEntry(entry_, this, false);
2695 entry_ = NULL; 2997 entry_ = NULL;
2696 is_sparse_ = false; 2998 is_sparse_ = false;
2697 truncated_ = false; 2999 truncated_ = false;
2698 if (delete_object) 3000 if (delete_object)
2699 partial_.reset(NULL); 3001 partial_.reset(NULL);
2700 } 3002 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2741 if (!delete_object) { 3043 if (!delete_object) {
2742 // The simplest way to re-initialize partial_ is to create a new object. 3044 // The simplest way to re-initialize partial_ is to create a new object.
2743 partial_.reset(new PartialData()); 3045 partial_.reset(new PartialData());
2744 if (partial_->Init(request_->extra_headers)) 3046 if (partial_->Init(request_->extra_headers))
2745 partial_->SetHeaders(custom_request_->extra_headers); 3047 partial_->SetHeaders(custom_request_->extra_headers);
2746 else 3048 else
2747 partial_.reset(); 3049 partial_.reset();
2748 } 3050 }
2749 } 3051 }
2750 3052
2751 void HttpCache::Transaction::ResetNetworkTransaction() { 3053 void HttpCache::Transaction::SaveNetworkTransInfo() {
2752 DCHECK(!old_network_trans_load_timing_); 3054 DCHECK(!old_network_trans_load_timing_);
2753 DCHECK(network_trans_); 3055 DCHECK(network_trans_);
2754 LoadTimingInfo load_timing; 3056 LoadTimingInfo load_timing;
2755 if (network_trans_->GetLoadTimingInfo(&load_timing)) 3057 if (network_trans_->GetLoadTimingInfo(&load_timing))
2756 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); 3058 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
2757 total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); 3059 total_received_bytes_ += network_trans_->GetTotalReceivedBytes();
2758 total_sent_bytes_ += network_trans_->GetTotalSentBytes(); 3060 total_sent_bytes_ += network_trans_->GetTotalSentBytes();
2759 ConnectionAttempts attempts; 3061 ConnectionAttempts attempts;
2760 network_trans_->GetConnectionAttempts(&attempts); 3062 network_trans_->GetConnectionAttempts(&attempts);
2761 for (const auto& attempt : attempts) 3063 for (const auto& attempt : attempts)
2762 old_connection_attempts_.push_back(attempt); 3064 old_connection_attempts_.push_back(attempt);
2763 old_remote_endpoint_ = IPEndPoint(); 3065 old_remote_endpoint_ = IPEndPoint();
2764 network_trans_->GetRemoteEndpoint(&old_remote_endpoint_); 3066 network_trans_->GetRemoteEndpoint(&old_remote_endpoint_);
3067 }
3068
3069 void HttpCache::Transaction::SaveSharedNetworkTransInfo() {
3070 // If network_trans_ is still present, this transaction has not started using
3071 // the "shared" network transaction, so do nothing.
3072 if (network_trans_)
3073 return;
3074 DCHECK(!old_network_trans_load_timing_);
3075
3076 // If the transaction is being deleted while still in the waiting queue,
3077 // entry_ is not yet set, do nothing.
3078 if (!entry_)
3079 return;
3080 DCHECK(entry_->shared_writers);
3081 LoadTimingInfo load_timing;
3082 if (entry_->shared_writers->GetLoadTimingInfo(&load_timing))
3083 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
3084 total_received_bytes_ += entry_->shared_writers->GetTotalReceivedBytes();
3085 total_sent_bytes_ += entry_->shared_writers->GetTotalSentBytes();
3086 ConnectionAttempts attempts;
3087 entry_->shared_writers->GetConnectionAttempts(&attempts);
3088 for (const auto& attempt : attempts)
3089 old_connection_attempts_.push_back(attempt);
3090 old_remote_endpoint_ = IPEndPoint();
3091 entry_->shared_writers->GetRemoteEndpoint(&old_remote_endpoint_);
3092 have_full_request_headers_ =
3093 entry_->shared_writers->GetFullRequestHeaders(&full_request_headers_);
3094 }
3095
3096 void HttpCache::Transaction::ResetNetworkTransaction() {
3097 SaveNetworkTransInfo();
2765 network_trans_.reset(); 3098 network_trans_.reset();
2766 } 3099 }
2767 3100
2768 // Histogram data from the end of 2010 show the following distribution of 3101 // Histogram data from the end of 2010 show the following distribution of
2769 // response headers: 3102 // response headers:
2770 // 3103 //
2771 // Content-Length............... 87% 3104 // Content-Length............... 87%
2772 // Date......................... 98% 3105 // Date......................... 98%
2773 // Last-Modified................ 49% 3106 // Last-Modified................ 49%
2774 // Etag......................... 19% 3107 // Etag......................... 19%
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
2922 3255
2923 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) 3256 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
2924 return; 3257 return;
2925 DCHECK(!range_requested_); 3258 DCHECK(!range_requested_);
2926 DCHECK(!first_cache_access_since_.is_null()); 3259 DCHECK(!first_cache_access_since_.is_null());
2927 3260
2928 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 3261 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2929 3262
2930 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 3263 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2931 3264
3265 if (cache_entry_status_ ==
3266 CacheEntryStatus::ENTRY_VALIDATED_DO_SHARED_WRITING) {
3267 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.ValidationMatchSharedWriting",
3268 total_time);
3269 }
3270
2932 bool did_send_request = !send_request_since_.is_null(); 3271 bool did_send_request = !send_request_since_.is_null();
2933 DCHECK( 3272 DCHECK((did_send_request &&
2934 (did_send_request && 3273 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
2935 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE || 3274 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
2936 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED || 3275 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
2937 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED || 3276 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
2938 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) || 3277 cache_entry_status_ ==
2939 (!did_send_request && 3278 CacheEntryStatus::ENTRY_VALIDATED_DO_SHARED_WRITING ||
2940 cache_entry_status_ == CacheEntryStatus::ENTRY_USED)); 3279 cache_entry_status_ ==
3280 CacheEntryStatus::ENTRY_VALIDATED_DOOM_SHARED_WRITING)) ||
3281 (!did_send_request &&
3282 (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
3283 cache_entry_status_ ==
3284 CacheEntryStatus::ENTRY_SKIP_VALIDATION_DO_SHARED_WRITING)));
2941 3285
2942 if (!did_send_request) { 3286 if (!did_send_request) {
2943 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_USED); 3287 if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED) {
2944 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time); 3288 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
3289 } else if (cache_entry_status_ ==
3290 CacheEntryStatus::ENTRY_SKIP_VALIDATION_DO_SHARED_WRITING) {
3291 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SkipValidationSharedWriting",
3292 total_time);
3293 }
2945 return; 3294 return;
2946 } 3295 }
2947 3296
2948 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_; 3297 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
2949 int64_t before_send_percent = (total_time.ToInternalValue() == 0) 3298 int64_t before_send_percent = (total_time.ToInternalValue() == 0)
2950 ? 0 3299 ? 0
2951 : before_send_time * 100 / total_time; 3300 : before_send_time * 100 / total_time;
2952 DCHECK_GE(before_send_percent, 0); 3301 DCHECK_GE(before_send_percent, 0);
2953 DCHECK_LE(before_send_percent, 100); 3302 DCHECK_LE(before_send_percent, 100);
2954 base::HistogramBase::Sample before_send_sample = 3303 base::HistogramBase::Sample before_send_sample =
(...skipping 24 matching lines...) Expand all
2979 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated", 3328 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
2980 before_send_sample); 3329 before_send_sample);
2981 break; 3330 break;
2982 } 3331 }
2983 case CacheEntryStatus::ENTRY_UPDATED: { 3332 case CacheEntryStatus::ENTRY_UPDATED: {
2984 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time); 3333 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
2985 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated", 3334 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
2986 before_send_sample); 3335 before_send_sample);
2987 break; 3336 break;
2988 } 3337 }
3338 case CacheEntryStatus::ENTRY_VALIDATED_DO_SHARED_WRITING: {
3339 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.ValidationMatchSharedWriting",
3340 before_send_time);
3341 UMA_HISTOGRAM_PERCENTAGE(
3342 "HttpCache.PercentBeforeSend.ValidationMatchSharedWriting",
3343 before_send_sample);
3344 break;
3345 }
3346 case CacheEntryStatus::ENTRY_VALIDATED_DOOM_SHARED_WRITING: {
3347 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.ValidationDoomSharedWriting",
3348 before_send_time);
3349 UMA_HISTOGRAM_PERCENTAGE(
3350 "HttpCache.PercentBeforeSend.ValidationDoomSharedWriting",
3351 before_send_sample);
3352 break;
3353 }
2989 default: 3354 default:
2990 NOTREACHED(); 3355 NOTREACHED();
2991 } 3356 }
2992 } 3357 }
2993 3358
3359 bool HttpCache::Transaction::IsEligibleForSharedWriting() const {
3360 if (!(mode_ & WRITE))
3361 return false;
3362
3363 DCHECK(request_);
3364 if (request_->method != "GET")
3365 return false;
3366
3367 if (partial_ || range_requested_)
3368 return false;
3369
3370 return true;
3371 }
3372
3373 void HttpCache::Transaction::SetSharedWritingFailState() {
3374 // This state should only be set when the transaction is idle waiting for Read
3375 // to be invoked.
3376 DCHECK_EQ(next_state_, STATE_NONE);
3377 next_state_ = STATE_SHARED_READ_WRITE_FAILED;
3378 entry_ = nullptr;
3379 }
3380
2994 void HttpCache::Transaction::OnIOComplete(int result) { 3381 void HttpCache::Transaction::OnIOComplete(int result) {
3382 // Setting this in a local variable because if the consumer still exists, its
3383 // possible for this object to get destroyed during the consumer's callback
3384 // processing.
3385 bool orphaned = orphaned_;
2995 DoLoop(result); 3386 DoLoop(result);
3387 if (orphaned && finalize_doomed_) {
jkarlin 2016/12/06 21:06:28 finalized_doomed_ should cause a crash if this obj
shivanisha 2016/12/06 21:53:35 The underlying assumption here is that since orpha
jkarlin 2016/12/07 01:09:04 Makes sense, thanks.
3388 cache_->FinalizeDoomedSharedWriter(entry_);
jkarlin 2016/12/06 21:06:28 Also entry_
shivanisha 2016/12/06 21:53:35 Same as above.
shivanisha 2016/12/07 00:09:02 For clarity, I will add a comment for this assumpt
3389 }
2996 } 3390 }
2997 3391
2998 } // namespace net 3392 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698