diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-22 18:36:19 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-22 18:36:19 +0000 |
commit | 73cae57f1b63a1979790881960ca7615cd779cd0 (patch) | |
tree | 39b12bde09b9210d3e015e741d57f2ec35977000 /net | |
parent | 204e18e9f7fabcbe467c7dcf015fac2ed0567e66 (diff) | |
download | chromium_src-73cae57f1b63a1979790881960ca7615cd779cd0.zip chromium_src-73cae57f1b63a1979790881960ca7615cd779cd0.tar.gz chromium_src-73cae57f1b63a1979790881960ca7615cd779cd0.tar.bz2 |
Http Cache: Convert data writes from sysnchronous to asynchronous.
BUG=21383
TEST=unit tests
(original review for r25873: http://codereview.chromium.org/201065)
Review URL: http://codereview.chromium.org/313013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29792 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_cache.cc | 106 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 74 | ||||
-rw-r--r-- | net/http/http_transaction_unittest.h | 1 |
3 files changed, 138 insertions, 43 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index a2b131f..eee9397 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -163,6 +163,9 @@ class HttpCache::Transaction : public HttpTransaction { cache_read_callback_(new CancelableCompletionCallback<Transaction>( this, &Transaction::OnCacheReadCompleted))), ALLOW_THIS_IN_INITIALIZER_LIST( + cache_write_callback_(new CancelableCompletionCallback<Transaction>( + this, &Transaction::OnCacheWriteCompleted))), + ALLOW_THIS_IN_INITIALIZER_LIST( entry_ready_callback_(new CancelableCompletionCallback<Transaction>( this, &Transaction::OnCacheEntryReady))) { } @@ -309,15 +312,18 @@ class HttpCache::Transaction : public HttpTransaction { // Called to write data to the cache entry. If the write fails, then the // cache entry is destroyed. Future calls to this function will just do - // nothing without side-effect. - void WriteToEntry(int index, int offset, IOBuffer* data, int data_len); + // nothing without side-effect. Returns a network error code. + int WriteToEntry(int index, int offset, IOBuffer* data, int data_len, + CompletionCallback* callback); // Called to write response_ to the cache entry. |truncated| indicates if the // entry should be marked as incomplete. void WriteResponseInfoToEntry(bool truncated); - // Called to append response data to the cache entry. - void AppendResponseDataToEntry(IOBuffer* data, int data_len); + // Called to append response data to the cache entry. Returns a network error + // code. + int AppendResponseDataToEntry(IOBuffer* data, int data_len, + CompletionCallback* callback); // Called to truncate response content in the entry. void TruncateResponseData(); @@ -343,6 +349,9 @@ class HttpCache::Transaction : public HttpTransaction { // working with range requests. int DoPartialCacheReadCompleted(int result); + // Performs the needed work after writing data to the cache. + int DoCacheWriteCompleted(int result); + // Called to signal completion of the network transaction's Start method: void OnNetworkInfoAvailable(int result); @@ -352,6 +361,9 @@ class HttpCache::Transaction : public HttpTransaction { // Called to signal completion of the cache's ReadData method: void OnCacheReadCompleted(int result); + // Called to signal completion of the cache's WriteData method: + void OnCacheWriteCompleted(int result); + // Called to signal completion of the cache entry's ReadyForSparseIO method: void OnCacheEntryReady(int result); @@ -384,6 +396,8 @@ class HttpCache::Transaction : public HttpTransaction { scoped_refptr<CancelableCompletionCallback<Transaction> > cache_read_callback_; scoped_refptr<CancelableCompletionCallback<Transaction> > + cache_write_callback_; + scoped_refptr<CancelableCompletionCallback<Transaction> > entry_ready_callback_; }; @@ -408,9 +422,10 @@ HttpCache::Transaction::~Transaction() { // If there is an outstanding callback, mark it as cancelled so running it // does nothing. cache_read_callback_->Cancel(); + cache_write_callback_->Cancel(); - // We could still have a cache read in progress, so we just null the cache_ - // pointer to signal that we are dead. See OnCacheReadCompleted. + // We could still have a cache read or write in progress, so we just null the + // cache_ pointer to signal that we are dead. See DoCacheReadCompleted. cache_.reset(); } @@ -1274,7 +1289,7 @@ int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { DCHECK(entry_); int rv; - cache_read_callback_->AddRef(); // Balanced in DoCacheReadCompleted. + cache_read_callback_->AddRef(); // Balanced in OnCacheReadCompleted. if (partial_.get()) { rv = partial_->CacheRead(entry_->disk_entry, data, data_len, cache_read_callback_); @@ -1284,11 +1299,12 @@ int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { } read_buf_ = data; read_buf_len_ = data_len; - if (rv >= 0) { - rv = DoCacheReadCompleted(rv); - } else if (rv != ERR_IO_PENDING) { + if (rv != ERR_IO_PENDING) cache_read_callback_->Release(); - } + + if (rv >= 0) + rv = DoCacheReadCompleted(rv); + return rv; } @@ -1303,22 +1319,29 @@ int HttpCache::Transaction::ReadResponseInfoFromEntry() { return read_ok ? OK : ERR_CACHE_READ_FAILURE; } -void HttpCache::Transaction::WriteToEntry(int index, int offset, - IOBuffer* data, int data_len) { +int HttpCache::Transaction::WriteToEntry(int index, int offset, + IOBuffer* data, int data_len, + CompletionCallback* callback) { if (!entry_) - return; + return data_len; int rv = 0; if (!partial_.get() || !data_len) { - rv = entry_->disk_entry->WriteData(index, offset, data, data_len, NULL, + rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, true); } else { - rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, NULL); + rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); } - if (rv != data_len) { + + if (rv != ERR_IO_PENDING && rv != data_len) { DLOG(ERROR) << "failed to write response data to cache"; DoneWritingToEntry(false); + + // We want to ignore errors writing to disk and just keep reading from + // the network. + rv = data_len; } + return rv; } void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { @@ -1356,13 +1379,14 @@ void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { } } -void HttpCache::Transaction::AppendResponseDataToEntry(IOBuffer* data, - int data_len) { +int HttpCache::Transaction::AppendResponseDataToEntry( + IOBuffer* data, int data_len, CompletionCallback* callback) { if (!entry_ || !data_len) - return; + return data_len; int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); - WriteToEntry(kResponseContentIndex, current_size, data, data_len); + return WriteToEntry(kResponseContentIndex, current_size, data, data_len, + callback); } void HttpCache::Transaction::TruncateResponseData() { @@ -1370,7 +1394,8 @@ void HttpCache::Transaction::TruncateResponseData() { return; // Truncate the stream. - WriteToEntry(kResponseContentIndex, 0, NULL, 0); + int rv = WriteToEntry(kResponseContentIndex, 0, NULL, 0, NULL); + DCHECK(rv != ERR_IO_PENDING); } void HttpCache::Transaction::DoneWritingToEntry(bool success) { @@ -1400,15 +1425,13 @@ int HttpCache::Transaction::DoNetworkReadCompleted(int result) { if (!cache_) return HandleResult(ERR_UNEXPECTED); - AppendResponseDataToEntry(read_buf_, result); + cache_write_callback_->AddRef(); // Balanced in DoCacheWriteCompleted. - if (partial_.get()) - return DoPartialNetworkReadCompleted(result); + result = AppendResponseDataToEntry(read_buf_, result, cache_write_callback_); + if (result == ERR_IO_PENDING) + return result; - if (result == 0) // End of file. - DoneWritingToEntry(true); - - return HandleResult(result); + return DoCacheWriteCompleted(result); } int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { @@ -1430,7 +1453,6 @@ int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { int HttpCache::Transaction::DoCacheReadCompleted(int result) { DCHECK(cache_); - cache_read_callback_->Release(); // Balance the AddRef() from Start(). if (!cache_) return HandleResult(ERR_UNEXPECTED); @@ -1465,6 +1487,25 @@ int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { return HandleResult(result); } +int HttpCache::Transaction::DoCacheWriteCompleted(int result) { + DCHECK(cache_); + // Balance the AddRef from DoNetworkReadCompleted. + cache_write_callback_->Release(); + if (!cache_) + return HandleResult(ERR_UNEXPECTED); + + if (result < 0) + return HandleResult(result); + + if (partial_.get()) + return DoPartialNetworkReadCompleted(result); + + if (result == 0) // End of file. + DoneWritingToEntry(true); + + return HandleResult(result); +} + void HttpCache::Transaction::OnNetworkInfoAvailable(int result) { DCHECK(result != ERR_IO_PENDING); @@ -1579,9 +1620,14 @@ void HttpCache::Transaction::OnNetworkReadCompleted(int result) { } void HttpCache::Transaction::OnCacheReadCompleted(int result) { + cache_read_callback_->Release(); // Balance the AddRef from ReadFromEntry. DoCacheReadCompleted(result); } +void HttpCache::Transaction::OnCacheWriteCompleted(int result) { + DoCacheWriteCompleted(result); +} + void HttpCache::Transaction::OnCacheEntryReady(int result) { DCHECK_EQ(OK, result); ValidateEntryHeadersAndContinue(true); diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 9df19c2..371ef2586 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -128,7 +128,12 @@ class MockDiskEntry : public disk_cache::Entry, data_[index].resize(offset + buf_len); if (buf_len) memcpy(&data_[index][offset], buf->data(), buf_len); - return buf_len; + + if (!callback || (test_mode_ & TEST_MODE_SYNC_CACHE_WRITE)) + return buf_len; + + CallbackLater(callback, buf_len); + return net::ERR_IO_PENDING; } virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, @@ -183,7 +188,11 @@ class MockDiskEntry : public disk_cache::Entry, data_[1].resize(real_offset + buf_len); memcpy(&data_[1][real_offset], buf->data(), buf_len); - return buf_len; + if (!completion_callback || (test_mode_ & TEST_MODE_SYNC_CACHE_WRITE)) + return buf_len; + + CallbackLater(completion_callback, buf_len); + return net::ERR_IO_PENDING; } virtual int GetAvailableRange(int64 offset, int len, int64* start) { @@ -691,6 +700,14 @@ struct Response { const char* body; }; +struct Context { + Context() : result(net::ERR_IO_PENDING) {} + + int result; + TestCompletionCallback callback; + scoped_ptr<net::HttpTransaction> trans; +}; + } // namespace @@ -765,6 +782,44 @@ TEST(HttpCache, SimpleGETWithDiskFailures) { EXPECT_EQ(2, cache.disk_cache()->create_count()); } +// Tests that disk failures after the transaction has started don't cause the +// request to fail. +TEST(HttpCache, SimpleGETWithDiskFailures2) { + MockHttpCache cache; + + MockHttpRequest request(kSimpleGET_Transaction); + + scoped_ptr<Context> c(new Context()); + int rv = cache.http_cache()->CreateTransaction(&c->trans); + EXPECT_EQ(net::OK, rv); + + rv = c->trans->Start(&request, &c->callback, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + rv = c->callback.WaitForResult(); + + // Start failing request now. + cache.disk_cache()->set_soft_failures(true); + + // We have to open the entry again to propagate the failure flag. + disk_cache::Entry* en; + ASSERT_TRUE(cache.disk_cache()->OpenEntry(kSimpleGET_Transaction.url, &en)); + en->Close(); + + ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); + c.reset(); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + EXPECT_EQ(1, cache.disk_cache()->open_count()); + EXPECT_EQ(1, cache.disk_cache()->create_count()); + + // This one should see an empty cache again. + RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_EQ(1, cache.disk_cache()->open_count()); + EXPECT_EQ(2, cache.disk_cache()->create_count()); +} + TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) { MockHttpCache cache; @@ -965,15 +1020,6 @@ TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) { EXPECT_EQ(1, cache.disk_cache()->create_count()); } -struct Context { - int result; - TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - - Context() : result(net::ERR_IO_PENDING) { - } -}; - TEST(HttpCache, SimpleGET_ManyReaders) { MockHttpCache cache; @@ -2022,7 +2068,8 @@ TEST(HttpCache, UnknownRangeGET_2) { MockTransaction transaction(kRangeGET_TransactionOK); transaction.test_mode = TEST_MODE_SYNC_CACHE_START | - TEST_MODE_SYNC_CACHE_READ; + TEST_MODE_SYNC_CACHE_READ | + TEST_MODE_SYNC_CACHE_WRITE; AddMockTransaction(&transaction); // Write to the cache (70-79). @@ -2823,7 +2870,8 @@ TEST(HttpCache, SyncRead) { ScopedMockTransaction transaction(kSimpleGET_Transaction); transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START | - TEST_MODE_SYNC_CACHE_READ); + TEST_MODE_SYNC_CACHE_READ | + TEST_MODE_SYNC_CACHE_WRITE); MockHttpRequest r1(transaction), r2(transaction), diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h index 4de8efd..2a93237 100644 --- a/net/http/http_transaction_unittest.h +++ b/net/http/http_transaction_unittest.h @@ -33,6 +33,7 @@ enum { TEST_MODE_SYNC_NET_READ = 1 << 1, TEST_MODE_SYNC_CACHE_START = 1 << 2, TEST_MODE_SYNC_CACHE_READ = 1 << 3, + TEST_MODE_SYNC_CACHE_WRITE = 1 << 4, }; typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request, |