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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Feedback incorporated (Rebased till refs/heads/master@{#446065}) Created 3 years, 11 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 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 17 matching lines...) Expand all
28 #include "base/threading/worker_pool.h" 28 #include "base/threading/worker_pool.h"
29 #include "base/time/default_clock.h" 29 #include "base/time/default_clock.h"
30 #include "base/time/time.h" 30 #include "base/time/time.h"
31 #include "net/base/cache_type.h" 31 #include "net/base/cache_type.h"
32 #include "net/base/io_buffer.h" 32 #include "net/base/io_buffer.h"
33 #include "net/base/load_flags.h" 33 #include "net/base/load_flags.h"
34 #include "net/base/net_errors.h" 34 #include "net/base/net_errors.h"
35 #include "net/base/upload_data_stream.h" 35 #include "net/base/upload_data_stream.h"
36 #include "net/disk_cache/disk_cache.h" 36 #include "net/disk_cache/disk_cache.h"
37 #include "net/http/disk_cache_based_quic_server_info.h" 37 #include "net/http/disk_cache_based_quic_server_info.h"
38 #include "net/http/http_cache_shared_writers.h"
38 #include "net/http/http_cache_transaction.h" 39 #include "net/http/http_cache_transaction.h"
39 #include "net/http/http_network_layer.h" 40 #include "net/http/http_network_layer.h"
40 #include "net/http/http_network_session.h" 41 #include "net/http/http_network_session.h"
41 #include "net/http/http_request_info.h" 42 #include "net/http/http_request_info.h"
42 #include "net/http/http_response_headers.h" 43 #include "net/http/http_response_headers.h"
43 #include "net/http/http_response_info.h" 44 #include "net/http/http_response_info.h"
44 #include "net/http/http_util.h" 45 #include "net/http/http_util.h"
45 #include "net/log/net_log_with_source.h" 46 #include "net/log/net_log_with_source.h"
46 #include "net/quic/chromium/quic_server_info.h" 47 #include "net/quic/chromium/quic_server_info.h"
47 48
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 335
335 // If we have any active entries remaining, then we need to deactivate them. 336 // If we have any active entries remaining, then we need to deactivate them.
336 // We may have some pending calls to OnProcessPendingQueue, but since those 337 // We may have some pending calls to OnProcessPendingQueue, but since those
337 // won't run (due to our destruction), we can simply ignore the corresponding 338 // won't run (due to our destruction), we can simply ignore the corresponding
338 // will_process_pending_queue flag. 339 // will_process_pending_queue flag.
339 while (!active_entries_.empty()) { 340 while (!active_entries_.empty()) {
340 ActiveEntry* entry = active_entries_.begin()->second.get(); 341 ActiveEntry* entry = active_entries_.begin()->second.get();
341 entry->will_process_pending_queue = false; 342 entry->will_process_pending_queue = false;
342 entry->pending_queue.clear(); 343 entry->pending_queue.clear();
343 entry->readers.clear(); 344 entry->readers.clear();
344 entry->writer = NULL; 345 entry->writer = nullptr;
346 entry->shared_writers.reset();
jkarlin 2017/02/03 18:26:19 Is this necessary?
shivanisha 2017/02/06 21:14:10 DeactivateEntry has multiple dchecks to assert tha
345 DeactivateEntry(entry); 347 DeactivateEntry(entry);
346 } 348 }
347 349
348 doomed_entries_.clear(); 350 doomed_entries_.clear();
349 351
350 // Before deleting pending_ops_, we have to make sure that the disk cache is 352 // Before deleting pending_ops_, we have to make sure that the disk cache is
351 // done with said operations, or it will attempt to use deleted data. 353 // done with said operations, or it will attempt to use deleted data.
352 disk_cache_.reset(); 354 disk_cache_.reset();
353 355
354 for (auto pending_it = pending_ops_.begin(); pending_it != pending_ops_.end(); 356 for (auto pending_it = pending_ops_.begin(); pending_it != pending_ops_.end();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 } 448 }
447 449
448 int HttpCache::CreateTransaction(RequestPriority priority, 450 int HttpCache::CreateTransaction(RequestPriority priority,
449 std::unique_ptr<HttpTransaction>* trans) { 451 std::unique_ptr<HttpTransaction>* trans) {
450 // Do lazy initialization of disk cache if needed. 452 // Do lazy initialization of disk cache if needed.
451 if (!disk_cache_.get()) { 453 if (!disk_cache_.get()) {
452 // We don't care about the result. 454 // We don't care about the result.
453 CreateBackend(NULL, CompletionCallback()); 455 CreateBackend(NULL, CompletionCallback());
454 } 456 }
455 457
456 HttpCache::Transaction* transaction = 458 HttpCache::Transaction* transaction =
457 new HttpCache::Transaction(priority, this); 459 new HttpCache::Transaction(priority, this);
458 if (bypass_lock_for_test_) 460 if (bypass_lock_for_test_)
459 transaction->BypassLockForTest(); 461 transaction->BypassLockForTest();
460 if (fail_conditionalization_for_test_) 462 if (fail_conditionalization_for_test_)
461 transaction->FailConditionalizationForTest(); 463 transaction->FailConditionalizationForTest();
462 464
463 trans->reset(transaction); 465 trans->reset(transaction);
464 return OK; 466 return OK;
465 } 467 }
466 468
467 HttpCache* HttpCache::GetCache() { 469 HttpCache* HttpCache::GetCache() {
468 return this; 470 return this;
469 } 471 }
470 472
471 HttpNetworkSession* HttpCache::GetSession() { 473 HttpNetworkSession* HttpCache::GetSession() {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 579
578 // We keep track of doomed entries so that we can ensure that they are 580 // We keep track of doomed entries so that we can ensure that they are
579 // cleaned up properly when the cache is destroyed. 581 // cleaned up properly when the cache is destroyed.
580 ActiveEntry* entry_ptr = entry.get(); 582 ActiveEntry* entry_ptr = entry.get();
581 DCHECK_EQ(0u, doomed_entries_.count(entry_ptr)); 583 DCHECK_EQ(0u, doomed_entries_.count(entry_ptr));
582 doomed_entries_[entry_ptr] = std::move(entry); 584 doomed_entries_[entry_ptr] = std::move(entry);
583 585
584 entry_ptr->disk_entry->Doom(); 586 entry_ptr->disk_entry->Doom();
585 entry_ptr->doomed = true; 587 entry_ptr->doomed = true;
586 588
587 DCHECK(entry_ptr->writer || !entry_ptr->readers.empty() || 589 DCHECK(entry_ptr->writer || entry_ptr->shared_writers ||
588 entry_ptr->will_process_pending_queue); 590 !entry_ptr->readers.empty() || entry_ptr->will_process_pending_queue);
589 return OK; 591 return OK;
590 } 592 }
591 593
592 int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) { 594 int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) {
593 std::unique_ptr<WorkItem> item = 595 std::unique_ptr<WorkItem> item =
594 base::MakeUnique<WorkItem>(WI_DOOM_ENTRY, trans, nullptr); 596 base::MakeUnique<WorkItem>(WI_DOOM_ENTRY, trans, nullptr);
595 PendingOp* pending_op = GetPendingOp(key); 597 PendingOp* pending_op = GetPendingOp(key);
596 if (pending_op->writer) { 598 if (pending_op->writer) {
597 pending_op->pending_queue.push_back(std::move(item)); 599 pending_op->pending_queue.push_back(std::move(item));
598 return ERR_IO_PENDING; 600 return ERR_IO_PENDING;
(...skipping 26 matching lines...) Expand all
625 // Defer to DoomEntry if there is an active entry, otherwise call 627 // Defer to DoomEntry if there is an active entry, otherwise call
626 // AsyncDoomEntry without triggering a callback. 628 // AsyncDoomEntry without triggering a callback.
627 if (active_entries_.count(key)) 629 if (active_entries_.count(key))
628 DoomEntry(key, NULL); 630 DoomEntry(key, NULL);
629 else 631 else
630 AsyncDoomEntry(key, NULL); 632 AsyncDoomEntry(key, NULL);
631 } 633 }
632 634
633 void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) { 635 void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) {
634 DCHECK(entry->doomed); 636 DCHECK(entry->doomed);
635 DCHECK(!entry->writer); 637 DCHECK(!entry->writer && !entry->shared_writers);
636 DCHECK(entry->readers.empty()); 638 DCHECK(entry->readers.empty());
637 DCHECK(entry->pending_queue.empty()); 639 DCHECK(entry->pending_queue.empty());
638 640
639 auto it = doomed_entries_.find(entry); 641 auto it = doomed_entries_.find(entry);
640 DCHECK(it != doomed_entries_.end()); 642 DCHECK(it != doomed_entries_.end());
641 doomed_entries_.erase(it); 643 doomed_entries_.erase(it);
642 } 644 }
643 645
644 HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) { 646 HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
645 auto it = active_entries_.find(key); 647 auto it = active_entries_.find(key);
646 return it != active_entries_.end() ? it->second.get() : NULL; 648 return it != active_entries_.end() ? it->second.get() : NULL;
647 } 649 }
648 650
649 HttpCache::ActiveEntry* HttpCache::ActivateEntry( 651 HttpCache::ActiveEntry* HttpCache::ActivateEntry(
650 disk_cache::Entry* disk_entry) { 652 disk_cache::Entry* disk_entry) {
651 DCHECK(!FindActiveEntry(disk_entry->GetKey())); 653 DCHECK(!FindActiveEntry(disk_entry->GetKey()));
652 ActiveEntry* entry = new ActiveEntry(disk_entry); 654 ActiveEntry* entry = new ActiveEntry(disk_entry);
653 active_entries_[disk_entry->GetKey()] = base::WrapUnique(entry); 655 active_entries_[disk_entry->GetKey()] = base::WrapUnique(entry);
654 return entry; 656 return entry;
655 } 657 }
656 658
657 void HttpCache::DeactivateEntry(ActiveEntry* entry) { 659 void HttpCache::DeactivateEntry(ActiveEntry* entry) {
658 DCHECK(!entry->will_process_pending_queue); 660 DCHECK(!entry->will_process_pending_queue);
659 DCHECK(!entry->doomed); 661 DCHECK(!entry->doomed);
660 DCHECK(!entry->writer); 662 DCHECK(!entry->writer && !entry->shared_writers);
661 DCHECK(entry->disk_entry); 663 DCHECK(entry->disk_entry);
662 DCHECK(entry->readers.empty()); 664 DCHECK(entry->readers.empty());
663 DCHECK(entry->pending_queue.empty()); 665 DCHECK(entry->pending_queue.empty());
664 666
665 std::string key = entry->disk_entry->GetKey(); 667 std::string key = entry->disk_entry->GetKey();
666 if (key.empty()) 668 if (key.empty())
667 return SlowDeactivateEntry(entry); 669 return SlowDeactivateEntry(entry);
668 670
669 auto it = active_entries_.find(key); 671 auto it = active_entries_.find(key);
670 DCHECK(it != active_entries_.end()); 672 DCHECK(it != active_entries_.end());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 FinalizeDoomedEntry(entry); 786 FinalizeDoomedEntry(entry);
785 } else { 787 } else {
786 DeactivateEntry(entry); 788 DeactivateEntry(entry);
787 } 789 }
788 } 790 }
789 791
790 int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) { 792 int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) {
791 DCHECK(entry); 793 DCHECK(entry);
792 DCHECK(entry->disk_entry); 794 DCHECK(entry->disk_entry);
793 795
794 // We implement a basic reader/writer lock for the disk cache entry. If 796 // If a writer is in the validation stage, all other transactions need to wait
795 // there is already a writer, then everyone has to wait for the writer to 797 // before they can access the cache entry. Once the validation stage is over
796 // finish before they can access the cache entry. There can be multiple 798 // and if the writer creates a SharedWriters object, other eligible
797 // readers. 799 // transactions will become equally privileged to be able to read from the
800 // network and write to the cache.
798 // 801 //
799 // NOTE: If the transaction can only write, then the entry should not be in 802 // NOTE: If the transaction can only write, then the entry should not be in
800 // use (since any existing entry should have already been doomed). 803 // use (since any existing entry should have already been doomed).
801
802 if (entry->writer || entry->will_process_pending_queue) { 804 if (entry->writer || entry->will_process_pending_queue) {
803 entry->pending_queue.push_back(trans); 805 entry->pending_queue.push_back(trans);
804 return ERR_IO_PENDING; 806 return ERR_IO_PENDING;
805 } 807 }
806 808
807 if (trans->mode() & Transaction::WRITE) { 809 if (entry->shared_writers) {
810 DCHECK(!entry->writer);
811 if (!trans->IsEligibleForSharedWriting() ||
812 !entry->shared_writers->CanAddNewTransaction()) {
813 entry->pending_queue.push_back(trans);
814 return ERR_IO_PENDING;
815 } else {
816 if (entry->shared_writers->AddTransaction(trans)) {
817 return OK;
818 } else {
819 // Another transaction is in the process of validation, wait for it and
820 // any other transactions already in the queue to complete.
821 return ERR_IO_PENDING;
822 }
823 }
824 } else if (trans->mode() & Transaction::WRITE) { // No SharedWriters.
808 // transaction needs exclusive access to the entry 825 // transaction needs exclusive access to the entry
809 if (entry->readers.empty()) { 826 if (entry->readers.empty()) {
810 entry->writer = trans; 827 entry->writer = trans;
811 } else { 828 } else {
812 entry->pending_queue.push_back(trans); 829 entry->pending_queue.push_back(trans);
813 return ERR_IO_PENDING; 830 return ERR_IO_PENDING;
814 } 831 }
815 } else { 832 } else {
816 // transaction needs read access to the entry 833 // transaction needs read access to the entry
817 entry->readers.push_back(trans); 834 entry->readers.insert(trans);
818 } 835 }
819 836
820 // We do this before calling EntryAvailable to force any further calls to 837 // We do this before calling EntryAvailable to force any further calls to
821 // AddTransactionToEntry to add their transaction to the pending queue, which 838 // AddTransactionToEntry to add their transaction to the pending queue, which
822 // ensures FIFO ordering. 839 // ensures FIFO ordering.
823 if (!entry->writer && !entry->pending_queue.empty()) 840 if (!entry->writer && !entry->pending_queue.empty())
824 ProcessPendingQueue(entry); 841 ProcessPendingQueue(entry);
825 842
826 return OK; 843 return OK;
827 } 844 }
828 845
829 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans, 846 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans,
830 bool cancel) { 847 bool cancel) {
848 // This is not expected to be called for shared writing transactions.
jkarlin 2017/02/03 18:26:19 Comment unnecessary
shivanisha 2017/02/06 21:14:10 Removed
849 DCHECK(!trans->shared());
850
831 // If we already posted a task to move on to the next transaction and this was 851 // If we already posted a task to move on to the next transaction and this was
832 // the writer, there is nothing to cancel. 852 // the writer, there is nothing to cancel.
833 if (entry->will_process_pending_queue && entry->readers.empty()) 853 if (entry->will_process_pending_queue && entry->readers.empty())
834 return; 854 return;
835 855
836 if (entry->writer) { 856 if (entry->writer) {
837 DCHECK(trans == entry->writer); 857 DCHECK(trans == entry->writer);
838
839 // Assume there was a failure. 858 // Assume there was a failure.
840 bool success = false; 859 bool success = false;
841 if (cancel) { 860 if (cancel) {
842 DCHECK(entry->disk_entry); 861 DCHECK(entry->disk_entry);
843 // This is a successful operation in the sense that we want to keep the 862 // This is a successful operation in the sense that we want to keep the
844 // entry. 863 // entry.
845 success = trans->AddTruncatedFlag(); 864 success = trans->AddTruncatedFlag();
846 // The previous operation may have deleted the entry. 865 // The previous operation may have deleted the entry.
847 if (!trans->entry()) 866 if (!trans->entry())
848 return; 867 return;
849 } 868 }
850 DoneWritingToEntry(entry, success); 869 DoneWritingToEntry(entry, success);
851 } else { 870 } else {
852 DoneReadingFromEntry(entry, trans); 871 DoneReadingFromEntry(entry, trans);
853 } 872 }
854 } 873 }
855 874
856 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) { 875 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) {
857 DCHECK(entry->readers.empty()); 876 DCHECK(entry->readers.empty());
877 DCHECK(!entry->shared_writers);
858 878
859 entry->writer = NULL; 879 entry->writer = NULL;
860 880
861 if (success) { 881 if (success) {
862 ProcessPendingQueue(entry); 882 ProcessPendingQueue(entry);
863 } else { 883 } else {
864 DCHECK(!entry->will_process_pending_queue); 884 DestroyEntryRestartPendingQueue(entry);
885 }
886 }
865 887
866 // We failed to create this entry. 888 void HttpCache::DestroyEntryRestartPendingQueue(ActiveEntry* entry) {
867 TransactionList pending_queue; 889 DCHECK(!entry->will_process_pending_queue);
868 pending_queue.swap(entry->pending_queue);
869 890
870 entry->disk_entry->Doom(); 891 // We failed to create this entry.
871 DestroyEntry(entry); 892 TransactionList pending_queue;
893 pending_queue.swap(entry->pending_queue);
872 894
873 // We need to do something about these pending entries, which now need to 895 entry->disk_entry->Doom();
874 // be added to a new entry. 896
875 while (!pending_queue.empty()) { 897 DestroyEntry(entry);
876 // ERR_CACHE_RACE causes the transaction to restart the whole process. 898
877 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE); 899 // We need to do something about these pending entries, which now need to
878 pending_queue.pop_front(); 900 // be added to a new entry.
879 } 901 while (!pending_queue.empty()) {
902 // ERR_CACHE_RACE causes the transaction to restart the whole process.
903 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
904 pending_queue.pop_front();
880 } 905 }
881 } 906 }
882 907
883 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) { 908 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) {
884 DCHECK(!entry->writer); 909 DCHECK(!entry->writer && !entry->shared_writers);
885 910
886 auto it = std::find(entry->readers.begin(), entry->readers.end(), trans); 911 auto it = entry->readers.find(trans);
887 DCHECK(it != entry->readers.end()); 912 DCHECK(it != entry->readers.end());
888 913
889 entry->readers.erase(it); 914 entry->readers.erase(it);
890 915
891 ProcessPendingQueue(entry); 916 ProcessPendingQueue(entry);
892 } 917 }
893 918
894 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) { 919 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) {
895 DCHECK(entry->writer); 920 DCHECK(entry->writer);
896 DCHECK(entry->writer->mode() == Transaction::READ_WRITE); 921 DCHECK(entry->writer->mode() == Transaction::READ_WRITE);
897 DCHECK(entry->readers.empty()); 922 DCHECK(entry->readers.empty());
898 923
899 Transaction* trans = entry->writer; 924 Transaction* trans = entry->writer;
900 925
901 entry->writer = NULL; 926 entry->writer = NULL;
902 entry->readers.push_back(trans); 927 entry->readers.insert(trans);
903 928
904 ProcessPendingQueue(entry); 929 ProcessPendingQueue(entry);
905 } 930 }
906 931
907 LoadState HttpCache::GetLoadStateForPendingTransaction( 932 LoadState HttpCache::GetLoadStateForPendingTransaction(
908 const Transaction* trans) { 933 const Transaction* trans) {
909 auto i = active_entries_.find(trans->key()); 934 auto i = active_entries_.find(trans->key());
910 if (i == active_entries_.end()) { 935 if (i == active_entries_.end()) {
911 // If this is really a pending transaction, and it is not part of 936 // If this is really a pending transaction, and it is not part of
912 // active_entries_, we should be creating the backend or the entry. 937 // active_entries_, we should be creating the backend or the entry.
913 return LOAD_STATE_WAITING_FOR_CACHE; 938 return LOAD_STATE_WAITING_FOR_CACHE;
914 } 939 }
915 940
916 Transaction* writer = i->second->writer; 941 Transaction* writer = i->second->writer;
917 return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE; 942 return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE;
918 } 943 }
919 944
920 void HttpCache::RemovePendingTransaction(Transaction* trans) { 945 void HttpCache::RemovePendingTransaction(Transaction* trans) {
946 bool found = false;
947
921 auto i = active_entries_.find(trans->key()); 948 auto i = active_entries_.find(trans->key());
922 bool found = false;
923 if (i != active_entries_.end()) 949 if (i != active_entries_.end())
924 found = RemovePendingTransactionFromEntry(i->second.get(), trans); 950 found = RemovePendingTransactionFromEntry(i->second.get(), trans);
925 951
926 if (found) 952 if (found)
927 return; 953 return;
928 954
929 if (building_backend_) { 955 if (building_backend_) {
930 auto j = pending_ops_.find(std::string()); 956 auto j = pending_ops_.find(std::string());
931 if (j != pending_ops_.end()) 957 if (j != pending_ops_.end())
932 found = RemovePendingTransactionFromPendingOp(j->second, trans); 958 found = RemovePendingTransactionFromPendingOp(j->second, trans);
(...skipping 12 matching lines...) Expand all
945 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found; 971 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found;
946 ++k) { 972 ++k) {
947 found = RemovePendingTransactionFromEntry(k->first, trans); 973 found = RemovePendingTransactionFromEntry(k->first, trans);
948 } 974 }
949 975
950 DCHECK(found) << "Pending transaction not found"; 976 DCHECK(found) << "Pending transaction not found";
951 } 977 }
952 978
953 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry, 979 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry,
954 Transaction* trans) { 980 Transaction* trans) {
981 if (trans->shared())
982 return entry->shared_writers->RemoveWaitingTransaction(trans);
983
955 TransactionList& pending_queue = entry->pending_queue; 984 TransactionList& pending_queue = entry->pending_queue;
956
957 auto j = find(pending_queue.begin(), pending_queue.end(), trans); 985 auto j = find(pending_queue.begin(), pending_queue.end(), trans);
958 if (j == pending_queue.end()) 986 if (j == pending_queue.end())
959 return false; 987 return false;
960
961 pending_queue.erase(j); 988 pending_queue.erase(j);
962 return true; 989 return true;
963 } 990 }
964 991
965 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op, 992 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
966 Transaction* trans) { 993 Transaction* trans) {
967 if (pending_op->writer->Matches(trans)) { 994 if (pending_op->writer->Matches(trans)) {
968 pending_op->writer->ClearTransaction(); 995 pending_op->writer->ClearTransaction();
969 pending_op->writer->ClearEntry(); 996 pending_op->writer->ClearEntry();
970 return true; 997 return true;
(...skipping 17 matching lines...) Expand all
988 return; 1015 return;
989 entry->will_process_pending_queue = true; 1016 entry->will_process_pending_queue = true;
990 1017
991 base::ThreadTaskRunnerHandle::Get()->PostTask( 1018 base::ThreadTaskRunnerHandle::Get()->PostTask(
992 FROM_HERE, 1019 FROM_HERE,
993 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); 1020 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
994 } 1021 }
995 1022
996 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { 1023 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
997 entry->will_process_pending_queue = false; 1024 entry->will_process_pending_queue = false;
998 DCHECK(!entry->writer); 1025 DCHECK(!entry->writer && !entry->shared_writers);
999 1026
1000 // If no one is interested in this entry, then we can deactivate it. 1027 // If no one is interested in this entry, then we can deactivate it.
1001 if (entry->pending_queue.empty()) { 1028 if (entry->pending_queue.empty()) {
1002 if (entry->readers.empty()) 1029 if (entry->readers.empty())
1003 DestroyEntry(entry); 1030 DestroyEntry(entry);
1004 return; 1031 return;
1005 } 1032 }
1006 1033
1007 // Promote next transaction from the pending queue. 1034 // Promote next transaction from the pending queue.
1008 Transaction* next = entry->pending_queue.front(); 1035 Transaction* next = entry->pending_queue.front();
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 } else { 1180 } else {
1154 building_backend_ = false; 1181 building_backend_ = false;
1155 DeletePendingOp(pending_op); 1182 DeletePendingOp(pending_op);
1156 } 1183 }
1157 1184
1158 // The cache may be gone when we return from the callback. 1185 // The cache may be gone when we return from the callback.
1159 if (!item->DoCallback(result, disk_cache_.get())) 1186 if (!item->DoCallback(result, disk_cache_.get()))
1160 item->NotifyTransaction(result, NULL); 1187 item->NotifyTransaction(result, NULL);
1161 } 1188 }
1162 1189
1190 bool HttpCache::IsResponseCompleted(const ActiveEntry* entry,
1191 const HttpResponseInfo* response_info) {
1192 int current_size = entry->disk_entry->GetDataSize(kResponseContentIndex);
1193 int64_t content_length = response_info->headers->GetContentLength();
1194 if ((content_length >= 0 && content_length <= current_size) ||
1195 content_length < 0)
1196 return true;
1197 return false;
1198 }
1199
1200 int HttpCache::WriteResponseInfo(ActiveEntry* entry,
1201 const HttpResponseInfo* response,
1202 CompletionCallback& callback,
1203 bool truncated,
1204 int* io_buf_len) {
1205 // When writing headers, we normally only write the non-transient headers.
1206 bool skip_transient_headers = true;
1207 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
1208 response->Persist(data->pickle(), skip_transient_headers, truncated);
1209 data->Done();
1210
1211 *io_buf_len = data->pickle()->size();
1212 return entry->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
1213 *io_buf_len, callback, true);
1214 }
1215
1216 // Histogram data from the end of 2010 show the following distribution of
1217 // response headers:
1218 //
1219 // Content-Length............... 87%
1220 // Date......................... 98%
1221 // Last-Modified................ 49%
1222 // Etag......................... 19%
1223 // Accept-Ranges: bytes......... 25%
1224 // Accept-Ranges: none.......... 0.4%
1225 // Strong Validator............. 50%
1226 // Strong Validator + ranges.... 24%
1227 // Strong Validator + CL........ 49%
1228 //
1229 bool HttpCache::CanResumeEntry(bool has_data,
1230 const std::string& method,
1231 const HttpResponseInfo* response,
1232 ActiveEntry* entry) {
1233 // Double check that there is something worth keeping.
1234 if (has_data && !entry->disk_entry->GetDataSize(kResponseContentIndex))
1235 return false;
1236
1237 if (method != "GET")
1238 return false;
1239
1240 // Note that if this is a 206, content-length was already fixed after calling
1241 // PartialData::ResponseHeadersOK().
1242 if (response->headers->GetContentLength() <= 0 ||
1243 response->headers->HasHeaderValue("Accept-Ranges", "none") ||
1244 !response->headers->HasStrongValidators()) {
1245 return false;
1246 }
1247
1248 return true;
1249 }
1250
1251 void HttpCache::CreateSharedWriters(
1252 Transaction* cache_transaction,
1253 std::unique_ptr<HttpTransaction> network_transaction,
1254 RequestPriority priority) {
1255 ActiveEntry* entry = cache_transaction->entry();
1256 DCHECK(!entry->shared_writers);
1257 DCHECK_EQ(entry->writer, cache_transaction);
1258 DCHECK(entry->readers.empty());
1259 entry->shared_writers.reset(
1260 new HttpCache::SharedWriters(this, entry, cache_transaction, priority,
1261 std::move(network_transaction)));
1262
1263 // entry->writer should no longer exist as it is moved to
1264 // shared_writers.
1265 entry->writer = nullptr;
1266
1267 // Add the eligible transactions to waiting_for_validation_ and process the
1268 // first among them. After this, pending_queue will only contain transactions
1269 // that are not eligible for shared writing.
1270 entry->shared_writers->MoveFromPendingQueue();
1271 entry->shared_writers->ProcessFirstWaitingValidation();
1272 }
1273
1274 void HttpCache::ResponseDoneSharedWriters(ActiveEntry* entry,
1275 bool success,
1276 bool* destroyed) {
1277 DCHECK(entry->shared_writers->empty());
1278 entry->shared_writers.reset();
1279 *destroyed = true;
1280
1281 if (success)
1282 ProcessPendingQueue(entry);
1283 else
1284 DestroyEntryRestartPendingQueue(entry);
1285 }
1286
1287 void HttpCache::ResetSharedWriters(ActiveEntry* entry) {
1288 DCHECK(entry->shared_writers->empty());
1289 entry->shared_writers.reset();
1290 }
1291
1292 void HttpCache::DoomEntryRestartPendingQueue(const std::string& key,
1293 ActiveEntry* entry) {
1294 DoomActiveEntry(key);
1295 // We need to do something about these pending entries, which now need to
1296 // be added to a new entry.
1297 while (!entry->pending_queue.empty()) {
1298 // ERR_CACHE_RACE causes the transaction to restart the whole process.
1299 entry->pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
1300 entry->pending_queue.pop_front();
1301 }
1302 }
1303
1304 void HttpCache::ResetSharedWritersProcessPendingQueue(ActiveEntry* entry) {
1305 if (entry->shared_writers->empty()) {
1306 entry->shared_writers.reset();
1307 DCHECK(!entry->writer);
1308 ProcessPendingQueue(entry);
1309 }
1310 }
1311
1312 void HttpCache::RemovedSharedWriterTransaction(Transaction* transaction,
1313 ActiveEntry* entry) {
1314 if (entry->shared_writers->empty()) {
1315 bool success = false;
1316 success = transaction->AddTruncatedFlag();
1317 if (success) {
1318 ResetSharedWritersProcessPendingQueue(entry);
1319 } else {
1320 entry->shared_writers.reset();
1321 DestroyEntryRestartPendingQueue(entry);
1322 }
1323 }
1324 }
1325
1163 } // namespace net 1326 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698