Commit 7a7c11a6 authored by rvargas@google.com's avatar rvargas@google.com

Http cache: Convert data writes from sysnchronous to asynchronous.

BUG=21383
TEST=covered by current unit tests.


Review URL: http://codereview.chromium.org/201065

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25873 0039d316-1c4b-4281-b951-d872f2087c98
parent 13cd66e6
...@@ -192,7 +192,10 @@ class HttpCache::Transaction ...@@ -192,7 +192,10 @@ class HttpCache::Transaction
network_read_callback_(this, &Transaction::OnNetworkReadCompleted)), network_read_callback_(this, &Transaction::OnNetworkReadCompleted)),
ALLOW_THIS_IN_INITIALIZER_LIST( ALLOW_THIS_IN_INITIALIZER_LIST(
cache_read_callback_(new CancelableCompletionCallback<Transaction>( cache_read_callback_(new CancelableCompletionCallback<Transaction>(
this, &Transaction::OnCacheReadCompleted))) { this, &Transaction::OnCacheReadCompleted))),
ALLOW_THIS_IN_INITIALIZER_LIST(
cache_write_callback_(new CancelableCompletionCallback<Transaction>(
this, &Transaction::OnCacheWriteCompleted))) {
} }
// Clean up the transaction. // Clean up the transaction.
...@@ -333,15 +336,18 @@ class HttpCache::Transaction ...@@ -333,15 +336,18 @@ class HttpCache::Transaction
// Called to write data to the cache entry. If the write fails, then the // 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 // cache entry is destroyed. Future calls to this function will just do
// nothing without side-effect. // nothing without side-effect. Returns a network error code.
void WriteToEntry(int index, int offset, IOBuffer* data, int data_len); 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 // Called to write response_ to the cache entry. |truncated| indicates if the
// entry should be marked as incomplete. // entry should be marked as incomplete.
void WriteResponseInfoToEntry(bool truncated); void WriteResponseInfoToEntry(bool truncated);
// Called to append response data to the cache entry. // Called to append response data to the cache entry. Returns a network error
void AppendResponseDataToEntry(IOBuffer* data, int data_len); // code.
int AppendResponseDataToEntry(IOBuffer* data, int data_len,
CompletionCallback* callback);
// Called to truncate response content in the entry. // Called to truncate response content in the entry.
void TruncateResponseData(); void TruncateResponseData();
...@@ -367,6 +373,9 @@ class HttpCache::Transaction ...@@ -367,6 +373,9 @@ class HttpCache::Transaction
// working with range requests. // working with range requests.
int DoPartialCacheReadCompleted(int result); 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: // Called to signal completion of the network transaction's Start method:
void OnNetworkInfoAvailable(int result); void OnNetworkInfoAvailable(int result);
...@@ -376,6 +385,9 @@ class HttpCache::Transaction ...@@ -376,6 +385,9 @@ class HttpCache::Transaction
// Called to signal completion of the cache's ReadData method: // Called to signal completion of the cache's ReadData method:
void OnCacheReadCompleted(int result); void OnCacheReadCompleted(int result);
// Called to signal completion of the cache's WriteData method:
void OnCacheWriteCompleted(int result);
scoped_refptr<LoadLog> load_log_; scoped_refptr<LoadLog> load_log_;
const HttpRequestInfo* request_; const HttpRequestInfo* request_;
scoped_ptr<HttpRequestInfo> custom_request_; scoped_ptr<HttpRequestInfo> custom_request_;
...@@ -404,6 +416,8 @@ class HttpCache::Transaction ...@@ -404,6 +416,8 @@ class HttpCache::Transaction
CompletionCallbackImpl<Transaction> network_read_callback_; CompletionCallbackImpl<Transaction> network_read_callback_;
scoped_refptr<CancelableCompletionCallback<Transaction> > scoped_refptr<CancelableCompletionCallback<Transaction> >
cache_read_callback_; cache_read_callback_;
scoped_refptr<CancelableCompletionCallback<Transaction> >
cache_write_callback_;
}; };
HttpCache::Transaction::~Transaction() { HttpCache::Transaction::~Transaction() {
...@@ -422,9 +436,10 @@ HttpCache::Transaction::~Transaction() { ...@@ -422,9 +436,10 @@ HttpCache::Transaction::~Transaction() {
// If there is an outstanding callback, mark it as cancelled so running it // If there is an outstanding callback, mark it as cancelled so running it
// does nothing. // does nothing.
cache_read_callback_->Cancel(); cache_read_callback_->Cancel();
cache_write_callback_->Cancel();
// We could still have a cache read in progress, so we just null the cache_ // We could still have a cache read or write in progress, so we just null the
// pointer to signal that we are dead. See OnCacheReadCompleted. // cache_ pointer to signal that we are dead. See DoCacheReadCompleted.
cache_ = NULL; cache_ = NULL;
} }
...@@ -1272,7 +1287,7 @@ int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { ...@@ -1272,7 +1287,7 @@ int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
DCHECK(entry_); DCHECK(entry_);
int rv; int rv;
cache_read_callback_->AddRef(); // Balanced in DoCacheReadCompleted. cache_read_callback_->AddRef(); // Balanced in OnCacheReadCompleted.
if (partial_.get()) { if (partial_.get()) {
rv = partial_->CacheRead(entry_->disk_entry, data, data_len, rv = partial_->CacheRead(entry_->disk_entry, data, data_len,
cache_read_callback_); cache_read_callback_);
...@@ -1282,11 +1297,12 @@ int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { ...@@ -1282,11 +1297,12 @@ int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) {
} }
read_buf_ = data; read_buf_ = data;
read_buf_len_ = data_len; read_buf_len_ = data_len;
if (rv >= 0) { if (rv != ERR_IO_PENDING)
rv = DoCacheReadCompleted(rv);
} else if (rv != ERR_IO_PENDING) {
cache_read_callback_->Release(); cache_read_callback_->Release();
}
if (rv >= 0)
rv = DoCacheReadCompleted(rv);
return rv; return rv;
} }
...@@ -1301,22 +1317,25 @@ int HttpCache::Transaction::ReadResponseInfoFromEntry() { ...@@ -1301,22 +1317,25 @@ int HttpCache::Transaction::ReadResponseInfoFromEntry() {
return read_ok ? OK : ERR_CACHE_READ_FAILURE; return read_ok ? OK : ERR_CACHE_READ_FAILURE;
} }
void HttpCache::Transaction::WriteToEntry(int index, int offset, int HttpCache::Transaction::WriteToEntry(int index, int offset,
IOBuffer* data, int data_len) { IOBuffer* data, int data_len,
CompletionCallback* callback) {
if (!entry_) if (!entry_)
return; return data_len;
int rv = 0; int rv = 0;
if (!partial_.get() || !data_len) { 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); true);
} else { } 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 >= 0 && rv != data_len) {
DLOG(ERROR) << "failed to write response data to cache"; DLOG(ERROR) << "failed to write response data to cache";
DoneWritingToEntry(false); DoneWritingToEntry(false);
} }
return rv;
} }
void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
...@@ -1354,13 +1373,14 @@ void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { ...@@ -1354,13 +1373,14 @@ void HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) {
} }
} }
void HttpCache::Transaction::AppendResponseDataToEntry(IOBuffer* data, int HttpCache::Transaction::AppendResponseDataToEntry(
int data_len) { IOBuffer* data, int data_len, CompletionCallback* callback) {
if (!entry_ || !data_len) if (!entry_ || !data_len)
return; return data_len;
int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 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() { void HttpCache::Transaction::TruncateResponseData() {
...@@ -1368,7 +1388,8 @@ void HttpCache::Transaction::TruncateResponseData() { ...@@ -1368,7 +1388,8 @@ void HttpCache::Transaction::TruncateResponseData() {
return; return;
// Truncate the stream. // 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) { void HttpCache::Transaction::DoneWritingToEntry(bool success) {
...@@ -1398,15 +1419,13 @@ int HttpCache::Transaction::DoNetworkReadCompleted(int result) { ...@@ -1398,15 +1419,13 @@ int HttpCache::Transaction::DoNetworkReadCompleted(int result) {
if (revoked()) if (revoked())
return HandleResult(ERR_UNEXPECTED); return HandleResult(ERR_UNEXPECTED);
AppendResponseDataToEntry(read_buf_, result); cache_write_callback_->AddRef(); // Balanced in DoCacheWriteCompleted.
if (partial_.get())
return DoPartialNetworkReadCompleted(result);
if (result == 0) // End of file. result = AppendResponseDataToEntry(read_buf_, result, cache_write_callback_);
DoneWritingToEntry(true); if (result == ERR_IO_PENDING)
return result;
return HandleResult(result); return DoCacheWriteCompleted(result);
} }
int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
...@@ -1428,7 +1447,6 @@ int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { ...@@ -1428,7 +1447,6 @@ int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
int HttpCache::Transaction::DoCacheReadCompleted(int result) { int HttpCache::Transaction::DoCacheReadCompleted(int result) {
DCHECK(cache_); DCHECK(cache_);
cache_read_callback_->Release(); // Balance the AddRef() from Start().
if (revoked()) if (revoked())
return HandleResult(ERR_UNEXPECTED); return HandleResult(ERR_UNEXPECTED);
...@@ -1463,6 +1481,25 @@ int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { ...@@ -1463,6 +1481,25 @@ int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
return HandleResult(result); return HandleResult(result);
} }
int HttpCache::Transaction::DoCacheWriteCompleted(int result) {
DCHECK(cache_);
// Balance the AddRef from DoNetworkReadCompleted.
cache_write_callback_->Release();
if (revoked())
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) { void HttpCache::Transaction::OnNetworkInfoAvailable(int result) {
DCHECK(result != ERR_IO_PENDING); DCHECK(result != ERR_IO_PENDING);
...@@ -1577,9 +1614,14 @@ void HttpCache::Transaction::OnNetworkReadCompleted(int result) { ...@@ -1577,9 +1614,14 @@ void HttpCache::Transaction::OnNetworkReadCompleted(int result) {
} }
void HttpCache::Transaction::OnCacheReadCompleted(int result) { void HttpCache::Transaction::OnCacheReadCompleted(int result) {
cache_read_callback_->Release(); // Balance the AddRef from ReadFromEntry.
DoCacheReadCompleted(result); DoCacheReadCompleted(result);
} }
void HttpCache::Transaction::OnCacheWriteCompleted(int result) {
DoCacheWriteCompleted(result);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HttpCache::HttpCache(HostResolver* host_resolver, HttpCache::HttpCache(HostResolver* host_resolver,
......
...@@ -126,7 +126,12 @@ class MockDiskEntry : public disk_cache::Entry, ...@@ -126,7 +126,12 @@ class MockDiskEntry : public disk_cache::Entry,
data_[index].resize(offset + buf_len); data_[index].resize(offset + buf_len);
if (buf_len) if (buf_len)
memcpy(&data_[index][offset], buf->data(), 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, virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
...@@ -177,7 +182,11 @@ class MockDiskEntry : public disk_cache::Entry, ...@@ -177,7 +182,11 @@ class MockDiskEntry : public disk_cache::Entry,
data_[1].resize(real_offset + buf_len); data_[1].resize(real_offset + buf_len);
memcpy(&data_[1][real_offset], buf->data(), 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) { virtual int GetAvailableRange(int64 offset, int len, int64* start) {
...@@ -1969,7 +1978,8 @@ TEST(HttpCache, UnknownRangeGET_2) { ...@@ -1969,7 +1978,8 @@ TEST(HttpCache, UnknownRangeGET_2) {
MockTransaction transaction(kRangeGET_TransactionOK); MockTransaction transaction(kRangeGET_TransactionOK);
transaction.test_mode = TEST_MODE_SYNC_CACHE_START | 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); AddMockTransaction(&transaction);
// Write to the cache (70-79). // Write to the cache (70-79).
...@@ -2534,7 +2544,8 @@ TEST(HttpCache, SyncRead) { ...@@ -2534,7 +2544,8 @@ TEST(HttpCache, SyncRead) {
ScopedMockTransaction transaction(kSimpleGET_Transaction); ScopedMockTransaction transaction(kSimpleGET_Transaction);
transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START | 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), MockHttpRequest r1(transaction),
r2(transaction), r2(transaction),
......
...@@ -33,6 +33,7 @@ enum { ...@@ -33,6 +33,7 @@ enum {
TEST_MODE_SYNC_NET_READ = 1 << 1, TEST_MODE_SYNC_NET_READ = 1 << 1,
TEST_MODE_SYNC_CACHE_START = 1 << 2, TEST_MODE_SYNC_CACHE_START = 1 << 2,
TEST_MODE_SYNC_CACHE_READ = 1 << 3, TEST_MODE_SYNC_CACHE_READ = 1 << 3,
TEST_MODE_SYNC_CACHE_WRITE = 1 << 4,
}; };
typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request, typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment