summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-22 18:36:19 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-22 18:36:19 +0000
commit73cae57f1b63a1979790881960ca7615cd779cd0 (patch)
tree39b12bde09b9210d3e015e741d57f2ec35977000 /net
parent204e18e9f7fabcbe467c7dcf015fac2ed0567e66 (diff)
downloadchromium_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.cc106
-rw-r--r--net/http/http_cache_unittest.cc74
-rw-r--r--net/http/http_transaction_unittest.h1
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,