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

Unified Diff: net/http/http_cache_transaction.cc

Issue 464028: Http cache: Second pass to move the HttpCache::Transaction... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years 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') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_cache_transaction.cc
===================================================================
--- net/http/http_cache_transaction.cc (revision 33833)
+++ net/http/http_cache_transaction.cc (working copy)
@@ -101,6 +101,7 @@
request_(NULL),
cache_(cache->AsWeakPtr()),
entry_(NULL),
+ new_entry_(NULL),
network_trans_(NULL),
callback_(NULL),
mode_(NONE),
@@ -156,6 +157,9 @@
// Ensure that we only have one asynchronous call at a time.
DCHECK(!callback_);
+ DCHECK(!reading_);
+ DCHECK(!network_trans_.get());
+ DCHECK(!entry_);
if (!cache_)
return ERR_UNEXPECTED;
@@ -167,7 +171,7 @@
if (!ShouldPassThrough()) {
cache_key_ = cache_->GenerateCacheKey(request);
- // requested cache access mode
+ // Requested cache access mode.
if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
mode_ = READ;
} else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
@@ -188,7 +192,7 @@
}
}
- // if must use cache, then we must fail. this can happen for back/forward
+ // If must use cache, then we must fail. This can happen for back/forward
// navigations to a page generated via a form post.
if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
return ERR_CACHE_MISS;
@@ -201,7 +205,7 @@
rv = AddToEntry();
}
- // setting this here allows us to check for the existance of a callback_ to
+ // Setting this here allows us to check for the existance of a callback_ to
// determine if we are still inside Start.
if (rv == ERR_IO_PENDING)
callback_ = callback;
@@ -213,7 +217,7 @@
CompletionCallback* callback) {
DCHECK(callback);
- // ensure that we only have one asynchronous call at a time.
+ // Ensure that we only have one asynchronous call at a time.
DCHECK(!callback_);
if (!cache_)
@@ -232,7 +236,7 @@
CompletionCallback* callback) {
DCHECK(callback);
- // ensure that we only have one asynchronous call at a time.
+ // Ensure that we only have one asynchronous call at a time.
DCHECK(!callback_);
if (!cache_)
@@ -350,60 +354,128 @@
}
int HttpCache::Transaction::AddToEntry() {
- ActiveEntry* entry = NULL;
+ next_state_ = STATE_INIT_ENTRY;
+ return DoLoop(OK);
+}
+int HttpCache::Transaction::DoInitEntry() {
+ DCHECK(!new_entry_);
+
if (!cache_)
return ERR_UNEXPECTED;
if (mode_ == WRITE) {
- cache_->DoomEntry(cache_key_);
- } else {
- entry = cache_->FindActiveEntry(cache_key_);
- if (!entry) {
- LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
- entry = cache_->OpenEntry(cache_key_);
- LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
- if (!entry) {
- if (mode_ == READ_WRITE) {
- mode_ = WRITE;
- } else if (mode_ == UPDATE) {
- // There is no cache entry to update; proceed without caching.
- mode_ = NONE;
- return BeginNetworkRequest();
- } else {
- if (cache_->mode() == PLAYBACK)
- DLOG(INFO) << "Playback Cache Miss: " << request_->url;
+ next_state_ = STATE_DOOM_ENTRY;
+ return OK;
+ }
- // entry does not exist, and not permitted to create a new entry, so
- // we must fail.
- return HandleResult(ERR_CACHE_MISS);
- }
- }
- }
+ new_entry_ = cache_->FindActiveEntry(cache_key_);
+ if (!new_entry_) {
+ next_state_ = STATE_OPEN_ENTRY;
+ return OK;
}
if (mode_ == WRITE) {
- DCHECK(!entry);
- LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
- entry = cache_->CreateEntry(cache_key_);
- LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
- if (!entry) {
- DLOG(WARNING) << "unable to create cache entry";
- mode_ = NONE;
- if (partial_.get())
- partial_->RestoreHeaders(&custom_request_->extra_headers);
- return BeginNetworkRequest();
- }
+ next_state_ = STATE_CREATE_ENTRY;
+ return OK;
}
+ next_state_ = STATE_ADD_TO_ENTRY;
+ return OK;
+}
+int HttpCache::Transaction::DoDoomEntry() {
+ next_state_ = STATE_DOOM_ENTRY_COMPLETE;
+ cache_->DoomEntry(cache_key_);
+ return OK;
+}
+
+int HttpCache::Transaction::DoDoomEntryComplete() {
+ next_state_ = STATE_CREATE_ENTRY;
+ return OK;
+}
+
+int HttpCache::Transaction::DoOpenEntry() {
+ DCHECK(!new_entry_);
+ next_state_ = STATE_OPEN_ENTRY_COMPLETE;
+ LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
+ new_entry_ = cache_->OpenEntry(cache_key_);
+ return OK;
+}
+
+int HttpCache::Transaction::DoOpenEntryComplete() {
+ LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
+ if (new_entry_) {
+ next_state_ = STATE_ADD_TO_ENTRY;
+ return OK;
+ }
+
+ if (mode_ == READ_WRITE) {
+ mode_ = WRITE;
+ next_state_ = STATE_CREATE_ENTRY;
+ return OK;
+ }
+ if (mode_ == UPDATE) {
+ // There is no cache entry to update; proceed without caching.
+ mode_ = NONE;
+ next_state_ = STATE_SEND_REQUEST;
+ return OK;
+ }
+ if (cache_->mode() == PLAYBACK)
+ DLOG(INFO) << "Playback Cache Miss: " << request_->url;
+
+ // The entry does not exist, and we are not permitted to create a new entry,
+ // so we must fail.
+ return ERR_CACHE_MISS;
+}
+
+int HttpCache::Transaction::DoCreateEntry() {
+ DCHECK(!new_entry_);
+ next_state_ = STATE_CREATE_ENTRY_COMPLETE;
+ LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
+ new_entry_ = cache_->CreateEntry(cache_key_);
+ return OK;
+}
+
+int HttpCache::Transaction::DoCreateEntryComplete() {
+ LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
+ next_state_ = STATE_ADD_TO_ENTRY;
+ if (!new_entry_) {
+ // We have a race here: Maybe we failed to open the entry and decided to
+ // create one, but by the time we called create, another transaction already
+ // created the entry. If we want to eliminate this issue, we need an atomic
+ // OpenOrCreate() method exposed by the disk cache.
+ DLOG(WARNING) << "Unable to create cache entry";
+ mode_ = NONE;
+ if (partial_.get())
+ partial_->RestoreHeaders(&custom_request_->extra_headers);
+ next_state_ = STATE_SEND_REQUEST;
+ }
+ return OK;
+}
+
+int HttpCache::Transaction::DoAddToEntry() {
+ DCHECK(new_entry_);
LoadLog::BeginEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING);
- return cache_->AddTransactionToEntry(entry, this);
+ int rv = cache_->AddTransactionToEntry(new_entry_, this);
+ new_entry_ = NULL;
+ return rv;
}
int HttpCache::Transaction::EntryAvailable(ActiveEntry* entry) {
LoadLog::EndEvent(load_log_, LoadLog::TYPE_HTTP_CACHE_WAITING);
+ entry_ = entry;
+ next_state_ = STATE_ENTRY_AVAILABLE;
+ if (new_entry_) {
+ // We are inside AddTransactionToEntry() so avoid reentering DoLoop().
+ DCHECK_EQ(new_entry_, entry);
+ return OK;
+ }
+ return DoLoop(OK);
+}
+
+int HttpCache::Transaction::DoEntryAvailable() {
// We now have access to the cache entry.
//
// o if we are the writer for the transaction, then we can start the network
@@ -421,8 +493,8 @@
// the cache entry, and check if the request headers define a validation
// request.
//
+ DCHECK(!new_entry_);
int rv;
- entry_ = entry;
switch (mode_) {
case READ:
rv = BeginCacheRead();
@@ -430,7 +502,8 @@
case WRITE:
if (partial_.get())
partial_->RestoreHeaders(&custom_request_->extra_headers);
- rv = BeginNetworkRequest();
+ next_state_ = STATE_SEND_REQUEST;
+ rv = OK;
break;
case READ_WRITE:
rv = BeginPartialCacheValidation();
@@ -500,6 +573,46 @@
case STATE_NETWORK_READ_COMPLETE:
rv = DoNetworkReadComplete(rv);
break;
+ case STATE_INIT_ENTRY:
+ DCHECK_EQ(OK, rv);
+ rv = DoInitEntry();
+ break;
+ case STATE_OPEN_ENTRY:
+ DCHECK_EQ(OK, rv);
+ rv = DoOpenEntry();
+ break;
+ case STATE_OPEN_ENTRY_COMPLETE:
+ DCHECK_EQ(OK, rv);
+ rv = DoOpenEntryComplete();
+ break;
+ case STATE_CREATE_ENTRY:
+ DCHECK_EQ(OK, rv);
+ rv = DoCreateEntry();
+ break;
+ case STATE_CREATE_ENTRY_COMPLETE:
+ DCHECK_EQ(OK, rv);
+ rv = DoCreateEntryComplete();
+ break;
+ case STATE_DOOM_ENTRY:
+ DCHECK_EQ(OK, rv);
+ rv = DoDoomEntry();
+ break;
+ case STATE_DOOM_ENTRY_COMPLETE:
+ DCHECK_EQ(OK, rv);
+ rv = DoDoomEntryComplete();
+ break;
+ case STATE_ADD_TO_ENTRY:
+ DCHECK_EQ(OK, rv);
+ rv = DoAddToEntry();
+ break;
+ case STATE_ENTRY_AVAILABLE:
+ DCHECK_EQ(OK, rv);
+ rv = DoEntryAvailable();
+ break;
+ case STATE_PARTIAL_CACHE_VALIDATION:
+ DCHECK_EQ(OK, rv);
+ rv = DoPartialCacheValidation();
+ break;
case STATE_CACHE_QUERY_DATA:
DCHECK_EQ(OK, rv);
rv = DoCacheQueryData();
@@ -681,19 +794,19 @@
// Read response headers.
int rv = ReadResponseInfoFromEntry();
if (rv != OK)
- return HandleResult(rv);
+ return rv;
// We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges.
if (response_.headers->response_code() == 206 || partial_.get()) {
NOTREACHED();
- return HandleResult(ERR_CACHE_MISS);
+ return ERR_CACHE_MISS;
}
// We don't have the whole resource.
if (truncated_)
- return HandleResult(ERR_CACHE_MISS);
+ return ERR_CACHE_MISS;
- return HandleResult(rv);
+ return rv;
}
int HttpCache::Transaction::BeginCacheValidation() {
@@ -710,9 +823,9 @@
// either READ or WRITE mode once we hear back from the server.
if (!ConditionalizeRequest())
mode_ = WRITE;
- return BeginNetworkRequest();
+ next_state_ = STATE_SEND_REQUEST;
}
- return HandleResult(OK);
+ return OK;
}
int HttpCache::Transaction::BeginPartialCacheValidation() {
@@ -721,7 +834,7 @@
int rv = ReadResponseInfoFromEntry();
if (rv != OK) {
DCHECK(rv != ERR_IO_PENDING);
- return HandleResult(rv);
+ return rv;
}
if (response_.headers->response_code() != 206 && !partial_.get() &&
@@ -734,7 +847,7 @@
bool byte_range_requested = partial_.get() != NULL;
if (byte_range_requested) {
next_state_ = STATE_CACHE_QUERY_DATA;
- return DoLoop(OK);
+ return OK;
}
// The request is not for a range, but we have stored just ranges.
partial_.reset(new PartialData());
@@ -776,7 +889,8 @@
DoomPartialEntry(!byte_range_requested);
mode_ = WRITE;
truncated_ = false;
- return AddToEntry();
+ next_state_ = STATE_INIT_ENTRY;
+ return OK;
}
if (!partial_->IsRequestedRangeOK()) {
@@ -784,31 +898,36 @@
invalid_range_ = true;
}
- return ContinuePartialCacheValidation();
+ next_state_ = STATE_PARTIAL_CACHE_VALIDATION;
+ return OK;
}
-int HttpCache::Transaction::ContinuePartialCacheValidation() {
- DCHECK(mode_ == READ_WRITE);
+int HttpCache::Transaction::DoPartialCacheValidation() {
+ if (mode_ == NONE)
+ return OK;
+
int rv = partial_->PrepareCacheValidation(entry_->disk_entry,
&custom_request_->extra_headers);
if (!rv) {
- // Don't invoke the callback before telling the cache we're done.
+ // This is the end of the request.
+ if (mode_ & WRITE) {
+ DoneWritingToEntry(true);
+ } else {
+ cache_->DoneReadingFromEntry(entry_, this);
+ entry_ = NULL;
+ }
return rv;
}
if (rv < 0) {
DCHECK(rv != ERR_IO_PENDING);
- return HandleResult(rv);
+ return rv;
}
if (reading_ && partial_->IsCurrentRangeCached()) {
- rv = ReadFromEntry(read_buf_, read_buf_len_);
-
- // We are supposed to hanlde errors here.
- if (rv < 0 && rv != ERR_IO_PENDING)
- HandleResult(rv);
- return rv;
+ next_state_ = STATE_CACHE_READ_DATA;
+ return OK;
}
return BeginCacheValidation();
@@ -822,7 +941,7 @@
int rv = ReadResponseInfoFromEntry();
if (rv != OK) {
DCHECK(rv != ERR_IO_PENDING);
- return HandleResult(rv);
+ return rv;
}
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) {
@@ -843,7 +962,8 @@
}
}
- return BeginNetworkRequest();
+ next_state_ = STATE_SEND_REQUEST;
+ return OK;
}
int HttpCache::Transaction::BeginNetworkRequest() {
@@ -1261,16 +1381,10 @@
int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
partial_->OnNetworkReadCompleted(result);
- if (result == 0) { // End of file.
- if (mode_ == READ_WRITE) {
- // We need to move on to the next range.
- network_trans_.reset();
- result = ContinuePartialCacheValidation();
- if (result != OK)
- // Any error was already handled.
- return result;
- }
- DoneWritingToEntry(true);
+ if (result == 0) {
+ // We need to move on to the next range.
+ network_trans_.reset();
+ next_state_ = STATE_PARTIAL_CACHE_VALIDATION;
}
return result;
}
@@ -1296,18 +1410,9 @@
int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
partial_->OnCacheReadCompleted(result);
- if (result == 0) { // End of file.
- if (partial_.get() && mode_ == READ_WRITE) {
- // We need to move on to the next range.
- result = ContinuePartialCacheValidation();
- if (result != OK || !entry_) {
- // Any error was already handled.
- return result;
- }
- cache_->ConvertWriterToReader(entry_);
- }
- cache_->DoneReadingFromEntry(entry_, this);
- entry_ = NULL;
+ if (result == 0 && mode_ == READ_WRITE) {
+ // We need to move on to the next range.
+ next_state_ = STATE_PARTIAL_CACHE_VALIDATION;
}
return result;
}
@@ -1420,19 +1525,11 @@
}
if (reading_ && partial_.get()) {
if (network_trans_.get()) {
- next_state_ = STATE_NETWORK_READ_COMPLETE;
- result = ReadFromNetwork(read_buf_, read_buf_len_);
+ next_state_ = STATE_NETWORK_READ;
} else {
- next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
- result = ReadFromEntry(read_buf_, read_buf_len_);
+ next_state_ = STATE_CACHE_READ_DATA;
}
- if (result >= 0 || result == ERR_IO_PENDING) {
- // Keep looping.
- return result;
- } else {
- // Don't keep looping when we return.
- next_state_ = STATE_NONE;
- }
+ result = OK;
} else if (mode_ != NONE && partial_.get()) {
// We are about to return the headers for a byte-range request to the
// user, so let's fix them.
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698