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

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

Issue 2774603003: Doom and create new entry when validation is not a match (Closed)
Patch Set: Added a new state + tests Created 3 years, 8 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_transaction.h ('k') | net/http/http_cache_unittest.cc » ('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_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" // For OS_POSIX 7 #include "build/build_config.h" // For OS_POSIX
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 mode_(NONE), 158 mode_(NONE),
159 original_mode_(NONE), 159 original_mode_(NONE),
160 reading_(false), 160 reading_(false),
161 invalid_range_(false), 161 invalid_range_(false),
162 truncated_(false), 162 truncated_(false),
163 is_sparse_(false), 163 is_sparse_(false),
164 range_requested_(false), 164 range_requested_(false),
165 handling_206_(false), 165 handling_206_(false),
166 cache_pending_(false), 166 cache_pending_(false),
167 done_reading_(false), 167 done_reading_(false),
168 done_headers_create_new_entry_(false),
168 vary_mismatch_(false), 169 vary_mismatch_(false),
169 couldnt_conditionalize_request_(false), 170 couldnt_conditionalize_request_(false),
170 bypass_lock_for_test_(false), 171 bypass_lock_for_test_(false),
171 fail_conditionalization_for_test_(false), 172 fail_conditionalization_for_test_(false),
172 io_buf_len_(0), 173 io_buf_len_(0),
173 read_offset_(0), 174 read_offset_(0),
174 effective_load_flags_(0), 175 effective_load_flags_(0),
175 write_len_(0), 176 write_len_(0),
176 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED), 177 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED),
177 validation_cause_(VALIDATION_CAUSE_UNDEFINED), 178 validation_cause_(VALIDATION_CAUSE_UNDEFINED),
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 case STATE_CREATE_ENTRY_COMPLETE: 748 case STATE_CREATE_ENTRY_COMPLETE:
748 rv = DoCreateEntryComplete(rv); 749 rv = DoCreateEntryComplete(rv);
749 break; 750 break;
750 case STATE_ADD_TO_ENTRY: 751 case STATE_ADD_TO_ENTRY:
751 DCHECK_EQ(OK, rv); 752 DCHECK_EQ(OK, rv);
752 rv = DoAddToEntry(); 753 rv = DoAddToEntry();
753 break; 754 break;
754 case STATE_ADD_TO_ENTRY_COMPLETE: 755 case STATE_ADD_TO_ENTRY_COMPLETE:
755 rv = DoAddToEntryComplete(rv); 756 rv = DoAddToEntryComplete(rv);
756 break; 757 break;
758 case STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE:
759 rv = DoDoneHeadersAddToEntryComplete(rv);
760 break;
757 case STATE_CACHE_READ_RESPONSE: 761 case STATE_CACHE_READ_RESPONSE:
758 DCHECK_EQ(OK, rv); 762 DCHECK_EQ(OK, rv);
759 rv = DoCacheReadResponse(); 763 rv = DoCacheReadResponse();
760 break; 764 break;
761 case STATE_CACHE_READ_RESPONSE_COMPLETE: 765 case STATE_CACHE_READ_RESPONSE_COMPLETE:
762 rv = DoCacheReadResponseComplete(rv); 766 rv = DoCacheReadResponseComplete(rv);
763 break; 767 break;
764 case STATE_TOGGLE_UNUSED_SINCE_PREFETCH: 768 case STATE_TOGGLE_UNUSED_SINCE_PREFETCH:
765 DCHECK_EQ(OK, rv); 769 DCHECK_EQ(OK, rv);
766 rv = DoCacheToggleUnusedSincePrefetch(); 770 rv = DoCacheToggleUnusedSincePrefetch();
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 case ERR_CACHE_RACE: 1109 case ERR_CACHE_RACE:
1106 TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED); 1110 TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
1107 break; 1111 break;
1108 1112
1109 default: 1113 default:
1110 // We have a race here: Maybe we failed to open the entry and decided to 1114 // We have a race here: Maybe we failed to open the entry and decided to
1111 // create one, but by the time we called create, another transaction 1115 // create one, but by the time we called create, another transaction
1112 // already created the entry. If we want to eliminate this issue, we 1116 // already created the entry. If we want to eliminate this issue, we
1113 // need an atomic OpenOrCreate() method exposed by the disk cache. 1117 // need an atomic OpenOrCreate() method exposed by the disk cache.
1114 DLOG(WARNING) << "Unable to create cache entry"; 1118 DLOG(WARNING) << "Unable to create cache entry";
1119 // Change the mode to not write anything to the cache.
Randy Smith (Not in Mondays) 2017/04/11 19:41:07 This comment doesn't really add anything to the co
shivanisha 2017/04/24 17:23:46 Done
1115 mode_ = NONE; 1120 mode_ = NONE;
1121 if (done_headers_create_new_entry_) {
Randy Smith (Not in Mondays) 2017/04/11 19:41:07 Maybe a comment here something like "The headers t
shivanisha 2017/04/24 17:23:46 Comment added and restructured the code.
1122 done_headers_create_new_entry_ = false;
1123 TransitionToState(STATE_CACHE_WRITE_RESPONSE);
1124 return OK;
1125 }
1126
1116 if (partial_) 1127 if (partial_)
1117 partial_->RestoreHeaders(&custom_request_->extra_headers); 1128 partial_->RestoreHeaders(&custom_request_->extra_headers);
1118 TransitionToState(STATE_SEND_REQUEST); 1129 TransitionToState(STATE_SEND_REQUEST);
1119 } 1130 }
1120 return OK; 1131 return OK;
1121 } 1132 }
1122 1133
1123 int HttpCache::Transaction::DoAddToEntry() { 1134 int HttpCache::Transaction::DoAddToEntry() {
1124 TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntry"); 1135 TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntry");
1125 DCHECK(new_entry_); 1136 DCHECK(new_entry_);
1126 cache_pending_ = true; 1137 cache_pending_ = true;
1127 TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);
1128 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY); 1138 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY);
1129 DCHECK(entry_lock_waiting_since_.is_null()); 1139 DCHECK(entry_lock_waiting_since_.is_null());
1140 int rv = cache_->AddTransactionToEntry(new_entry_, this);
1141 DCHECK_EQ(rv, ERR_IO_PENDING);
1142
1143 if (done_headers_create_new_entry_) {
1144 TransitionToState(STATE_DONE_HEADERS_ADD_TO_ENTRY_COMPLETE);
1145 return rv;
1146 }
1147
1148 TransitionToState(STATE_ADD_TO_ENTRY_COMPLETE);
Randy Smith (Not in Mondays) 2017/04/11 19:41:07 The naming makes it clear that these are parallel
shivanisha 2017/04/24 17:23:46 Added a comment in the new Do* function.
1149
1130 entry_lock_waiting_since_ = TimeTicks::Now(); 1150 entry_lock_waiting_since_ = TimeTicks::Now();
1131 int rv = cache_->AddTransactionToEntry(new_entry_, this); 1151 if (bypass_lock_for_test_) {
1132 if (rv == ERR_IO_PENDING) { 1152 base::ThreadTaskRunnerHandle::Get()->PostTask(
1133 if (bypass_lock_for_test_) { 1153 FROM_HERE,
1134 base::ThreadTaskRunnerHandle::Get()->PostTask( 1154 base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
1135 FROM_HERE, 1155 weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
1136 base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout, 1156 } else {
1137 weak_factory_.GetWeakPtr(), entry_lock_waiting_since_)); 1157 int timeout_milliseconds = 20 * 1000;
1138 } else { 1158 if (partial_ && new_entry_->writer &&
1139 int timeout_milliseconds = 20 * 1000; 1159 new_entry_->writer->range_requested_) {
1140 if (partial_ && new_entry_->writer && 1160 // Quickly timeout and bypass the cache if we're a range request and
1141 new_entry_->writer->range_requested_) { 1161 // we're blocked by the reader/writer lock. Doing so eliminates a long
1142 // Quickly timeout and bypass the cache if we're a range request and 1162 // running issue, http://crbug.com/31014, where two of the same media
1143 // we're blocked by the reader/writer lock. Doing so eliminates a long 1163 // resources could not be played back simultaneously due to one locking
1144 // running issue, http://crbug.com/31014, where two of the same media 1164 // the cache entry until the entire video was downloaded.
1145 // resources could not be played back simultaneously due to one locking 1165 //
1146 // the cache entry until the entire video was downloaded. 1166 // Bypassing the cache is not ideal, as we are now ignoring the cache
1147 // 1167 // entirely for all range requests to a resource beyond the first. This
1148 // Bypassing the cache is not ideal, as we are now ignoring the cache 1168 // is however a much more succinct solution than the alternatives, which
1149 // entirely for all range requests to a resource beyond the first. This 1169 // would require somewhat significant changes to the http caching logic.
1150 // is however a much more succinct solution than the alternatives, which 1170 //
1151 // would require somewhat significant changes to the http caching logic. 1171 // Allow some timeout slack for the entry addition to complete in case
1152 // 1172 // the writer lock is imminently released; we want to avoid skipping
1153 // Allow some timeout slack for the entry addition to complete in case 1173 // the cache if at all possible. See http://crbug.com/408765
1154 // the writer lock is imminently released; we want to avoid skipping 1174 timeout_milliseconds = 25;
1155 // the cache if at all possible. See http://crbug.com/408765
1156 timeout_milliseconds = 25;
1157 }
1158 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1159 FROM_HERE,
1160 base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
1161 weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
1162 TimeDelta::FromMilliseconds(timeout_milliseconds));
1163 } 1175 }
1176 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1177 FROM_HERE,
1178 base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
1179 weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
1180 TimeDelta::FromMilliseconds(timeout_milliseconds));
Randy Smith (Not in Mondays) 2017/04/11 19:41:07 Why is this pulled out of the conditional? It loo
shivanisha 2017/04/24 17:23:46 It is not out of the else conditional. This post t
1164 } 1181 }
1165 return rv; 1182 return rv;
1166 } 1183 }
1167 1184
1168 int HttpCache::Transaction::DoAddToEntryComplete(int result) { 1185 int HttpCache::Transaction::DoAddToEntryComplete(int result) {
1169 TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntryComplete"); 1186 TRACE_EVENT0("io", "HttpCacheTransaction::DoAddToEntryComplete");
1170 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY, 1187 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY,
1171 result); 1188 result);
1172 const TimeDelta entry_lock_wait = 1189 const TimeDelta entry_lock_wait =
1173 TimeTicks::Now() - entry_lock_waiting_since_; 1190 TimeTicks::Now() - entry_lock_waiting_since_;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 partial_->RestoreHeaders(&custom_request_->extra_headers); 1235 partial_->RestoreHeaders(&custom_request_->extra_headers);
1219 TransitionToState(STATE_SEND_REQUEST); 1236 TransitionToState(STATE_SEND_REQUEST);
1220 } else { 1237 } else {
1221 // We have to read the headers from the cached entry. 1238 // We have to read the headers from the cached entry.
1222 DCHECK(mode_ & READ_META); 1239 DCHECK(mode_ & READ_META);
1223 TransitionToState(STATE_CACHE_READ_RESPONSE); 1240 TransitionToState(STATE_CACHE_READ_RESPONSE);
1224 } 1241 }
1225 return OK; 1242 return OK;
1226 } 1243 }
1227 1244
1245 int HttpCache::Transaction::DoDoneHeadersAddToEntryComplete(int result) {
Randy Smith (Not in Mondays) 2017/04/11 19:41:07 Comment somewhere as to the context/motivation for
shivanisha 2017/04/24 17:23:46 done.
1246 DCHECK_EQ(result, OK);
1247 DCHECK(mode_ & WRITE);
1248 DCHECK(new_entry_);
1249 DCHECK(response_.headers);
1250
1251 cache_pending_ = false;
1252 entry_ = new_entry_;
1253 done_headers_create_new_entry_ = false;
1254 DCHECK(cache_->CanTransactionWriteResponseHeaders(
1255 entry_, this, response_.headers->response_code()));
1256 TransitionToState(STATE_CACHE_WRITE_RESPONSE);
1257 return OK;
1258 }
1259
1228 int HttpCache::Transaction::DoCacheReadResponse() { 1260 int HttpCache::Transaction::DoCacheReadResponse() {
1229 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadResponse"); 1261 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadResponse");
1230 DCHECK(entry_); 1262 DCHECK(entry_);
1231 TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE); 1263 TransitionToState(STATE_CACHE_READ_RESPONSE_COMPLETE);
1232 1264
1233 io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex); 1265 io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
1234 read_buf_ = new IOBuffer(io_buf_len_); 1266 read_buf_ = new IOBuffer(io_buf_len_);
1235 1267
1236 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO); 1268 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO);
1237 return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(), 1269 return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE); 1738 TransitionToState(STATE_CACHE_WRITE_RESPONSE_COMPLETE);
1707 1739
1708 // Invalidate any current entry with a successful response if this transaction 1740 // Invalidate any current entry with a successful response if this transaction
1709 // cannot write to this entry. This transaction then continues to read from 1741 // cannot write to this entry. This transaction then continues to read from
1710 // the network without writing to the backend. 1742 // the network without writing to the backend.
1711 if (entry_ && response_.headers && 1743 if (entry_ && response_.headers &&
1712 !cache_->CanTransactionWriteResponseHeaders( 1744 !cache_->CanTransactionWriteResponseHeaders(
1713 entry_, this, response_.headers->response_code())) { 1745 entry_, this, response_.headers->response_code())) {
1714 cache_->DoneWritingToEntry(entry_, false, this); 1746 cache_->DoneWritingToEntry(entry_, false, this);
1715 entry_ = nullptr; 1747 entry_ = nullptr;
1716 mode_ = NONE; 1748 next_state_ = STATE_CREATE_ENTRY;
1749 done_headers_create_new_entry_ = true;
1717 return OK; 1750 return OK;
1718 } 1751 }
1719 1752
1720 return WriteResponseInfoToEntry(truncated_); 1753 return WriteResponseInfoToEntry(truncated_);
1721 } 1754 }
1722 1755
1723 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1756 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1724 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete"); 1757 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
1725 TransitionToState(STATE_TRUNCATE_CACHED_DATA); 1758 TransitionToState(STATE_TRUNCATE_CACHED_DATA);
1726 return OnWriteResponseInfoToEntryComplete(result); 1759 return OnWriteResponseInfoToEntryComplete(result);
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after
3104 } 3137 }
3105 3138
3106 void HttpCache::Transaction::TransitionToState(State state) { 3139 void HttpCache::Transaction::TransitionToState(State state) {
3107 // Ensure that the state is only set once per Do* state. 3140 // Ensure that the state is only set once per Do* state.
3108 DCHECK(in_do_loop_); 3141 DCHECK(in_do_loop_);
3109 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; 3142 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
3110 next_state_ = state; 3143 next_state_ = state;
3111 } 3144 }
3112 3145
3113 } // namespace net 3146 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698