Chromium Code Reviews| Index: net/http/http_cache_transaction.cc |
| diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
| index 44acc4bcc27ae21a1ad7facc46700e0787c78e66..e7ae6a8e3823795c0e10beb6bcb44296c5daec76 100644 |
| --- a/net/http/http_cache_transaction.cc |
| +++ b/net/http/http_cache_transaction.cc |
| @@ -263,9 +263,10 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache) |
| range_requested_(false), |
| handling_206_(false), |
| cache_pending_(false), |
| - done_reading_(false), |
| + done_writing_(false), |
| vary_mismatch_(false), |
| couldnt_conditionalize_request_(false), |
| + stopped_caching_(false), |
| bypass_lock_for_test_(false), |
| fail_conditionalization_for_test_(false), |
| io_buf_len_(0), |
| @@ -300,7 +301,7 @@ HttpCache::Transaction::~Transaction() { |
| } |
| } |
| - cache_->DoneWithEntry(entry_, this, cancel_request); |
| + DoneWithEntry(cancel_request); |
| } else if (cache_pending_) { |
| cache_->RemovePendingTransaction(this); |
| } |
| @@ -334,7 +335,7 @@ bool HttpCache::Transaction::AddTruncatedFlag() { |
| return false; |
| // We may have received the whole resource already. |
| - if (done_reading_) |
| + if (done_writing_) |
| return true; |
| truncated_ = true; |
| @@ -495,21 +496,12 @@ int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, |
| } |
| void HttpCache::Transaction::StopCaching() { |
| - // We really don't know where we are now. Hopefully there is no operation in |
| - // progress, but nothing really prevents this method to be called after we |
| - // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this |
| - // point because we need the state machine for that (and even if we are really |
| - // free, that would be an asynchronous operation). In other words, keep the |
| - // entry how it is (it will be marked as truncated at destruction), and let |
| - // the next piece of code that executes know that we are now reading directly |
| - // from the net. |
| // TODO(mmenke): This doesn't release the lock on the cache entry, so a |
| // future request for the resource will be blocked on this one. |
| // Fix this. |
| - if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() && |
| - !is_sparse_ && !range_requested_) { |
| - mode_ = NONE; |
| - } |
| + |
| + stopped_caching_ = true; |
| + UpdateTransactionPattern(PATTERN_NOT_COVERED); |
| } |
| bool HttpCache::Transaction::GetFullRequestHeaders( |
| @@ -529,18 +521,7 @@ int64 HttpCache::Transaction::GetTotalReceivedBytes() const { |
| } |
| void HttpCache::Transaction::DoneReading() { |
| - if (cache_.get() && entry_) { |
| - DCHECK_NE(mode_, UPDATE); |
| - if (mode_ & WRITE) { |
| - DoneWritingToEntry(true); |
| - } else if (mode_ & READ) { |
| - // It is necessary to check mode_ & READ because it is possible |
| - // for mode_ to be NONE and entry_ non-NULL with a write entry |
| - // if StopCaching was called. |
| - cache_->DoneReadingFromEntry(entry_, this); |
| - entry_ = NULL; |
| - } |
| - } |
| + DoneWithRequest(); |
| } |
| const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const { |
| @@ -1351,16 +1332,9 @@ int HttpCache::Transaction::DoStartPartialCacheValidation() { |
| } |
| int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { |
| - if (!result) { |
| - // This is the end of the request. |
| - if (mode_ & WRITE) { |
| - DoneWritingToEntry(true); |
| - } else { |
| - cache_->DoneReadingFromEntry(entry_, this); |
| - entry_ = NULL; |
| - } |
| - return result; |
| - } |
| + // This is the end of the request. |
| + if (!result) |
| + return DoneWithRequest(); |
| if (result < 0) |
| return result; |
| @@ -1506,9 +1480,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() { |
| int ret = cache_->DoomEntry(cache_key_, NULL); |
| DCHECK_EQ(OK, ret); |
| } |
| - cache_->DoneWritingToEntry(entry_, true); |
| - entry_ = NULL; |
| - mode_ = NONE; |
| + DoneWritingToEntry(true); |
| } |
| // Invalidate any cached GET with a successful POST. |
| @@ -1643,7 +1615,6 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() { |
| if (request_->method == "HEAD") { |
| // This response is replacing the cached one. |
| DoneWritingToEntry(false); |
| - mode_ = NONE; |
| new_response_ = NULL; |
| return OK; |
| } |
| @@ -1776,9 +1747,19 @@ int HttpCache::Transaction::DoNetworkReadComplete(int result) { |
| if (!cache_.get()) |
| return ERR_UNEXPECTED; |
| - // If there is an error or we aren't saving the data, we are done; just wait |
| - // until the destructor runs to see if we can keep the data. |
| - if (mode_ == NONE || result < 0) |
| + if (result < 0) |
| + return result; |
| + |
| + // Skip writing if StopCaching() has been called. |
| + // |
| + // For partial requests the transaction still needs to update its state. If |
| + // the network transaction being read was conditionalized, the cache |
| + // transaction may need to issue additional network or cache reads to fulfil |
| + // the original request. |
| + if (stopped_caching_ && partial_) |
| + return DoPartialNetworkReadCompleted(result); |
| + |
| + if (mode_ == NONE || stopped_caching_) |
| return result; |
| next_state_ = STATE_CACHE_WRITE_DATA; |
| @@ -1849,12 +1830,9 @@ int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { |
| } |
| int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { |
| - if (entry_) { |
| - if (net_log_.IsCapturing()) { |
| - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, |
| - result); |
| - } |
| - } |
| + if (entry_ && net_log_.IsCapturing()) |
| + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, |
| + result); |
| if (!cache_.get()) |
| return ERR_UNEXPECTED; |
| @@ -1865,11 +1843,11 @@ int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { |
| // We want to ignore errors writing to disk and just keep reading from |
| // the network. |
| result = write_len_; |
| - } else if (!done_reading_ && entry_) { |
| + } else if (!done_writing_ && entry_) { |
| int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); |
| int64 body_size = response_.headers->GetContentLength(); |
| if (body_size >= 0 && body_size <= current_size) |
| - done_reading_ = true; |
| + done_writing_ = true; |
| } |
| if (partial_) { |
| @@ -1883,10 +1861,9 @@ int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { |
| if (result == 0) { |
| // End of file. This may be the result of a connection problem so see if we |
| // have to keep the entry around to be flagged as truncated later on. |
| - if (done_reading_ || !entry_ || partial_ || |
| - response_.headers->GetContentLength() <= 0) { |
| + if (done_writing_ || !entry_ || partial_ || |
| + response_.headers->GetContentLength() <= 0) |
| DoneWritingToEntry(true); |
| - } |
| } |
| return result; |
| @@ -2673,6 +2650,32 @@ int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { |
| return OK; |
| } |
| +int HttpCache::Transaction::DoneWithRequest() { |
| + if (!cache_ || !entry_) |
| + return OK; |
| + |
| + DCHECK_EQ(STATE_NONE, next_state_); |
|
hubbe
2015/07/16 15:56:12
Shouldn't these DCHECKs go first?
asanka
2015/07/16 17:57:00
Moved up.
|
| + DCHECK_NE(mode_, UPDATE); |
| + |
| + if (!(mode_ & WRITE)) { |
| + cache_->DoneReadingFromEntry(entry_, this); |
| + entry_ = NULL; |
| + return OK; |
| + } |
| + |
| + if (stopped_caching_ && !is_sparse_ && !done_writing_ && !entry_->doomed) { |
| + if (CanResume(true)) { |
| + truncated_ = true; |
| + return DoCacheWriteTruncatedResponse(); |
| + } |
| + int ret = cache_->DoomEntry(cache_key_, nullptr); |
| + DCHECK_EQ(OK, ret); |
| + } |
| + |
| + DoneWritingToEntry(true); |
| + return OK; |
| +} |
| + |
| void HttpCache::Transaction::DoneWritingToEntry(bool success) { |
| if (!entry_) |
| return; |
| @@ -2684,6 +2687,13 @@ void HttpCache::Transaction::DoneWritingToEntry(bool success) { |
| mode_ = NONE; // switch to 'pass through' mode |
| } |
| +void HttpCache::Transaction::DoneWithEntry(bool cancel) { |
| + cache_->DoneWithEntry(entry_, this, cancel); |
| + entry_ = nullptr; |
| + is_sparse_ = false; |
| + truncated_ = false; |
| +} |
| + |
| int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { |
| DLOG(ERROR) << "ReadData failed: " << result; |
| const int result_for_histogram = std::max(0, -result); |
| @@ -2702,9 +2712,7 @@ int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { |
| if (restart) { |
| DCHECK(!reading_); |
| DCHECK(!network_trans_.get()); |
| - cache_->DoneWithEntry(entry_, this, false); |
| - entry_ = NULL; |
| - is_sparse_ = false; |
| + DoneWithEntry(false); |
| partial_.reset(); |
| next_state_ = STATE_GET_BACKEND; |
| return OK; |
| @@ -2730,12 +2738,9 @@ void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { |
| DVLOG(2) << "DoomPartialEntry"; |
| int rv = cache_->DoomEntry(cache_key_, NULL); |
| DCHECK_EQ(OK, rv); |
| - cache_->DoneWithEntry(entry_, this, false); |
| - entry_ = NULL; |
| - is_sparse_ = false; |
| - truncated_ = false; |
| + DoneWithEntry(false); |
| if (delete_object) |
| - partial_.reset(NULL); |
| + partial_.reset(); |
| } |
| int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { |