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

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

Issue 11787007: Race Create vs SendRequest on cache misses. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move it into the disk cache Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache.h" 5 #include "net/http/http_cache.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 10
(...skipping 12 matching lines...) Expand all
23 #include "base/pickle.h" 23 #include "base/pickle.h"
24 #include "base/stl_util.h" 24 #include "base/stl_util.h"
25 #include "base/string_number_conversions.h" 25 #include "base/string_number_conversions.h"
26 #include "base/string_util.h" 26 #include "base/string_util.h"
27 #include "base/stringprintf.h" 27 #include "base/stringprintf.h"
28 #include "net/base/io_buffer.h" 28 #include "net/base/io_buffer.h"
29 #include "net/base/load_flags.h" 29 #include "net/base/load_flags.h"
30 #include "net/base/net_errors.h" 30 #include "net/base/net_errors.h"
31 #include "net/base/upload_data_stream.h" 31 #include "net/base/upload_data_stream.h"
32 #include "net/disk_cache/disk_cache.h" 32 #include "net/disk_cache/disk_cache.h"
33 #include "net/disk_cache/pending_create_entry.h"
33 #include "net/http/http_cache_transaction.h" 34 #include "net/http/http_cache_transaction.h"
34 #include "net/http/http_network_layer.h" 35 #include "net/http/http_network_layer.h"
35 #include "net/http/http_network_session.h" 36 #include "net/http/http_network_session.h"
36 #include "net/http/http_request_info.h" 37 #include "net/http/http_request_info.h"
37 #include "net/http/http_response_headers.h" 38 #include "net/http/http_response_headers.h"
38 #include "net/http/http_response_info.h" 39 #include "net/http/http_response_info.h"
39 #include "net/http/http_util.h" 40 #include "net/http/http_util.h"
40 41
41 namespace net { 42 namespace net {
42 43
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 CompletionCallback callback; // BackendCallback. 96 CompletionCallback callback; // BackendCallback.
96 WorkItemList pending_queue; 97 WorkItemList pending_queue;
97 }; 98 };
98 99
99 //----------------------------------------------------------------------------- 100 //-----------------------------------------------------------------------------
100 101
101 // The type of operation represented by a work item. 102 // The type of operation represented by a work item.
102 enum WorkItemOperation { 103 enum WorkItemOperation {
103 WI_CREATE_BACKEND, 104 WI_CREATE_BACKEND,
104 WI_OPEN_ENTRY, 105 WI_OPEN_ENTRY,
105 WI_CREATE_ENTRY,
106 WI_DOOM_ENTRY 106 WI_DOOM_ENTRY
107 }; 107 };
108 108
109 // A work item encapsulates a single request to the backend with all the 109 // A work item encapsulates a single request to the backend with all the
110 // information needed to complete that request. 110 // information needed to complete that request.
111 class HttpCache::WorkItem { 111 class HttpCache::WorkItem {
112 public: 112 public:
113 WorkItem(WorkItemOperation operation, Transaction* trans, ActiveEntry** entry) 113 WorkItem(WorkItemOperation operation, Transaction* trans, ActiveEntry** entry)
114 : operation_(operation), 114 : operation_(operation),
115 trans_(trans), 115 trans_(trans),
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 item->ClearTransaction(); 705 item->ClearTransaction();
706 pending_op->callback.Run(rv); 706 pending_op->callback.Run(rv);
707 } 707 }
708 708
709 return rv; 709 return rv;
710 } 710 }
711 711
712 int HttpCache::CreateEntry(const std::string& key, ActiveEntry** entry, 712 int HttpCache::CreateEntry(const std::string& key, ActiveEntry** entry,
713 Transaction* trans) { 713 Transaction* trans) {
714 DCHECK(!FindActiveEntry(key)); 714 DCHECK(!FindActiveEntry(key));
715 715 disk_cache::Entry* new_entry;
716 WorkItem* item = new WorkItem(WI_CREATE_ENTRY, trans, entry); 716 int rv = disk_cache::PendingCreateEntry(disk_cache_.get(), key, &new_entry);
rvargas (doing something else) 2013/01/23 22:04:09 why is this not calling CreateEntry?. I mean, if y
gavinp 2013/01/24 07:38:10 Good point. And if we want to do A/B tests (and we
717 PendingOp* pending_op = GetPendingOp(key); 717 if (rv == net::OK)
718 if (pending_op->writer) { 718 *entry = ActivateEntry(new_entry);
719 pending_op->pending_queue.push_back(item);
720 return ERR_IO_PENDING;
721 }
722
723 DCHECK(pending_op->pending_queue.empty());
724
725 pending_op->writer = item;
726 pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
727 AsWeakPtr(), pending_op);
728
729 int rv = disk_cache_->CreateEntry(key, &(pending_op->disk_entry),
730 pending_op->callback);
731 if (rv != ERR_IO_PENDING) {
732 item->ClearTransaction();
733 pending_op->callback.Run(rv);
734 }
735
736 return rv; 719 return rv;
737 } 720 }
738 721
739 void HttpCache::DestroyEntry(ActiveEntry* entry) { 722 void HttpCache::DestroyEntry(ActiveEntry* entry) {
740 if (entry->doomed) { 723 if (entry->doomed) {
741 FinalizeDoomedEntry(entry); 724 FinalizeDoomedEntry(entry);
742 } else { 725 } else {
743 DeactivateEntry(entry); 726 DeactivateEntry(entry);
744 } 727 }
745 } 728 }
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 std::string key; 976 std::string key;
994 if (result == OK) { 977 if (result == OK) {
995 if (op == WI_DOOM_ENTRY) { 978 if (op == WI_DOOM_ENTRY) {
996 // Anything after a Doom has to be restarted. 979 // Anything after a Doom has to be restarted.
997 fail_requests = true; 980 fail_requests = true;
998 } else if (item->IsValid()) { 981 } else if (item->IsValid()) {
999 key = pending_op->disk_entry->GetKey(); 982 key = pending_op->disk_entry->GetKey();
1000 entry = ActivateEntry(pending_op->disk_entry); 983 entry = ActivateEntry(pending_op->disk_entry);
1001 } else { 984 } else {
1002 // The writer transaction is gone. 985 // The writer transaction is gone.
1003 if (op == WI_CREATE_ENTRY)
1004 pending_op->disk_entry->Doom();
1005 pending_op->disk_entry->Close(); 986 pending_op->disk_entry->Close();
1006 pending_op->disk_entry = NULL; 987 pending_op->disk_entry = NULL;
1007 fail_requests = true; 988 fail_requests = true;
1008 } 989 }
1009 } 990 }
1010 991
1011 // We are about to notify a bunch of transactions, and they may decide to 992 // We are about to notify a bunch of transactions, and they may decide to
1012 // re-issue a request (or send a different one). If we don't delete 993 // re-issue a request (or send a different one). If we don't delete
1013 // pending_op, the new request will be appended to the end of the list, and 994 // pending_op, the new request will be appended to the end of the list, and
1014 // we'll see it again from this point before it has a chance to complete (and 995 // we'll see it again from this point before it has a chance to complete (and
(...skipping 21 matching lines...) Expand all
1036 entry = FindActiveEntry(key); 1017 entry = FindActiveEntry(key);
1037 if (!entry) 1018 if (!entry)
1038 fail_requests = true; 1019 fail_requests = true;
1039 } 1020 }
1040 1021
1041 if (fail_requests) { 1022 if (fail_requests) {
1042 item->NotifyTransaction(ERR_CACHE_RACE, NULL); 1023 item->NotifyTransaction(ERR_CACHE_RACE, NULL);
1043 continue; 1024 continue;
1044 } 1025 }
1045 1026
1046 if (item->operation() == WI_CREATE_ENTRY) { 1027 item->NotifyTransaction(result, entry);
1047 if (result == OK) {
1048 // A second Create request, but the first request succeeded.
1049 item->NotifyTransaction(ERR_CACHE_CREATE_FAILURE, NULL);
1050 } else {
1051 if (op != WI_CREATE_ENTRY) {
1052 // Failed Open followed by a Create.
1053 item->NotifyTransaction(ERR_CACHE_RACE, NULL);
1054 fail_requests = true;
1055 } else {
1056 item->NotifyTransaction(result, entry);
1057 }
1058 }
1059 } else {
1060 if (op == WI_CREATE_ENTRY && result != OK) {
1061 // Failed Create followed by an Open.
1062 item->NotifyTransaction(ERR_CACHE_RACE, NULL);
1063 fail_requests = true;
1064 } else {
1065 item->NotifyTransaction(result, entry);
1066 }
1067 }
1068 } 1028 }
1069 } 1029 }
1070 1030
1071 // static 1031 // static
1072 void HttpCache::OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache, 1032 void HttpCache::OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache,
1073 PendingOp* pending_op, 1033 PendingOp* pending_op,
1074 int rv) { 1034 int rv) {
1075 if (cache.get()) { 1035 if (cache.get()) {
1076 cache->OnIOComplete(rv, pending_op); 1036 cache->OnIOComplete(rv, pending_op);
1077 } else { 1037 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 building_backend_ = false; 1076 building_backend_ = false;
1117 DeletePendingOp(pending_op); 1077 DeletePendingOp(pending_op);
1118 } 1078 }
1119 1079
1120 // The cache may be gone when we return from the callback. 1080 // The cache may be gone when we return from the callback.
1121 if (!item->DoCallback(result, backend)) 1081 if (!item->DoCallback(result, backend))
1122 item->NotifyTransaction(result, NULL); 1082 item->NotifyTransaction(result, NULL);
1123 } 1083 }
1124 1084
1125 } // namespace net 1085 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698