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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Feedback addressed Created 3 years, 10 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
« no previous file with comments | « net/http/http_cache.h ('k') | net/http/http_cache_shared_writers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
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 return entry->shared_writers->AddTransaction(trans);
817 }
818 } else if (trans->mode() & Transaction::WRITE) { // No SharedWriters.
808 // transaction needs exclusive access to the entry 819 // transaction needs exclusive access to the entry
809 if (entry->readers.empty()) { 820 if (entry->readers.empty()) {
810 entry->writer = trans; 821 entry->writer = trans;
811 } else { 822 } else {
812 entry->pending_queue.push_back(trans); 823 entry->pending_queue.push_back(trans);
813 return ERR_IO_PENDING; 824 return ERR_IO_PENDING;
814 } 825 }
815 } else { 826 } else {
816 // transaction needs read access to the entry 827 // transaction needs read access to the entry
817 entry->readers.push_back(trans); 828 entry->readers.insert(trans);
818 } 829 }
819 830
820 // We do this before calling EntryAvailable to force any further calls to 831 // We do this before calling EntryAvailable to force any further calls to
821 // AddTransactionToEntry to add their transaction to the pending queue, which 832 // AddTransactionToEntry to add their transaction to the pending queue, which
822 // ensures FIFO ordering. 833 // ensures FIFO ordering.
823 if (!entry->writer && !entry->pending_queue.empty()) 834 if (!entry->writer && !entry->pending_queue.empty())
824 ProcessPendingQueue(entry); 835 ProcessPendingQueue(entry);
825 836
826 return OK; 837 return OK;
827 } 838 }
828 839
829 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans, 840 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans,
830 bool cancel) { 841 bool cancel) {
842 DCHECK(!trans->shared());
843
831 // If we already posted a task to move on to the next transaction and this was 844 // If we already posted a task to move on to the next transaction and this was
832 // the writer, there is nothing to cancel. 845 // the writer, there is nothing to cancel.
833 if (entry->will_process_pending_queue && entry->readers.empty()) 846 if (entry->will_process_pending_queue && entry->readers.empty())
834 return; 847 return;
835 848
836 if (entry->writer) { 849 if (entry->writer) {
837 DCHECK(trans == entry->writer); 850 DCHECK(trans == entry->writer);
838
839 // Assume there was a failure. 851 // Assume there was a failure.
840 bool success = false; 852 bool success = false;
841 if (cancel) { 853 if (cancel) {
842 DCHECK(entry->disk_entry); 854 DCHECK(entry->disk_entry);
843 // This is a successful operation in the sense that we want to keep the 855 // This is a successful operation in the sense that we want to keep the
844 // entry. 856 // entry.
845 success = trans->AddTruncatedFlag(); 857 success = trans->AddTruncatedFlag();
846 // The previous operation may have deleted the entry. 858 // The previous operation may have deleted the entry.
847 if (!trans->entry()) 859 if (!trans->entry())
848 return; 860 return;
849 } 861 }
850 DoneWritingToEntry(entry, success); 862 DoneWritingToEntry(entry, success);
851 } else { 863 } else {
852 DoneReadingFromEntry(entry, trans); 864 DoneReadingFromEntry(entry, trans);
853 } 865 }
854 } 866 }
855 867
856 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) { 868 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) {
857 DCHECK(entry->readers.empty()); 869 DCHECK(entry->readers.empty());
870 DCHECK(!entry->shared_writers);
858 871
859 entry->writer = NULL; 872 entry->writer = NULL;
860 873
861 if (success) { 874 if (success) {
862 ProcessPendingQueue(entry); 875 ProcessPendingQueue(entry);
863 } else { 876 } else {
864 DCHECK(!entry->will_process_pending_queue); 877 DestroyEntryRestartPendingQueue(entry);
878 }
879 }
865 880
866 // We failed to create this entry. 881 void HttpCache::DestroyEntryRestartPendingQueue(ActiveEntry* entry) {
867 TransactionList pending_queue; 882 DCHECK(!entry->will_process_pending_queue);
868 pending_queue.swap(entry->pending_queue);
869 883
870 entry->disk_entry->Doom(); 884 // We failed to create this entry.
871 DestroyEntry(entry); 885 TransactionList pending_queue;
886 pending_queue.swap(entry->pending_queue);
872 887
873 // We need to do something about these pending entries, which now need to 888 entry->disk_entry->Doom();
874 // be added to a new entry. 889
875 while (!pending_queue.empty()) { 890 DestroyEntry(entry);
876 // ERR_CACHE_RACE causes the transaction to restart the whole process. 891
877 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE); 892 // We need to do something about these pending entries, which now need to
878 pending_queue.pop_front(); 893 // be added to a new entry.
879 } 894 while (!pending_queue.empty()) {
895 // ERR_CACHE_RACE causes the transaction to restart the whole process.
896 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
897 pending_queue.pop_front();
880 } 898 }
881 } 899 }
882 900
883 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) { 901 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) {
884 DCHECK(!entry->writer); 902 DCHECK(!entry->writer && !entry->shared_writers);
885 903
886 auto it = std::find(entry->readers.begin(), entry->readers.end(), trans); 904 auto it = entry->readers.find(trans);
887 DCHECK(it != entry->readers.end()); 905 DCHECK(it != entry->readers.end());
888 906
889 entry->readers.erase(it); 907 entry->readers.erase(it);
890 908
891 ProcessPendingQueue(entry); 909 ProcessPendingQueue(entry);
892 } 910 }
893 911
894 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) { 912 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) {
895 DCHECK(entry->writer); 913 DCHECK(entry->writer);
896 DCHECK(entry->writer->mode() == Transaction::READ_WRITE); 914 DCHECK(entry->writer->mode() == Transaction::READ_WRITE);
897 DCHECK(entry->readers.empty()); 915 DCHECK(entry->readers.empty());
898 916
899 Transaction* trans = entry->writer; 917 Transaction* trans = entry->writer;
900 918
901 entry->writer = NULL; 919 entry->writer = NULL;
902 entry->readers.push_back(trans); 920 entry->readers.insert(trans);
903 921
904 ProcessPendingQueue(entry); 922 ProcessPendingQueue(entry);
905 } 923 }
906 924
907 LoadState HttpCache::GetLoadStateForPendingTransaction( 925 LoadState HttpCache::GetLoadStateForPendingTransaction(
908 const Transaction* trans) { 926 const Transaction* trans) {
909 auto i = active_entries_.find(trans->key()); 927 auto i = active_entries_.find(trans->key());
910 if (i == active_entries_.end()) { 928 if (i == active_entries_.end()) {
911 // If this is really a pending transaction, and it is not part of 929 // 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. 930 // active_entries_, we should be creating the backend or the entry.
913 return LOAD_STATE_WAITING_FOR_CACHE; 931 return LOAD_STATE_WAITING_FOR_CACHE;
914 } 932 }
915 933
916 Transaction* writer = i->second->writer; 934 Transaction* writer = i->second->writer;
917 return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE; 935 return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE;
918 } 936 }
919 937
920 void HttpCache::RemovePendingTransaction(Transaction* trans) { 938 void HttpCache::RemovePendingTransaction(Transaction* trans) {
939 bool found = false;
940
921 auto i = active_entries_.find(trans->key()); 941 auto i = active_entries_.find(trans->key());
922 bool found = false;
923 if (i != active_entries_.end()) 942 if (i != active_entries_.end())
924 found = RemovePendingTransactionFromEntry(i->second.get(), trans); 943 found = RemovePendingTransactionFromEntry(i->second.get(), trans);
925 944
926 if (found) 945 if (found)
927 return; 946 return;
928 947
929 if (building_backend_) { 948 if (building_backend_) {
930 auto j = pending_ops_.find(std::string()); 949 auto j = pending_ops_.find(std::string());
931 if (j != pending_ops_.end()) 950 if (j != pending_ops_.end())
932 found = RemovePendingTransactionFromPendingOp(j->second, trans); 951 found = RemovePendingTransactionFromPendingOp(j->second, trans);
(...skipping 12 matching lines...) Expand all
945 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found; 964 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found;
946 ++k) { 965 ++k) {
947 found = RemovePendingTransactionFromEntry(k->first, trans); 966 found = RemovePendingTransactionFromEntry(k->first, trans);
948 } 967 }
949 968
950 DCHECK(found) << "Pending transaction not found"; 969 DCHECK(found) << "Pending transaction not found";
951 } 970 }
952 971
953 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry, 972 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry,
954 Transaction* trans) { 973 Transaction* trans) {
974 if (trans->shared())
975 return entry->shared_writers->RemoveWaitingForValidationTransaction(trans);
976
955 TransactionList& pending_queue = entry->pending_queue; 977 TransactionList& pending_queue = entry->pending_queue;
956
957 auto j = find(pending_queue.begin(), pending_queue.end(), trans); 978 auto j = find(pending_queue.begin(), pending_queue.end(), trans);
958 if (j == pending_queue.end()) 979 if (j == pending_queue.end())
959 return false; 980 return false;
960
961 pending_queue.erase(j); 981 pending_queue.erase(j);
962 return true; 982 return true;
963 } 983 }
964 984
965 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op, 985 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
966 Transaction* trans) { 986 Transaction* trans) {
967 if (pending_op->writer->Matches(trans)) { 987 if (pending_op->writer->Matches(trans)) {
968 pending_op->writer->ClearTransaction(); 988 pending_op->writer->ClearTransaction();
969 pending_op->writer->ClearEntry(); 989 pending_op->writer->ClearEntry();
970 return true; 990 return true;
(...skipping 17 matching lines...) Expand all
988 return; 1008 return;
989 entry->will_process_pending_queue = true; 1009 entry->will_process_pending_queue = true;
990 1010
991 base::ThreadTaskRunnerHandle::Get()->PostTask( 1011 base::ThreadTaskRunnerHandle::Get()->PostTask(
992 FROM_HERE, 1012 FROM_HERE,
993 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); 1013 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
994 } 1014 }
995 1015
996 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { 1016 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
997 entry->will_process_pending_queue = false; 1017 entry->will_process_pending_queue = false;
998 DCHECK(!entry->writer); 1018 DCHECK(!entry->writer && !entry->shared_writers);
999 1019
1000 // If no one is interested in this entry, then we can deactivate it. 1020 // If no one is interested in this entry, then we can deactivate it.
1001 if (entry->pending_queue.empty()) { 1021 if (entry->pending_queue.empty()) {
1002 if (entry->readers.empty()) 1022 if (entry->readers.empty())
1003 DestroyEntry(entry); 1023 DestroyEntry(entry);
1004 return; 1024 return;
1005 } 1025 }
1006 1026
1007 // Promote next transaction from the pending queue. 1027 // Promote next transaction from the pending queue.
1008 Transaction* next = entry->pending_queue.front(); 1028 Transaction* next = entry->pending_queue.front();
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 } else { 1173 } else {
1154 building_backend_ = false; 1174 building_backend_ = false;
1155 DeletePendingOp(pending_op); 1175 DeletePendingOp(pending_op);
1156 } 1176 }
1157 1177
1158 // The cache may be gone when we return from the callback. 1178 // The cache may be gone when we return from the callback.
1159 if (!item->DoCallback(result, disk_cache_.get())) 1179 if (!item->DoCallback(result, disk_cache_.get()))
1160 item->NotifyTransaction(result, NULL); 1180 item->NotifyTransaction(result, NULL);
1161 } 1181 }
1162 1182
1183 bool HttpCache::IsResponseCompleted(const ActiveEntry* entry,
1184 const HttpResponseInfo* response_info) {
1185 int current_size = entry->disk_entry->GetDataSize(kResponseContentIndex);
1186 int64_t content_length = response_info->headers->GetContentLength();
1187 if ((content_length >= 0 && content_length <= current_size) ||
1188 content_length < 0)
1189 return true;
1190 return false;
1191 }
1192
1193 int HttpCache::WriteResponseInfo(ActiveEntry* entry,
1194 const HttpResponseInfo* response,
1195 CompletionCallback& callback,
1196 bool truncated,
1197 int* io_buf_len) {
1198 // When writing headers, we normally only write the non-transient headers.
1199 bool skip_transient_headers = true;
1200 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
1201 response->Persist(data->pickle(), skip_transient_headers, truncated);
1202 data->Done();
1203
1204 *io_buf_len = data->pickle()->size();
1205 return entry->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
1206 *io_buf_len, callback, true);
1207 }
1208
1209 // Histogram data from the end of 2010 show the following distribution of
1210 // response headers:
1211 //
1212 // Content-Length............... 87%
1213 // Date......................... 98%
1214 // Last-Modified................ 49%
1215 // Etag......................... 19%
1216 // Accept-Ranges: bytes......... 25%
1217 // Accept-Ranges: none.......... 0.4%
1218 // Strong Validator............. 50%
1219 // Strong Validator + ranges.... 24%
1220 // Strong Validator + CL........ 49%
1221 //
1222 bool HttpCache::CanResumeEntry(bool has_data,
1223 const std::string& method,
1224 const HttpResponseInfo* response,
1225 ActiveEntry* entry) {
1226 // Double check that there is something worth keeping.
1227 if (has_data && !entry->disk_entry->GetDataSize(kResponseContentIndex))
1228 return false;
1229
1230 if (method != "GET")
1231 return false;
1232
1233 // Note that if this is a 206, content-length was already fixed after calling
1234 // PartialData::ResponseHeadersOK().
1235 if (response->headers->GetContentLength() <= 0 ||
1236 response->headers->HasHeaderValue("Accept-Ranges", "none") ||
1237 !response->headers->HasStrongValidators()) {
1238 return false;
1239 }
1240
1241 return true;
1242 }
1243
1244 void HttpCache::ResponseDoneSharedWriters(ActiveEntry* entry,
1245 bool success,
1246 bool* destroyed) {
1247 DCHECK(entry->shared_writers->empty());
1248 entry->shared_writers.reset();
1249 *destroyed = true;
1250
1251 if (success)
1252 ProcessPendingQueue(entry);
1253 else
1254 DestroyEntryRestartPendingQueue(entry);
1255 }
1256
1257 void HttpCache::ResetSharedWriters(ActiveEntry* entry) {
1258 DCHECK(entry->shared_writers->empty());
1259 entry->shared_writers.reset();
1260 }
1261
1262 void HttpCache::DoomEntryRestartPendingQueue(const std::string& key,
1263 ActiveEntry* entry) {
1264 DoomActiveEntry(key);
1265 // We need to do something about these pending entries, which now need to
1266 // be added to a new entry.
1267 while (!entry->pending_queue.empty()) {
1268 // ERR_CACHE_RACE causes the transaction to restart the whole process.
1269 entry->pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
1270 entry->pending_queue.pop_front();
1271 }
1272 }
1273
1274 void HttpCache::ResetSharedWritersProcessPendingQueue(ActiveEntry* entry) {
1275 if (entry->shared_writers->empty()) {
1276 entry->shared_writers.reset();
1277 DCHECK(!entry->writer);
1278 ProcessPendingQueue(entry);
1279 }
1280 }
1281
1282 void HttpCache::RemovedSharedWriterTransaction(Transaction* transaction,
1283 ActiveEntry* entry) {
1284 if (entry->shared_writers->empty()) {
1285 bool success = false;
1286 success = transaction->AddTruncatedFlag();
1287 if (success) {
1288 ResetSharedWritersProcessPendingQueue(entry);
1289 } else {
1290 entry->shared_writers.reset();
1291 DestroyEntryRestartPendingQueue(entry);
1292 }
1293 }
1294 }
1295
1163 } // namespace net 1296 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache.h ('k') | net/http/http_cache_shared_writers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698