summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-04 21:43:49 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-04 21:43:49 +0000
commita2068a61d67a2e90789e45a8073e631899bdeb9c (patch)
treeb8e80ea1d0cd464cd8422bb577161b7cad4d6edf /net
parent9b72d9a51a5e32f2600c27a65b6598745714c2be (diff)
downloadchromium_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.h3
-rw-r--r--net/disk_cache/disk_cache.h53
-rw-r--r--net/disk_cache/entry_impl.cc14
-rw-r--r--net/disk_cache/entry_impl.h5
-rw-r--r--net/disk_cache/mem_entry_impl.cc14
-rw-r--r--net/disk_cache/mem_entry_impl.h5
-rw-r--r--net/http/http_cache_unittest.cc79
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 {