diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 21:43:49 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 21:43:49 +0000 |
commit | a2068a61d67a2e90789e45a8073e631899bdeb9c (patch) | |
tree | b8e80ea1d0cd464cd8422bb577161b7cad4d6edf /net | |
parent | 9b72d9a51a5e32f2600c27a65b6598745714c2be (diff) | |
download | chromium_src-a2068a61d67a2e90789e45a8073e631899bdeb9c.zip chromium_src-a2068a61d67a2e90789e45a8073e631899bdeb9c.tar.gz chromium_src-a2068a61d67a2e90789e45a8073e631899bdeb9c.tar.bz2 |
Disk cache: Interface for the sparse cache support.
This is just the interface declaration plus a mocked
implementation of the interface.
BUG=12258
TEST=none
Review URL: http://codereview.chromium.org/119072
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17669 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_error_list.h | 3 | ||||
-rw-r--r-- | net/disk_cache/disk_cache.h | 53 | ||||
-rw-r--r-- | net/disk_cache/entry_impl.cc | 14 | ||||
-rw-r--r-- | net/disk_cache/entry_impl.h | 5 | ||||
-rw-r--r-- | net/disk_cache/mem_entry_impl.cc | 14 | ||||
-rw-r--r-- | net/disk_cache/mem_entry_impl.h | 5 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 79 |
7 files changed, 171 insertions, 2 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 6265895..ae7d272 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -250,5 +250,8 @@ NET_ERROR(CACHE_READ_FAILURE, -401) // transaction. NET_ERROR(CACHE_CANNOT_CREATE_NETWORK_TRANSACTION, -402) +// The operation is not supported for this entry. +NET_ERROR(CACHE_OPERATION_NOT_SUPPORTED, -403) + // The server's response was insecure (e.g. there was a cert error). NET_ERROR(INSECURE_RESPONSE, -501) diff --git a/net/disk_cache/disk_cache.h b/net/disk_cache/disk_cache.h index de40554..f43cace 100644 --- a/net/disk_cache/disk_cache.h +++ b/net/disk_cache/disk_cache.h @@ -154,6 +154,59 @@ class Entry { net::CompletionCallback* completion_callback, bool truncate) = 0; + // Sparse entries support: + // + // A Backend implementation can support sparse entries, so the cache keeps + // track of which parts of the entry have been written before. The backend + // will never return data that was not written previously, so reading from + // such region will return 0 bytes read (or actually the number of bytes read + // before reaching that region). + // + // There are only two streams for sparse entries: a regular control stream + // (index 0) that must be accessed through the regular API (ReadData and + // WriteData), and one sparse stream that must me accessed through the sparse- + // aware API that follows. Calling a non-sparse aware method with an index + // argument other than 0 is a mistake that results in implementation specific + // behavior. Using a sparse-aware method with an entry that was not stored + // using the same API, or with a backend that doesn't support sparse entries + // will return ERR_CACHE_OPERATION_NOT_SUPPORTED. + // + // The storage granularity of the implementation should be at least 1 KB. In + // other words, storing less than 1 KB may result in an implementation + // dropping the data completely, and writing at offsets not aligned with 1 KB, + // or with lengths not a multiple of 1 KB may result in the first or last part + // of the data being discarded. However, two consecutive writes should not + // result in a hole in between the two parts as long as they are sequential + // (the second one starts where the first one ended), and there is no other + // write between them. + // + // The Backend implementation is free to evict any range from the cache at any + // moment, so in practice, the previously stated granularity of 1 KB is not + // as bad as it sounds. + + // Behaves like ReadData() except that this method is used to access sparse + // entries. + virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) = 0; + + // Behaves like WriteData() except that this method is used to access sparse + // entries. |truncate| is not part of this interface because a sparse entry + // is not expected to be reused with new data. To delete the old data and + // start again, or to reduce the total size of the stream data (which implies + // that the content has changed), the whole entry should be doomed and + // re-created. + virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) = 0; + + // Returns information about the currently stored portion of a sparse entry. + // |offset| and |len| describe a particular range that should be scanned to + // find out if it is stored or not. |start| will contain the offset of the + // first byte that is stored within this range, and the return value is the + // minimum number of consecutive stored bytes. Note that it is possible that + // this entry has stored more than the returned value. This method returns a + // net error code whenever the request cannot be completed successfully. + virtual int GetAvailableRange(int64 offset, int len, int64* start) = 0; + protected: virtual ~Entry() {} }; diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc index e0853b7..ea20b3c 100644 --- a/net/disk_cache/entry_impl.cc +++ b/net/disk_cache/entry_impl.cc @@ -351,6 +351,20 @@ int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, return (completed || !completion_callback) ? buf_len : net::ERR_IO_PENDING; } +int EntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + +int EntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + +int EntryImpl::GetAvailableRange(int64 offset, int len, int64* start) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + uint32 EntryImpl::GetHash() { return entry_.Data()->hash; } diff --git a/net/disk_cache/entry_impl.h b/net/disk_cache/entry_impl.h index 39ba186..72b38cb 100644 --- a/net/disk_cache/entry_impl.h +++ b/net/disk_cache/entry_impl.h @@ -33,6 +33,11 @@ class EntryImpl : public Entry, public base::RefCounted<EntryImpl> { virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, net::CompletionCallback* completion_callback, bool truncate); + virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback); + virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback); + virtual int GetAvailableRange(int64 offset, int len, int64* start); inline CacheEntryBlock* entry() { return &entry_; diff --git a/net/disk_cache/mem_entry_impl.cc b/net/disk_cache/mem_entry_impl.cc index 9b8c1c9..ea55a18 100644 --- a/net/disk_cache/mem_entry_impl.cc +++ b/net/disk_cache/mem_entry_impl.cc @@ -150,6 +150,20 @@ int MemEntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, return buf_len; } +int MemEntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + +int MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + +int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) { + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; +} + void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) { int entry_size = GetDataSize(index); diff --git a/net/disk_cache/mem_entry_impl.h b/net/disk_cache/mem_entry_impl.h index 42fad96..65eb450 100644 --- a/net/disk_cache/mem_entry_impl.h +++ b/net/disk_cache/mem_entry_impl.h @@ -29,6 +29,11 @@ class MemEntryImpl : public Entry { virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, net::CompletionCallback* completion_callback, bool truncate); + virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback); + virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback); + virtual int GetAvailableRange(int64 offset, int len, int64* start); // Performs the initialization of a EntryImpl that will be added to the // cache. diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index ef127a2..b58eb44 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -27,11 +27,11 @@ class MockDiskEntry : public disk_cache::Entry, public base::RefCounted<MockDiskEntry> { public: MockDiskEntry() - : test_mode_(0), doomed_(false) { + : test_mode_(0), doomed_(false), sparse_(false) { } MockDiskEntry(const std::string& key) - : key_(key), doomed_(false) { + : key_(key), doomed_(false), sparse_(false) { // // 'key' is prefixed with an identifier if it corresponds to a cached POST. // Skip past that to locate the actual URL. @@ -116,6 +116,80 @@ class MockDiskEntry : public disk_cache::Entry, return buf_len; } + virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + if (!sparse_) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + if (offset < 0) + return net::ERR_FAILED; + + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + if (!buf_len) + return 0; + + int num = std::min(static_cast<int>(data_[1].size()) - real_offset, + buf_len); + memcpy(buf->data(), &data_[1][real_offset], num); + + if (!completion_callback || (test_mode_ & TEST_MODE_SYNC_CACHE_READ)) + return num; + + CallbackLater(completion_callback, num); + return net::ERR_IO_PENDING; + } + + virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::CompletionCallback* completion_callback) { + if (!sparse_) { + if (data_[1].size()) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + sparse_ = true; + } + if (offset < 0) + return net::ERR_FAILED; + if (!buf_len) + return 0; + + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + + if (static_cast<int>(data_[1].size()) < real_offset + buf_len) + data_[1].resize(real_offset + buf_len); + + memcpy(&data_[1][real_offset], buf->data(), buf_len); + return buf_len; + } + + virtual int GetAvailableRange(int64 offset, int len, int64* start) { + if (!sparse_) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + if (offset < 0) + return net::ERR_FAILED; + + *start = offset; + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + if (static_cast<int>(data_[1].size()) < real_offset) + return 0; + + int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len); + int count = 0; + for (; num > 0; num--, real_offset++) { + if (!count) { + if (data_[1][real_offset]) { + count++; + *start = real_offset; + } + } else { + if (!data_[1][real_offset]) + break; + count++; + } + } + return count; + } + private: // Unlike the callbacks for MockHttpTransaction, we want this one to run even // if the consumer called Close on the MockDiskEntry. We achieve that by @@ -132,6 +206,7 @@ class MockDiskEntry : public disk_cache::Entry, std::vector<char> data_[2]; int test_mode_; bool doomed_; + bool sparse_; }; class MockDiskCache : public disk_cache::Backend { |