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

Unified Diff: net/http/http_cache_transaction.cc

Issue 2953983003: Adds cache lock timeout handling after finishing headers phase. (Closed)
Patch Set: dcheck added Created 3 years, 6 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_cache_transaction.cc
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 29d040c885adf1ad9706a4754694155bf9755246..6be3d8711dc70b41ae8a3c269ff74d60e7cd61d5 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -168,6 +168,7 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache)
vary_mismatch_(false),
couldnt_conditionalize_request_(false),
bypass_lock_for_test_(false),
+ bypass_lock_after_headers_for_test_(false),
fail_conditionalization_for_test_(false),
io_buf_len_(0),
read_offset_(0),
@@ -853,7 +854,7 @@ int HttpCache::Transaction::DoLoop(int result) {
rv = DoCacheReadMetadataComplete(rv);
break;
case STATE_HEADERS_PHASE_CANNOT_PROCEED:
- rv = DoHeadersPhaseCannotProceed();
+ rv = DoHeadersPhaseCannotProceed(rv);
break;
case STATE_FINISH_HEADERS:
rv = DoFinishHeaders(rv);
@@ -923,6 +924,10 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) {
result);
cache_pending_ = false;
+ // Reset mode_ that might get set in this function. This is done because this
+ // function can be invoked multiple times for a transaction.
+ mode_ = NONE;
+
if (!ShouldPassThrough()) {
cache_key_ = cache_->GenerateCacheKey(request_);
@@ -1131,40 +1136,46 @@ int HttpCache::Transaction::DoAddToEntry() {
DCHECK(entry_lock_waiting_since_.is_null());
entry_lock_waiting_since_ = TimeTicks::Now();
int rv = cache_->AddTransactionToEntry(new_entry_, this);
- if (rv == ERR_IO_PENDING) {
- if (bypass_lock_for_test_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
- weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
- } else {
- int timeout_milliseconds = 20 * 1000;
- if (partial_ && new_entry_->writer &&
- new_entry_->writer->range_requested_) {
- // Quickly timeout and bypass the cache if we're a range request and
- // we're blocked by the reader/writer lock. Doing so eliminates a long
- // running issue, http://crbug.com/31014, where two of the same media
- // resources could not be played back simultaneously due to one locking
- // the cache entry until the entire video was downloaded.
- //
- // Bypassing the cache is not ideal, as we are now ignoring the cache
- // entirely for all range requests to a resource beyond the first. This
- // is however a much more succinct solution than the alternatives, which
- // would require somewhat significant changes to the http caching logic.
- //
- // Allow some timeout slack for the entry addition to complete in case
- // the writer lock is imminently released; we want to avoid skipping
- // the cache if at all possible. See http://crbug.com/408765
- timeout_milliseconds = 25;
- }
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
- weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
- TimeDelta::FromMilliseconds(timeout_milliseconds));
+ if (rv == ERR_IO_PENDING)
+ AddCacheLockTimeoutHandler(new_entry_);
+ return rv;
+}
+
+void HttpCache::Transaction::AddCacheLockTimeoutHandler(ActiveEntry* entry) {
+ DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
+ next_state_ == STATE_FINISH_HEADERS_COMPLETE);
+ if ((bypass_lock_for_test_ && next_state_ == STATE_ADD_TO_ENTRY_COMPLETE) ||
+ (bypass_lock_after_headers_for_test_ &&
+ next_state_ == STATE_FINISH_HEADERS_COMPLETE)) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&HttpCache::Transaction::OnCacheLockTimeout,
+ weak_factory_.GetWeakPtr(), entry_lock_waiting_since_));
+ } else {
+ int timeout_milliseconds = 20 * 1000;
+ if (partial_ && entry->writer && entry->writer->range_requested_) {
+ // Quickly timeout and bypass the cache if we're a range request and
+ // we're blocked by the reader/writer lock. Doing so eliminates a long
+ // running issue, http://crbug.com/31014, where two of the same media
+ // resources could not be played back simultaneously due to one locking
+ // the cache entry until the entire video was downloaded.
+ //
+ // Bypassing the cache is not ideal, as we are now ignoring the cache
+ // entirely for all range requests to a resource beyond the first. This
+ // is however a much more succinct solution than the alternatives, which
+ // would require somewhat significant changes to the http caching logic.
+ //
+ // Allow some timeout slack for the entry addition to complete in case
+ // the writer lock is imminently released; we want to avoid skipping
+ // the cache if at all possible. See http://crbug.com/408765
+ timeout_milliseconds = 25;
}
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&HttpCache::Transaction::OnCacheLockTimeout,
+ weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
+ TimeDelta::FromMilliseconds(timeout_milliseconds));
}
- return rv;
}
int HttpCache::Transaction::DoAddToEntryComplete(int result) {
@@ -1817,7 +1828,7 @@ int HttpCache::Transaction::DoPartialHeadersReceived() {
return OK;
}
-int HttpCache::Transaction::DoHeadersPhaseCannotProceed() {
+int HttpCache::Transaction::DoHeadersPhaseCannotProceed(int result) {
// If its the Start state machine and it cannot proceed due to a cache
// failure, restart this transaction.
DCHECK(!reading_);
@@ -1831,6 +1842,10 @@ int HttpCache::Transaction::DoHeadersPhaseCannotProceed() {
entry_ = nullptr;
+ // Bypass the cache for timeout scenario.
+ if (result == ERR_CACHE_LOCK_TIMEOUT)
+ effective_load_flags_ |= LOAD_DISABLE_CACHE;
+
TransitionToState(STATE_GET_BACKEND);
return OK;
}
@@ -1854,13 +1869,20 @@ int HttpCache::Transaction::DoFinishHeaders(int result) {
// If the transaction needs to wait because another transaction is still
// writing the response body, it will return ERR_IO_PENDING now and the
// io_callback_ will be invoked when the wait is done.
- return cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
+ int rv = cache_->DoneWithResponseHeaders(entry_, this, partial_ != nullptr);
+ if (rv == ERR_IO_PENDING) {
+ DCHECK(entry_lock_waiting_since_.is_null());
+ entry_lock_waiting_since_ = TimeTicks::Now();
+ AddCacheLockTimeoutHandler(entry_);
+ }
+ return rv;
}
int HttpCache::Transaction::DoFinishHeadersComplete(int rv) {
- if (rv == ERR_CACHE_RACE) {
+ entry_lock_waiting_since_ = TimeTicks();
+ if (rv == ERR_CACHE_RACE || rv == ERR_CACHE_LOCK_TIMEOUT) {
TransitionToState(STATE_HEADERS_PHASE_CANNOT_PROCEED);
- return OK;
+ return rv;
}
TransitionToState(STATE_NONE);
@@ -2805,16 +2827,20 @@ int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
return ERR_CACHE_READ_FAILURE;
}
-void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
+void HttpCache::Transaction::OnCacheLockTimeout(base::TimeTicks start_time) {
if (entry_lock_waiting_since_ != start_time)
return;
- DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
+ DCHECK(next_state_ == STATE_ADD_TO_ENTRY_COMPLETE ||
+ next_state_ == STATE_FINISH_HEADERS_COMPLETE);
if (!cache_)
return;
- cache_->RemovePendingTransaction(this);
+ if (next_state_ == STATE_ADD_TO_ENTRY_COMPLETE)
+ cache_->RemovePendingTransaction(this);
+ else
+ cache_->DoneWithEntry(entry_, this, false, partial_ != nullptr);
OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
}
« 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