OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |