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

Side by Side Diff: net/http/http_cache.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.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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 // This class encapsulates a transaction whose only purpose is to write metadata 192 // This class encapsulates a transaction whose only purpose is to write metadata
193 // to a given entry. 193 // to a given entry.
194 class HttpCache::MetadataWriter { 194 class HttpCache::MetadataWriter {
195 public: 195 public:
196 explicit MetadataWriter(HttpCache::Transaction* trans) 196 explicit MetadataWriter(HttpCache::Transaction* trans)
197 : transaction_(trans), 197 : transaction_(trans),
198 verified_(false), 198 verified_(false),
199 buf_len_(0) { 199 buf_len_(0) {
200 } 200 }
201 201
202 ~MetadataWriter() {} 202 ~MetadataWriter() { transaction_->Orphan(std::move(transaction_)); }
203 203
204 // Implements the bulk of HttpCache::WriteMetadata. 204 // Implements the bulk of HttpCache::WriteMetadata.
205 void Write(const GURL& url, 205 void Write(const GURL& url,
206 base::Time expected_response_time, 206 base::Time expected_response_time,
207 IOBuffer* buf, 207 IOBuffer* buf,
208 int buf_len); 208 int buf_len);
209 209
210 private: 210 private:
211 void VerifyResponse(int result); 211 void VerifyResponse(int result);
212 void SelfDestroy(); 212 void SelfDestroy();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 331
332 // If we have any active entries remaining, then we need to deactivate them. 332 // If we have any active entries remaining, then we need to deactivate them.
333 // We may have some pending calls to OnProcessPendingQueue, but since those 333 // We may have some pending calls to OnProcessPendingQueue, but since those
334 // won't run (due to our destruction), we can simply ignore the corresponding 334 // won't run (due to our destruction), we can simply ignore the corresponding
335 // will_process_pending_queue flag. 335 // will_process_pending_queue flag.
336 while (!active_entries_.empty()) { 336 while (!active_entries_.empty()) {
337 ActiveEntry* entry = active_entries_.begin()->second.get(); 337 ActiveEntry* entry = active_entries_.begin()->second.get();
338 entry->will_process_pending_queue = false; 338 entry->will_process_pending_queue = false;
339 entry->pending_queue.clear(); 339 entry->pending_queue.clear();
340 entry->readers.clear(); 340 entry->readers.clear();
341 entry->writer = NULL; 341 entry->writer = nullptr;
342 entry->shared_writers.reset();
342 DeactivateEntry(entry); 343 DeactivateEntry(entry);
343 } 344 }
344 345
345 doomed_entries_.clear(); 346 doomed_entries_.clear();
346 347
347 // Before deleting pending_ops_, we have to make sure that the disk cache is 348 // Before deleting pending_ops_, we have to make sure that the disk cache is
348 // done with said operations, or it will attempt to use deleted data. 349 // done with said operations, or it will attempt to use deleted data.
349 disk_cache_.reset(); 350 disk_cache_.reset();
350 351
351 for (auto pending_it = pending_ops_.begin(); pending_it != pending_ops_.end(); 352 for (auto pending_it = pending_ops_.begin(); pending_it != pending_ops_.end();
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 575
575 // We keep track of doomed entries so that we can ensure that they are 576 // We keep track of doomed entries so that we can ensure that they are
576 // cleaned up properly when the cache is destroyed. 577 // cleaned up properly when the cache is destroyed.
577 ActiveEntry* entry_ptr = entry.get(); 578 ActiveEntry* entry_ptr = entry.get();
578 DCHECK_EQ(0u, doomed_entries_.count(entry_ptr)); 579 DCHECK_EQ(0u, doomed_entries_.count(entry_ptr));
579 doomed_entries_[entry_ptr] = std::move(entry); 580 doomed_entries_[entry_ptr] = std::move(entry);
580 581
581 entry_ptr->disk_entry->Doom(); 582 entry_ptr->disk_entry->Doom();
582 entry_ptr->doomed = true; 583 entry_ptr->doomed = true;
583 584
584 DCHECK(entry_ptr->writer || !entry_ptr->readers.empty() || 585 DCHECK(entry_ptr->writer || entry_ptr->shared_writers ||
585 entry_ptr->will_process_pending_queue); 586 !entry_ptr->readers.empty() || entry_ptr->will_process_pending_queue);
586 return OK; 587 return OK;
587 } 588 }
588 589
589 int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) { 590 int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) {
590 std::unique_ptr<WorkItem> item = 591 std::unique_ptr<WorkItem> item =
591 base::MakeUnique<WorkItem>(WI_DOOM_ENTRY, trans, nullptr); 592 base::MakeUnique<WorkItem>(WI_DOOM_ENTRY, trans, nullptr);
592 PendingOp* pending_op = GetPendingOp(key); 593 PendingOp* pending_op = GetPendingOp(key);
593 if (pending_op->writer) { 594 if (pending_op->writer) {
594 pending_op->pending_queue.push_back(std::move(item)); 595 pending_op->pending_queue.push_back(std::move(item));
595 return ERR_IO_PENDING; 596 return ERR_IO_PENDING;
(...skipping 26 matching lines...) Expand all
622 // Defer to DoomEntry if there is an active entry, otherwise call 623 // Defer to DoomEntry if there is an active entry, otherwise call
623 // AsyncDoomEntry without triggering a callback. 624 // AsyncDoomEntry without triggering a callback.
624 if (active_entries_.count(key)) 625 if (active_entries_.count(key))
625 DoomEntry(key, NULL); 626 DoomEntry(key, NULL);
626 else 627 else
627 AsyncDoomEntry(key, NULL); 628 AsyncDoomEntry(key, NULL);
628 } 629 }
629 630
630 void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) { 631 void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) {
631 DCHECK(entry->doomed); 632 DCHECK(entry->doomed);
632 DCHECK(!entry->writer); 633 DCHECK(!entry->writer && !entry->shared_writers);
633 DCHECK(entry->readers.empty()); 634 DCHECK(entry->readers.empty());
634 DCHECK(entry->pending_queue.empty()); 635 DCHECK(entry->pending_queue.empty());
635 636
636 auto it = doomed_entries_.find(entry); 637 auto it = doomed_entries_.find(entry);
637 DCHECK(it != doomed_entries_.end()); 638 DCHECK(it != doomed_entries_.end());
638 doomed_entries_.erase(it); 639 doomed_entries_.erase(it);
639 } 640 }
640 641
641 HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) { 642 HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
642 auto it = active_entries_.find(key); 643 auto it = active_entries_.find(key);
643 return it != active_entries_.end() ? it->second.get() : NULL; 644 return it != active_entries_.end() ? it->second.get() : NULL;
644 } 645 }
645 646
646 HttpCache::ActiveEntry* HttpCache::ActivateEntry( 647 HttpCache::ActiveEntry* HttpCache::ActivateEntry(
647 disk_cache::Entry* disk_entry) { 648 disk_cache::Entry* disk_entry) {
648 DCHECK(!FindActiveEntry(disk_entry->GetKey())); 649 DCHECK(!FindActiveEntry(disk_entry->GetKey()));
649 ActiveEntry* entry = new ActiveEntry(disk_entry); 650 ActiveEntry* entry = new ActiveEntry(disk_entry);
650 active_entries_[disk_entry->GetKey()] = base::WrapUnique(entry); 651 active_entries_[disk_entry->GetKey()] = base::WrapUnique(entry);
651 return entry; 652 return entry;
652 } 653 }
653 654
654 void HttpCache::DeactivateEntry(ActiveEntry* entry) { 655 void HttpCache::DeactivateEntry(ActiveEntry* entry) {
655 DCHECK(!entry->will_process_pending_queue); 656 DCHECK(!entry->will_process_pending_queue);
656 DCHECK(!entry->doomed); 657 DCHECK(!entry->doomed);
657 DCHECK(!entry->writer); 658 DCHECK(!entry->writer && !entry->shared_writers);
658 DCHECK(entry->disk_entry); 659 DCHECK(entry->disk_entry);
659 DCHECK(entry->readers.empty()); 660 DCHECK(entry->readers.empty());
660 DCHECK(entry->pending_queue.empty()); 661 DCHECK(entry->pending_queue.empty());
661 662
662 std::string key = entry->disk_entry->GetKey(); 663 std::string key = entry->disk_entry->GetKey();
663 if (key.empty()) 664 if (key.empty())
664 return SlowDeactivateEntry(entry); 665 return SlowDeactivateEntry(entry);
665 666
666 auto it = active_entries_.find(key); 667 auto it = active_entries_.find(key);
667 DCHECK(it != active_entries_.end()); 668 DCHECK(it != active_entries_.end());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 FinalizeDoomedEntry(entry); 782 FinalizeDoomedEntry(entry);
782 } else { 783 } else {
783 DeactivateEntry(entry); 784 DeactivateEntry(entry);
784 } 785 }
785 } 786 }
786 787
787 int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) { 788 int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) {
788 DCHECK(entry); 789 DCHECK(entry);
789 DCHECK(entry->disk_entry); 790 DCHECK(entry->disk_entry);
790 791
791 // We implement a basic reader/writer lock for the disk cache entry. If 792 // If a writer is in the validation stage, all other transactions need to wait
792 // there is already a writer, then everyone has to wait for the writer to 793 // before they can access the cache entry. Once the validation stage is over
793 // finish before they can access the cache entry. There can be multiple 794 // and if the writer creates a SharedWriters object, other eligible
794 // readers. 795 // transactions will become equally privileged to be able to read from the
796 // network and write to the cache.
795 // 797 //
796 // NOTE: If the transaction can only write, then the entry should not be in 798 // NOTE: If the transaction can only write, then the entry should not be in
797 // use (since any existing entry should have already been doomed). 799 // use (since any existing entry should have already been doomed).
798
799 if (entry->writer || entry->will_process_pending_queue) { 800 if (entry->writer || entry->will_process_pending_queue) {
800 entry->pending_queue.push_back(trans); 801 entry->pending_queue.push_back(trans);
801 return ERR_IO_PENDING; 802 return ERR_IO_PENDING;
802 } 803 }
803 804
804 if (trans->mode() & Transaction::WRITE) { 805 if (entry->shared_writers) {
806 DCHECK(!entry->writer);
807 if (!trans->IsEligibleForSharedWriting()) {
808 entry->pending_queue.push_back(trans);
809 return ERR_IO_PENDING;
810 } else {
811 if (entry->shared_writers->AddTransaction(trans)) {
812 return OK;
813 } else {
814 // Another transaction is in the process of validation, wait for it and
815 // any other transactions already in the queue to complete.
816 return ERR_IO_PENDING;
817 }
818 }
819 }
820
821 // No SharedWriters.
822 else if (trans->mode() & Transaction::WRITE) {
805 // transaction needs exclusive access to the entry 823 // transaction needs exclusive access to the entry
806 if (entry->readers.empty()) { 824 if (entry->readers.empty()) {
807 entry->writer = trans; 825 entry->writer = trans;
808 } else { 826 } else {
809 entry->pending_queue.push_back(trans); 827 entry->pending_queue.push_back(trans);
810 return ERR_IO_PENDING; 828 return ERR_IO_PENDING;
811 } 829 }
812 } else { 830 } else {
813 // transaction needs read access to the entry 831 // transaction needs read access to the entry
814 entry->readers.push_back(trans); 832 entry->readers.insert(trans);
815 } 833 }
816 834
817 // We do this before calling EntryAvailable to force any further calls to 835 // We do this before calling EntryAvailable to force any further calls to
818 // AddTransactionToEntry to add their transaction to the pending queue, which 836 // AddTransactionToEntry to add their transaction to the pending queue, which
819 // ensures FIFO ordering. 837 // ensures FIFO ordering.
820 if (!entry->writer && !entry->pending_queue.empty()) 838 if (!entry->writer && !entry->pending_queue.empty())
821 ProcessPendingQueue(entry); 839 ProcessPendingQueue(entry);
822 840
823 return OK; 841 return OK;
824 } 842 }
825 843
826 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans, 844 void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans,
827 bool cancel) { 845 bool cancel) {
846 // This is not expected to be called for shared writing transactions which
847 // have completed their Start state machine.
848 DCHECK(!trans->shared());
849
828 // If we already posted a task to move on to the next transaction and this was 850 // If we already posted a task to move on to the next transaction and this was
829 // the writer, there is nothing to cancel. 851 // the writer, there is nothing to cancel.
830 if (entry->will_process_pending_queue && entry->readers.empty()) 852 if (entry->will_process_pending_queue && entry->readers.empty())
831 return; 853 return;
832 854
833 if (entry->writer) { 855 if (entry->writer) {
834 DCHECK(trans == entry->writer); 856 DCHECK(trans == entry->writer);
835
836 // Assume there was a failure. 857 // Assume there was a failure.
837 bool success = false; 858 bool success = false;
838 if (cancel) { 859 if (cancel) {
839 DCHECK(entry->disk_entry); 860 DCHECK(entry->disk_entry);
840 // This is a successful operation in the sense that we want to keep the 861 // This is a successful operation in the sense that we want to keep the
841 // entry. 862 // entry.
842 success = trans->AddTruncatedFlag(); 863 success = trans->AddTruncatedFlag();
843 // The previous operation may have deleted the entry. 864 // The previous operation may have deleted the entry.
844 if (!trans->entry()) 865 if (!trans->entry())
845 return; 866 return;
846 } 867 }
847 DoneWritingToEntry(entry, success); 868 DoneWritingToEntry(entry, success);
848 } else { 869 } else {
849 DoneReadingFromEntry(entry, trans); 870 DoneReadingFromEntry(entry, trans);
850 } 871 }
851 } 872 }
852 873
853 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) { 874 void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) {
854 DCHECK(entry->readers.empty()); 875 DCHECK(entry->readers.empty());
876 DCHECK(!entry->shared_writers);
855 877
856 entry->writer = NULL; 878 entry->writer = NULL;
857 879
858 if (success) { 880 if (success) {
859 ProcessPendingQueue(entry); 881 ProcessPendingQueue(entry);
860 } else { 882 } else {
861 DCHECK(!entry->will_process_pending_queue); 883 DestroyEntryAndRestartPendingQueueTxns(entry);
884 }
885 }
862 886
863 // We failed to create this entry. 887 void HttpCache::DestroyEntryAndRestartPendingQueueTxns(ActiveEntry* entry) {
864 TransactionList pending_queue; 888 DCHECK(!entry->will_process_pending_queue);
865 pending_queue.swap(entry->pending_queue);
866 889
867 entry->disk_entry->Doom(); 890 // We failed to create this entry.
868 DestroyEntry(entry); 891 TransactionList pending_queue;
892 pending_queue.swap(entry->pending_queue);
869 893
870 // We need to do something about these pending entries, which now need to 894 entry->disk_entry->Doom();
871 // be added to a new entry. 895
872 while (!pending_queue.empty()) { 896 DestroyEntry(entry);
873 // ERR_CACHE_RACE causes the transaction to restart the whole process. 897
874 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE); 898 // We need to do something about these pending entries, which now need to
875 pending_queue.pop_front(); 899 // be added to a new entry.
876 } 900 while (!pending_queue.empty()) {
901 // ERR_CACHE_RACE causes the transaction to restart the whole process.
902 pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
903 pending_queue.pop_front();
877 } 904 }
878 } 905 }
879 906
880 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) { 907 void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) {
881 DCHECK(!entry->writer); 908 DCHECK(!entry->writer && !entry->shared_writers);
882 909
883 auto it = std::find(entry->readers.begin(), entry->readers.end(), trans); 910 auto it = entry->readers.find(trans);
884 DCHECK(it != entry->readers.end()); 911 DCHECK(it != entry->readers.end());
885 912
886 entry->readers.erase(it); 913 entry->readers.erase(it);
887 914
888 ProcessPendingQueue(entry); 915 ProcessPendingQueue(entry);
889 } 916 }
890 917
891 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) { 918 void HttpCache::ConvertWriterToReader(ActiveEntry* entry) {
892 DCHECK(entry->writer);
893 DCHECK(entry->writer->mode() == Transaction::READ_WRITE); 919 DCHECK(entry->writer->mode() == Transaction::READ_WRITE);
894 DCHECK(entry->readers.empty()); 920 DCHECK(entry->readers.empty());
895 921
896 Transaction* trans = entry->writer; 922 Transaction* trans = entry->writer;
897 923
898 entry->writer = NULL; 924 entry->writer = NULL;
899 entry->readers.push_back(trans); 925 entry->readers.insert(trans);
900 926
901 ProcessPendingQueue(entry); 927 ProcessPendingQueue(entry);
902 } 928 }
903 929
904 LoadState HttpCache::GetLoadStateForPendingTransaction( 930 LoadState HttpCache::GetLoadStateForPendingTransaction(
905 const Transaction* trans) { 931 const Transaction* trans) {
906 auto i = active_entries_.find(trans->key()); 932 auto i = active_entries_.find(trans->key());
907 if (i == active_entries_.end()) { 933 if (i == active_entries_.end()) {
908 // If this is really a pending transaction, and it is not part of 934 // If this is really a pending transaction, and it is not part of
909 // active_entries_, we should be creating the backend or the entry. 935 // active_entries_, we should be creating the backend or the entry.
910 return LOAD_STATE_WAITING_FOR_CACHE; 936 return LOAD_STATE_WAITING_FOR_CACHE;
911 } 937 }
912 938
913 Transaction* writer = i->second->writer; 939 Transaction* writer = i->second->writer;
914 return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE; 940 if (writer)
941 return writer->GetWriterLoadState();
942
943 if (i->second->shared_writers)
944 return i->second->shared_writers->GetLoadState();
945
946 return LOAD_STATE_WAITING_FOR_CACHE;
915 } 947 }
916 948
917 void HttpCache::RemovePendingTransaction(Transaction* trans) { 949 void HttpCache::RemovePendingTransaction(Transaction* trans) {
950 bool found = false;
951
918 auto i = active_entries_.find(trans->key()); 952 auto i = active_entries_.find(trans->key());
919 bool found = false;
920 if (i != active_entries_.end()) 953 if (i != active_entries_.end())
921 found = RemovePendingTransactionFromEntry(i->second.get(), trans); 954 found = RemovePendingTransactionFromEntry(i->second.get(), trans);
922 955
923 if (found) 956 if (found)
924 return; 957 return;
925 958
926 if (building_backend_) { 959 if (building_backend_) {
927 auto j = pending_ops_.find(std::string()); 960 auto j = pending_ops_.find(std::string());
928 if (j != pending_ops_.end()) 961 if (j != pending_ops_.end())
929 found = RemovePendingTransactionFromPendingOp(j->second, trans); 962 found = RemovePendingTransactionFromPendingOp(j->second, trans);
(...skipping 12 matching lines...) Expand all
942 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found; 975 for (auto k = doomed_entries_.begin(); k != doomed_entries_.end() && !found;
943 ++k) { 976 ++k) {
944 found = RemovePendingTransactionFromEntry(k->first, trans); 977 found = RemovePendingTransactionFromEntry(k->first, trans);
945 } 978 }
946 979
947 DCHECK(found) << "Pending transaction not found"; 980 DCHECK(found) << "Pending transaction not found";
948 } 981 }
949 982
950 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry, 983 bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry,
951 Transaction* trans) { 984 Transaction* trans) {
952 TransactionList& pending_queue = entry->pending_queue; 985 if (trans->shared()) {
953 986 return entry->shared_writers->RemoveWaitingTransaction(trans);
954 auto j = find(pending_queue.begin(), pending_queue.end(), trans); 987 } else {
955 if (j == pending_queue.end()) 988 TransactionList& pending_queue = entry->pending_queue;
956 return false; 989 auto j = find(pending_queue.begin(), pending_queue.end(), trans);
957 990 if (j == pending_queue.end())
958 pending_queue.erase(j); 991 return false;
959 return true; 992 pending_queue.erase(j);
993 return true;
994 }
960 } 995 }
961 996
962 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op, 997 bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
963 Transaction* trans) { 998 Transaction* trans) {
964 if (pending_op->writer->Matches(trans)) { 999 if (pending_op->writer->Matches(trans)) {
965 pending_op->writer->ClearTransaction(); 1000 pending_op->writer->ClearTransaction();
966 pending_op->writer->ClearEntry(); 1001 pending_op->writer->ClearEntry();
967 return true; 1002 return true;
968 } 1003 }
969 WorkItemList& pending_queue = pending_op->pending_queue; 1004 WorkItemList& pending_queue = pending_op->pending_queue;
(...skipping 15 matching lines...) Expand all
985 return; 1020 return;
986 entry->will_process_pending_queue = true; 1021 entry->will_process_pending_queue = true;
987 1022
988 base::ThreadTaskRunnerHandle::Get()->PostTask( 1023 base::ThreadTaskRunnerHandle::Get()->PostTask(
989 FROM_HERE, 1024 FROM_HERE,
990 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry)); 1025 base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
991 } 1026 }
992 1027
993 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) { 1028 void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
994 entry->will_process_pending_queue = false; 1029 entry->will_process_pending_queue = false;
995 DCHECK(!entry->writer); 1030 DCHECK(!entry->writer && !entry->shared_writers);
996 1031
997 // If no one is interested in this entry, then we can deactivate it. 1032 // If no one is interested in this entry, then we can deactivate it.
998 if (entry->pending_queue.empty()) { 1033 if (entry->pending_queue.empty()) {
999 if (entry->readers.empty()) 1034 if (entry->readers.empty())
1000 DestroyEntry(entry); 1035 DestroyEntry(entry);
1001 return; 1036 return;
1002 } 1037 }
1003 1038
1004 // Promote next transaction from the pending queue. 1039 // Promote next transaction from the pending queue.
1005 Transaction* next = entry->pending_queue.front(); 1040 Transaction* next = entry->pending_queue.front();
1041
1006 if ((next->mode() & Transaction::WRITE) && !entry->readers.empty()) 1042 if ((next->mode() & Transaction::WRITE) && !entry->readers.empty())
1007 return; // Have to wait. 1043 return; // Have to wait.
1008 1044
1009 entry->pending_queue.erase(entry->pending_queue.begin()); 1045 entry->pending_queue.erase(entry->pending_queue.begin());
1010 1046
1011 int rv = AddTransactionToEntry(entry, next); 1047 int rv = AddTransactionToEntry(entry, next);
1012 if (rv != ERR_IO_PENDING) { 1048 if (rv != ERR_IO_PENDING) {
1013 next->io_callback().Run(rv); 1049 next->io_callback().Run(rv);
1014 } 1050 }
1015 } 1051 }
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 } else { 1186 } else {
1151 building_backend_ = false; 1187 building_backend_ = false;
1152 DeletePendingOp(pending_op); 1188 DeletePendingOp(pending_op);
1153 } 1189 }
1154 1190
1155 // The cache may be gone when we return from the callback. 1191 // The cache may be gone when we return from the callback.
1156 if (!item->DoCallback(result, disk_cache_.get())) 1192 if (!item->DoCallback(result, disk_cache_.get()))
1157 item->NotifyTransaction(result, NULL); 1193 item->NotifyTransaction(result, NULL);
1158 } 1194 }
1159 1195
1196 void HttpCache::CreateSharedWriters(
1197 Transaction* cache_trans,
1198 std::unique_ptr<HttpTransaction> network_trans,
1199 RequestPriority priority) {
1200 ActiveEntry* entry = cache_trans->entry();
1201 DCHECK(!entry->shared_writers);
1202 DCHECK_EQ(entry->writer, cache_trans);
1203 DCHECK(entry->readers.empty());
1204 entry->shared_writers.reset(new HttpCache::SharedWriters(
1205 this, entry, cache_trans, priority, std::move(network_trans)));
1206
1207 // entry->writer should no longer exist as it is moved to
1208 // shared_writers.
1209 entry->writer = nullptr;
1210
1211 // Add the eligible transactions to waiting_for_validation_ and process the
1212 // first among them. Post this, pending_queue will only contain transactions
1213 // that are not eligible for shared writing.
1214 entry->shared_writers->MoveFromPendingQueue();
1215 entry->shared_writers->ProcessFirstWaitingValidation();
1216 }
1217
1218 HttpCache::SharedWriters::SharedWriters(
1219 HttpCache* cache,
1220 ActiveEntry* entry,
1221 Transaction* cache_trans,
1222 RequestPriority priority,
1223 std::unique_ptr<HttpTransaction> transaction)
1224 : cache_(cache->GetWeakPtr()),
1225 entry_(entry),
1226 current_writer_(nullptr),
1227 validating_trans_(nullptr),
1228 priority_(priority),
1229 destroy_entry_(false),
1230 weak_factory_(this) {
1231 cache_trans->SetShared();
1232 all_writers_.insert(cache_trans);
1233 network_trans_ = std::move(transaction);
1234 }
1235
1236 HttpCache::SharedWriters::~SharedWriters() {
1237 weak_factory_.InvalidateWeakPtrs();
1238 }
1239
1240 std::unique_ptr<HttpTransaction> HttpCache::StopCachingSharedWriters(
1241 Transaction* transaction,
1242 ActiveEntry* entry) {
1243 auto network_trans = entry->shared_writers->StopCaching(transaction);
1244
1245 if (network_trans) { // stopped
1246 DCHECK(entry->shared_writers->empty());
1247 DCHECK_EQ(entry->writer, transaction);
1248 entry->shared_writers.reset();
1249 }
1250
1251 return network_trans;
1252 }
1253
1254 std::unique_ptr<HttpTransaction> HttpCache::SharedWriters::StopCaching(
1255 Transaction* transaction) {
1256 bool result = false;
1257 if (transaction == validating_trans_) {
1258 if (all_writers_.empty()) {
1259 result = true;
1260 validating_trans_ = nullptr;
1261 }
1262 } else if (all_writers_.size() == 1 && all_writers_.count(transaction) &&
1263 !validating_trans_) {
1264 if (current_writer_ == transaction) {
1265 current_writer_ = nullptr;
1266 }
1267 all_writers_.erase(transaction);
1268 result = true;
1269 }
1270 if (result) {
1271 transaction->ResetShared(true);
1272 entry_->writer = transaction;
1273 MoveToPendingQueue();
1274 return std::move(network_trans_);
1275 }
1276 return std::unique_ptr<HttpTransaction>();
1277 }
1278
1279 HttpTransaction* HttpCache::CacheWriteFailedSharedWriters(Transaction* trans,
1280 ActiveEntry* entry) {
1281 HttpTransaction* network_trans =
1282 entry->shared_writers->OnCacheWriteFailure(trans);
1283
1284 if (entry->shared_writers->empty()) {
1285 entry->shared_writers.reset();
1286 DestroyEntryAndRestartPendingQueueTxns(entry);
1287 }
1288 return network_trans;
1289 }
1290
1291 HttpTransaction* HttpCache::SharedWriters::OnCacheWriteFailure(
1292 Transaction* trans) {
1293 DCHECK_EQ(trans, current_writer_);
1294
1295 // Now we need to take care of all the transactions in SharedWriters and
1296 // delete SharedWriters as without the cache, we cannot continue the shared
1297 // logic.
1298 ResetAndRemoveCurrentWriter(true);
1299
1300 // Notify waiting_writers_ of the failure. Tasks will be posted for all the
1301 // transactions.
1302 ProcessWaitingWriters(ERR_CACHE_WRITE_FAILURE);
1303
1304 // Idle readers should know to fail when Read is invoked by their consumers.
1305 SetIdleWritersFailState();
1306 DCHECK(all_writers_.empty());
1307
1308 // If there is a transaction validating currently, let it continue reading
1309 // from the network without attempting to write to the cache.
1310 if (validating_trans_) {
1311 validating_trans_->ContinueWithoutSharedWriting();
1312 validating_trans_ = nullptr;
1313 }
1314 MoveToPendingQueue();
1315
1316 if (!empty()) {
1317 DCHECK(doomed_writer_);
1318 destroy_entry_ = true;
1319 }
1320
1321 return network_trans_.release();
1322 }
1323
1324 void HttpCache::FinalizeDoomedSharedWriter(ActiveEntry* entry) {
1325 bool destroy_entry = false;
1326 entry->shared_writers->FinalizeDoomedWriter(destroy_entry);
1327 if (destroy_entry) {
1328 DestroyEntryAndRestartPendingQueueTxns(entry);
1329 } else {
1330 ResetSharedWritersProcessPendingQueue(entry);
1331 }
1332 }
1333
1334 void HttpCache::SharedWriters::FinalizeDoomedWriter(bool& out_destroy_entry) {
1335 if (doomed_writer_) {
1336 DCHECK_EQ(doomed_writer_.get(), current_writer_);
1337 all_writers_.erase(current_writer_);
1338 doomed_writer_.reset();
1339 current_writer_ = nullptr;
1340 out_destroy_entry = destroy_entry_;
1341 }
1342 }
1343
1344 void HttpCache::NetworkReadFailedSharedWriters(Transaction* trans,
1345 ActiveEntry* entry,
1346 int result) {
1347 entry->shared_writers->OnNetworkReadFailure(trans, result);
1348
1349 DCHECK(entry->shared_writers->empty());
1350 entry->shared_writers.reset();
1351
1352 // If entry->writer was set from the SharedWriters' validating_trans_, let it
1353 // run else process pending queue.
1354 if (!entry->writer) {
1355 ProcessPendingQueue(entry);
1356 }
1357 }
1358
1359 void HttpCache::SharedWriters::OnNetworkReadFailure(const Transaction* trans,
1360 int result) {
1361 DCHECK_EQ(trans, current_writer_);
1362
1363 // Now we need to take care of all the transactions in SharedWriters and
1364 // delete SharedWriters.
1365 ResetAndRemoveCurrentWriter();
1366
1367 // Notify waiting_writers_ of the failure. Tasks will be posted for all the
1368 // transactions.
1369 ProcessWaitingWriters(result);
1370
1371 // Idle readers should know to fail when Read is invoked by their consumers.
1372 SetIdleWritersFailState();
1373 DCHECK(all_writers_.empty());
1374
1375 // If there is a transaction validating currently, let it continue reading
1376 // from the network without attempting to write to the cache.
1377 if (validating_trans_) {
1378 DCHECK(!entry_->writer);
1379 entry_->writer = validating_trans_;
1380 validating_trans_->ResetShared(true);
1381 validating_trans_ = nullptr;
1382 }
1383 MoveToPendingQueue();
1384 }
1385
1386 void HttpCache::SharedWriters::ResetAndRemoveCurrentWriter(
1387 bool continue_network_reading) {
1388 current_writer_->ResetShared(continue_network_reading);
1389 all_writers_.erase(current_writer_);
1390 ResetCurrentWriter();
1391 }
1392
1393 void HttpCache::SharedWriters::ResetCurrentWriter() {
1394 // doomed_writer_ will be destroyed after cache transaction is done with its
1395 // processing.
1396 if (doomed_writer_) {
1397 DCHECK_EQ(doomed_writer_.get(), current_writer_);
1398 current_writer_->SetFinalizeDoomed();
1399 } else {
1400 current_writer_ = nullptr;
1401 }
1402 }
1403
1404 bool HttpCache::SharedWriters::empty() {
1405 if (doomed_writer_)
1406 return false;
1407 int count = all_writers_.size() + waiting_for_validation_.size() +
1408 (validating_trans_ ? 1 : 0);
1409 return count ? false : true;
1410 }
1411
1412 void HttpCache::SharedWriters::SetIdleWritersFailState() {
1413 // Since this is only for idle transactions, all waiting_writers_ and
1414 // current_writer_ should be empty.
1415 DCHECK(waiting_writers_.empty());
1416 DCHECK(!current_writer_);
1417
1418 for (auto trans : all_writers_) {
1419 trans->SetSharedWritingFailState();
1420 trans->ResetShared();
1421 }
1422
1423 all_writers_.clear();
1424 }
1425
1426 bool HttpCache::SharedWriters::AddTransaction(Transaction* transaction) {
1427 transaction->SetShared();
1428
1429 if (!validating_trans_) {
1430 validating_trans_ = transaction;
1431 return true;
1432 } else {
1433 waiting_for_validation_.push_back(transaction);
1434 return false;
1435 }
1436 }
1437
1438 void HttpCache::ValidationMatchSharedWriters(Transaction* transaction,
1439 RequestPriority priority,
1440 ActiveEntry* entry) {
1441 entry->shared_writers->OnValidationMatch(transaction, priority);
1442 if (entry->shared_writers->empty()) {
1443 entry->shared_writers.reset();
1444 ProcessPendingQueue(entry);
1445 }
1446 }
1447
1448 void HttpCache::SharedWriters::OnValidationMatch(Transaction* transaction,
1449 RequestPriority priority) {
1450 DCHECK_EQ(validating_trans_, transaction);
1451 validating_trans_ = nullptr;
1452
1453 ValidationDoneContinue(transaction, priority);
1454 }
1455
1456 void HttpCache::SharedWriters::ValidationDoneContinue(
1457 Transaction* transaction,
1458 RequestPriority priority) {
1459 validating_trans_ = nullptr;
1460 if (priority > priority_) {
1461 network_trans_->SetPriority(priority);
1462 priority_ = priority;
1463 }
1464 all_writers_.insert(transaction);
1465 transaction->SetShared();
1466 ProcessFirstWaitingValidation();
1467 }
1468
1469 std::unique_ptr<HttpTransaction> HttpCache::ValidationNoMatchSharedWriters(
1470 const std::string& key,
1471 Transaction* transaction,
1472 std::unique_ptr<HttpTransaction> network_trans,
1473 RequestPriority priority,
1474 ActiveEntry* entry) {
1475 // This will either return the ownership of the network transaction so that
1476 // this transaction can continue reading from the network or not, if this is
1477 // the only transaction in SharedWriters.
1478 std::unique_ptr<HttpTransaction> nw_trans =
1479 entry->shared_writers->OnValidationNoMatch(
1480 transaction, std::move(network_trans), priority);
1481 if (nw_trans) {
1482 DCHECK(!transaction->shared());
1483 DoomActiveEntry(key);
1484 // We need to do something about these pending entries, which now need to
1485 // be added to a new entry.
1486 while (!entry->pending_queue.empty()) {
1487 // ERR_CACHE_RACE causes the transaction to restart the whole process.
1488 entry->pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
1489 entry->pending_queue.pop_front();
1490 }
1491 }
1492 return nw_trans;
1493 }
1494
1495 std::unique_ptr<HttpTransaction> HttpCache::SharedWriters::OnValidationNoMatch(
1496 Transaction* transaction,
1497 std::unique_ptr<HttpTransaction> network_trans,
1498 RequestPriority priority) {
1499 DCHECK_EQ(validating_trans_, transaction);
1500 // If there is no transaction in all_writers_, its ok to rewrite the entry
1501 // response.
1502 if (all_writers_.empty()) {
1503 network_trans_ = std::move(network_trans);
1504 ValidationDoneContinue(transaction, priority);
1505 return std::unique_ptr<HttpTransaction>();
1506 }
1507
1508 transaction->ResetShared();
1509 validating_trans_ = nullptr;
1510 MoveToPendingQueue();
1511 return network_trans;
1512 }
1513
1514 int HttpCache::SharedWriters::Read(IOBuffer* buf,
1515 int buf_len,
1516 const CompletionCallback& callback,
1517 Transaction* transaction,
1518 bool& read_in_progress) {
1519 // If another transaction is already reading from the network, then this
1520 // transaction waits for the read to complete and reads from the cache
1521 // instead.
1522 if (current_writer_) {
1523 WaitingWriter waiting_writer(transaction, buf, buf_len);
1524 waiting_writers_.push_back(waiting_writer);
1525 read_in_progress = true;
1526 return ERR_IO_PENDING;
1527 }
1528 current_writer_ = transaction;
1529 return network_trans_->Read(buf, buf_len, callback);
1530 }
1531
1532 void HttpCache::SharedWriters::OnNetworkReadSuccess(const Transaction* trans,
1533 scoped_refptr<IOBuffer> buf,
1534 int len) {
1535 DCHECK_EQ(trans, current_writer_);
1536 // Save the network read data in all the waiting transactions' read buffers.
1537 for (auto it = waiting_writers_.begin(); it != waiting_writers_.end(); it++) {
1538 it->write_len = std::min(it->read_buf_len, len);
1539 memcpy(it->read_buf->data(), buf->data(), it->write_len);
1540 }
1541 }
1542
1543 void HttpCache::CacheWriteSuccessSharedWriters(Transaction* trans,
1544 ActiveEntry* entry,
1545 int result) {
1546 entry->shared_writers->OnCacheWriteSuccess(trans, result);
1547
1548 if (result > 0) // not the end of response.
1549 return;
1550
1551 ResetSharedWritersProcessPendingQueue(entry);
1552 }
1553
1554 void HttpCache::DoneReadingSharedWriters(Transaction* trans,
1555 ActiveEntry* entry) {
1556 entry->shared_writers->DoneReading(trans);
1557
1558 ResetSharedWritersProcessPendingQueue(entry);
1559 }
1560
1561 void HttpCache::SharedWriters::DoneReading(Transaction* trans) {
1562 // If current_writer_ is set, then wait for current_writer_ to detect the end
1563 // of stream.
1564 if (current_writer_) {
1565 return;
1566 }
1567 DCHECK(waiting_writers_.empty());
1568 RemoveIdleWriter(trans);
1569 // If there is a transaction validating currently, return.
1570 if (validating_trans_) {
1571 return;
1572 }
1573
1574 // Else empty the SharedWriters object.
1575 MoveIdleWritersToReaders();
1576 DCHECK(all_writers_.empty());
1577
1578 MoveToPendingQueue();
1579 }
1580
1581 void HttpCache::SharedWriters::RemoveIdleWriter(Transaction* trans) {
1582 // The transaction should be part of all_writers.
1583 auto it = all_writers_.find(trans);
1584 DCHECK(it != all_writers_.end());
1585 all_writers_.erase(trans);
1586 trans->ResetShared();
1587 }
1588
1589 void HttpCache::ResetSharedWritersProcessPendingQueue(ActiveEntry* entry) {
1590 if (entry->shared_writers->empty()) {
1591 entry->shared_writers.reset();
1592 DCHECK(!entry->writer);
1593 ProcessPendingQueue(entry);
1594 }
1595 }
1596
1597 void HttpCache::SharedWriters::OnCacheWriteSuccess(const Transaction* trans,
1598 int result) {
1599 DCHECK_EQ(trans, current_writer_);
1600
1601 // Notify waiting_writers_. Tasks will be posted for all the
1602 // transactions.
1603 ProcessWaitingWriters(result);
1604
1605 if (result > 0) { // not the end of response
1606 ResetCurrentWriter();
1607 return;
1608 }
1609
1610 ResetAndRemoveCurrentWriter();
1611
1612 // If there is a transaction validating currently, change state and return.
1613 if (validating_trans_) {
1614 return;
1615 }
1616
1617 // Else empty the SharedWriters object.
1618 MoveIdleWritersToReaders();
1619 DCHECK(all_writers_.empty());
1620
1621 MoveToPendingQueue();
1622 }
1623
1624 void HttpCache::SharedWriters::MoveIdleWritersToReaders() {
1625 // Should be invoked after waiting_writers_ are all processed.
1626 DCHECK(waiting_writers_.empty());
1627 for (auto idle_writer : all_writers_) {
1628 entry_->readers.insert(idle_writer);
1629 idle_writer->ResetShared(false, true);
1630 }
1631 all_writers_.clear();
1632 }
1633
1634 void HttpCache::DoomCurrentSharedWriter(std::unique_ptr<HttpTransaction> trans,
1635 ActiveEntry* entry) {
1636 entry->shared_writers->DoomCurrentWriter(std::move(trans));
1637 ResetSharedWritersProcessPendingQueue(entry);
1638 }
1639
1640 void HttpCache::SharedWriters::RemoveWaitingWriter(Transaction* trans) {
1641 auto it = waiting_writers_.begin();
1642 for (; it != waiting_writers_.end(); it++) {
1643 if (trans == it->transaction) {
1644 waiting_writers_.erase(it);
1645 all_writers_.erase(trans);
1646 trans->ResetShared();
1647 break;
1648 }
1649 }
1650
1651 // If a waiting_writer_ existed, there should have been a current_writer_.
1652 DCHECK(current_writer_);
1653 }
1654
1655 void HttpCache::RemoveIdleSharedWriter(Transaction* trans,
1656 ActiveEntry* entry,
1657 bool cancel) {
1658 entry->shared_writers->RemoveIdleWriter(trans);
1659
1660 bool success = false;
1661 if (cancel) {
1662 success = trans->AddTruncatedFlag();
1663 }
1664 if (entry->shared_writers->empty()) {
1665 if (!success) {
1666 entry->shared_writers.reset();
1667 DestroyEntryAndRestartPendingQueueTxns(entry);
1668 } else {
1669 ResetSharedWritersProcessPendingQueue(entry);
1670 }
1671 }
1672 }
1673
1674 void HttpCache::RemoveValidatingTransSharedWriters(Transaction* trans,
1675 ActiveEntry* entry) {
1676 entry->shared_writers->RemoveValidatingTransaction(trans);
1677 ResetSharedWritersProcessPendingQueue(entry);
1678 }
1679
1680 void HttpCache::SharedWriters::RemoveValidatingTransaction(Transaction* trans) {
1681 DCHECK_EQ(validating_trans_, trans);
1682 validating_trans_ = nullptr;
1683 trans->ResetShared();
1684 ProcessFirstWaitingValidation();
1685 return;
1686 }
1687
1688 bool HttpCache::SharedWriters::RemoveWaitingTransaction(Transaction* trans) {
1689 auto it = std::find(waiting_for_validation_.begin(),
1690 waiting_for_validation_.end(), trans);
1691 if (it != waiting_for_validation_.end()) {
1692 trans->ResetShared();
1693 waiting_for_validation_.erase(it);
1694 return true;
1695 }
1696 return false;
1697 }
1698
1699 void HttpCache::SharedWriters::DoomCurrentWriter(
1700 std::unique_ptr<HttpTransaction> trans) {
1701 DCHECK_EQ(current_writer_, trans.get());
1702 if (waiting_writers_.empty() && all_writers_.empty()) {
1703 ResetAndRemoveCurrentWriter();
1704 } else {
1705 doomed_writer_ = std::move(trans);
1706 }
1707 }
1708
1709 void HttpCache::SharedWriters::ProcessFirstWaitingValidation() {
1710 if (!waiting_for_validation_.empty() || validating_trans_)
1711 base::ThreadTaskRunnerHandle::Get()->PostTask(
1712 FROM_HERE,
1713 base::Bind(&HttpCache::SharedWriters::OnProcessFirstWaitingValidation,
1714 weak_factory_.GetWeakPtr()));
1715 }
1716
1717 void HttpCache::SharedWriters::OnProcessFirstWaitingValidation() {
1718 if (waiting_for_validation_.empty() && !validating_trans_)
1719 return;
1720
1721 Transaction* trans = nullptr;
1722 if (validating_trans_) {
1723 trans = validating_trans_;
1724 } else {
1725 trans = waiting_for_validation_.front();
1726 waiting_for_validation_.erase(waiting_for_validation_.begin());
1727 validating_trans_ = trans;
1728 }
1729 trans->io_callback().Run(OK);
1730 }
1731
1732 void HttpCache::SharedWriters::ProcessWaitingWriters(int result) {
1733 for (auto it = waiting_writers_.begin(); it != waiting_writers_.end(); it++) {
1734 Transaction* transaction = it->transaction;
1735
1736 if (result > 0) { // success
1737 // Fill result with the length of buffer filled for this transaction which
1738 // may be different from the transaction that actually wrote to the cache
1739 // based on the buffer size.
1740 // If cache write is completed, then result will be 0.
1741 // That will lead to the transaction calling DoneWritingToEntry().
1742 result = it->write_len;
1743 } else {
1744 // If its response completion or failure, this transaction needs to be
1745 // removed.
1746 transaction->ResetShared();
1747 all_writers_.erase(transaction);
1748 }
1749
1750 // Post task to notify transaction.
1751 base::ThreadTaskRunnerHandle::Get()->PostTask(
1752 FROM_HERE, base::Bind(&HttpCache::NotifyTransaction,
1753 cache_->GetWeakPtr(), transaction, result));
1754 }
1755
1756 waiting_writers_.clear();
1757 }
1758
1759 void HttpCache::NotifyTransaction(Transaction* transaction, int result) {
1760 DCHECK(transaction);
1761 transaction->io_callback().Run(result);
1762 }
1763
1764 void HttpCache::SharedWriters::MoveFromPendingQueue() {
1765 auto it = entry_->pending_queue.begin();
1766 while (it != entry_->pending_queue.end()) {
1767 Transaction* transaction = *it;
1768 if (transaction->IsEligibleForSharedWriting()) {
1769 transaction->SetShared();
1770 waiting_for_validation_.push_back(transaction);
1771 it = entry_->pending_queue.erase(it);
1772 } else {
1773 ++it;
1774 }
1775 }
1776 }
1777
1778 void HttpCache::SharedWriters::MoveToPendingQueue() {
1779 // For maintaining the order of the transactions as they arrived, append
1780 // these to the front of the pending_queue. Note that the order is preserved
1781 // only among the transactions that are eligible for sharing. For others, they
1782 // may have arrived earlier but may be processed later which is fair since
1783 // they have to anyways wait till the entry is written to the cache.
1784 while (!waiting_for_validation_.empty()) {
1785 Transaction* trans = waiting_for_validation_.back();
1786 trans->ResetShared(true);
1787 entry_->pending_queue.push_front(trans);
1788 waiting_for_validation_.pop_back();
1789 }
1790 }
1791
1792 int HttpCache::SharedWriters::GetTotalReceivedBytes() const {
1793 DCHECK(network_trans_);
1794 return network_trans_->GetTotalReceivedBytes();
1795 }
1796
1797 int HttpCache::SharedWriters::GetTotalSentBytes() const {
1798 DCHECK(network_trans_);
1799 return network_trans_->GetTotalSentBytes();
1800 }
1801
1802 LoadState HttpCache::SharedWriters::GetLoadState() const {
1803 DCHECK(network_trans_);
1804 return network_trans_->GetLoadState();
1805 }
1806
1807 bool HttpCache::SharedWriters::GetFullRequestHeaders(
1808 HttpRequestHeaders* headers) const {
1809 DCHECK(network_trans_);
1810 return network_trans_->GetFullRequestHeaders(headers);
1811 }
1812
1813 bool HttpCache::SharedWriters::GetLoadTimingInfo(
1814 LoadTimingInfo* load_timing_info) const {
1815 DCHECK(network_trans_);
1816 return network_trans_->GetLoadTimingInfo(load_timing_info);
1817 }
1818
1819 bool HttpCache::SharedWriters::GetRemoteEndpoint(IPEndPoint* endpoint) const {
1820 DCHECK(network_trans_);
1821 return network_trans_->GetRemoteEndpoint(endpoint);
1822 }
1823
1824 void HttpCache::SharedWriters::PopulateNetErrorDetails(
1825 NetErrorDetails* details) const {
1826 DCHECK(network_trans_);
1827 return network_trans_->PopulateNetErrorDetails(details);
1828 }
1829
1830 void HttpCache::SharedWriters::SetPriority(RequestPriority priority) {
1831 DCHECK(network_trans_);
1832 network_trans_->SetPriority(priority_);
1833 }
1834
1835 void HttpCache::SharedWriters::SetWebSocketHandshakeStreamCreateHelper(
1836 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
1837 DCHECK(network_trans_);
1838 return network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
1839 }
1840
1841 int HttpCache::SharedWriters::ResumeNetworkStart() {
1842 DCHECK(network_trans_);
1843 return network_trans_->ResumeNetworkStart();
1844 }
1845
1846 void HttpCache::SharedWriters::GetConnectionAttempts(
1847 ConnectionAttempts* out) const {
1848 DCHECK(network_trans_);
1849 network_trans_->GetConnectionAttempts(out);
1850 }
1851
1852 HttpCache::SharedWriters::WaitingWriter::WaitingWriter(
1853 Transaction* trans,
1854 scoped_refptr<IOBuffer> buf,
1855 int len)
1856 : transaction(trans), read_buf(buf), read_buf_len(len), write_len(0) {}
1857
1858 HttpCache::SharedWriters::WaitingWriter::~WaitingWriter() {}
1859
1860 HttpCache::SharedWriters::WaitingWriter::WaitingWriter(const WaitingWriter&) =
1861 default;
1862
1160 } // namespace net 1863 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698