summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/flash
diff options
context:
space:
mode:
authoragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-06 07:55:20 +0000
committeragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-06 07:55:20 +0000
commit9229656f8004972905c616dec1af9659ce23bb15 (patch)
treed07bdb2bf36be3dadab14fdebd564bf46c7b7fac /net/disk_cache/flash
parent7a6364c98232bb382461bcc1513f05b4604a0ab8 (diff)
downloadchromium_src-9229656f8004972905c616dec1af9659ce23bb15.zip
chromium_src-9229656f8004972905c616dec1af9659ce23bb15.tar.gz
chromium_src-9229656f8004972905c616dec1af9659ce23bb15.tar.bz2
Added CacheEntry implementation.
BUG=157187 TEST=net_unittests --gtest_filter="FlashCacheTest.*" --gtest_repeat=10 --shuffle Review URL: https://chromiumcodereview.appspot.com/11316178 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171444 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache/flash')
-rw-r--r--net/disk_cache/flash/cache_entry.cc160
-rw-r--r--net/disk_cache/flash/cache_entry.h63
-rw-r--r--net/disk_cache/flash/cache_entry_unittest.cc59
-rw-r--r--net/disk_cache/flash/format.h5
-rw-r--r--net/disk_cache/flash/storage.cc2
5 files changed, 287 insertions, 2 deletions
diff --git a/net/disk_cache/flash/cache_entry.cc b/net/disk_cache/flash/cache_entry.cc
new file mode 100644
index 0000000..a8bfb42
--- /dev/null
+++ b/net/disk_cache/flash/cache_entry.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/disk_cache/flash/cache_entry.h"
+#include "net/disk_cache/flash/format.h"
+#include "net/disk_cache/flash/log_structured_store.h"
+
+namespace disk_cache {
+
+CacheEntry::CacheEntry(LogStructuredStore* store)
+ : store_(store), id_(-1), init_(false), closed_(false) {
+ DCHECK(store);
+}
+
+CacheEntry::CacheEntry(LogStructuredStore* store, int32 id)
+ : store_(store), id_(id), init_(false), closed_(false) {
+ DCHECK(store);
+}
+
+CacheEntry::~CacheEntry() {
+ DCHECK(!init_ || closed_);
+}
+
+bool CacheEntry::Init() {
+ DCHECK(!init_);
+ if (!OnDisk()) {
+ init_ = true;
+ return true;
+ }
+
+ int32 stream_sizes[kFlashCacheEntryNumStreams];
+ COMPILE_ASSERT(sizeof(stream_sizes) == kFlashCacheEntryHeaderSize,
+ invalid_cache_entry_header_size);
+
+ if (!store_->OpenEntry(id_) ||
+ !store_->ReadData(id_, stream_sizes, kFlashCacheEntryHeaderSize, 0)) {
+ return false;
+ }
+ for (int i = 0, offset = kFlashCacheEntryHeaderSize;
+ i < kFlashCacheEntryNumStreams; ++i) {
+ streams_[i].offset = offset;
+ streams_[i].size = stream_sizes[i];
+ offset += stream_sizes[i];
+ }
+ init_ = true;
+ return true;
+}
+
+bool CacheEntry::Close() {
+ DCHECK(init_ && !closed_);
+ if (OnDisk())
+ store_->CloseEntry(id_);
+ else if (!Save())
+ return false;
+ closed_ = true;
+ return true;
+}
+
+int32 CacheEntry::id() const {
+ DCHECK(init_);
+ return id_;
+}
+
+int32 CacheEntry::GetDataSize(int index) const {
+ DCHECK(init_);
+ return InvalidStream(index) ? 0 : streams_[index].size;
+}
+
+int CacheEntry::ReadData(int index, int offset, net::IOBuffer* buf,
+ int buf_len) {
+ DCHECK(init_);
+ if (InvalidStream(index))
+ return net::ERR_INVALID_ARGUMENT;
+
+ int stream_size = streams_[index].size;
+ if (offset >= stream_size || offset < 0 || buf_len == 0)
+ return 0;
+ if (offset + buf_len > stream_size)
+ buf_len = stream_size - offset;
+
+ if (OnDisk()) {
+ offset += streams_[index].offset;
+ if (store_->ReadData(id_, buf->data(), buf_len, offset))
+ return buf_len;
+ return net::ERR_FAILED;
+ }
+ memcpy(buf->data(), &streams_[index].write_buffer[offset], buf_len);
+ return buf_len;
+}
+
+int CacheEntry::WriteData(int index, int offset, net::IOBuffer* buf,
+ int buf_len) {
+ DCHECK(init_ && !closed_);
+ if (InvalidStream(index))
+ return net::ERR_INVALID_ARGUMENT;
+
+ DCHECK(offset >= 0 && buf_len >= 0);
+ Stream& stream = streams_[index];
+ size_t new_size = static_cast<size_t>(offset + buf_len);
+ if (new_size) {
+ // TODO(agayev): Currently, only append and overwrite is supported. Add
+ // support for arbitrary writes.
+ DCHECK(!offset || offset == stream.size);
+ if (stream.write_buffer.capacity() < new_size)
+ stream.write_buffer.reserve(new_size);
+ memcpy(&streams_[index].write_buffer[offset], buf->data(), buf_len);
+ }
+ stream.size = new_size;
+ return buf_len;
+}
+
+bool CacheEntry::OnDisk() const {
+ return id_ != -1;
+}
+
+bool CacheEntry::InvalidStream(int stream_index) const {
+ return stream_index < 0 || stream_index >= kFlashCacheEntryNumStreams;
+}
+
+int32 CacheEntry::Size() const {
+ DCHECK(init_);
+ int32 size = kFlashCacheEntryHeaderSize;
+ for (int i = 0; i < kFlashCacheEntryNumStreams; ++i)
+ size += streams_[i].size;
+ DCHECK(size > 0 && size <= kFlashSegmentFreeSpace);
+ return size;
+}
+
+bool CacheEntry::Save() {
+ DCHECK(init_ && !closed_ && !OnDisk());
+ int32 stream_sizes[kFlashCacheEntryNumStreams];
+ COMPILE_ASSERT(sizeof(stream_sizes) == kFlashCacheEntryHeaderSize,
+ invalid_cache_entry_header_size);
+
+ for (int i = 0; i < kFlashCacheEntryNumStreams; ++i)
+ stream_sizes[i] = streams_[i].size;
+
+ if (!store_->CreateEntry(Size(), &id_))
+ return false;
+ if (!store_->WriteData(stream_sizes, kFlashCacheEntryHeaderSize))
+ return false;
+ for (int i = 0; i < kFlashCacheEntryNumStreams; ++i) {
+ if (!store_->WriteData(&streams_[i].write_buffer[0], streams_[i].size))
+ return false;
+ }
+ store_->CloseEntry(id_);
+ return true;
+}
+
+CacheEntry::Stream::Stream() : offset(0), size(0) {
+}
+
+CacheEntry::Stream::~Stream() {
+}
+
+} // namespace disk_cache
diff --git a/net/disk_cache/flash/cache_entry.h b/net/disk_cache/flash/cache_entry.h
new file mode 100644
index 0000000..05f08eb
--- /dev/null
+++ b/net/disk_cache/flash/cache_entry.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DISK_CACHE_FLASH_LOG_ENTRY_H_
+#define NET_DISK_CACHE_FLASH_LOG_ENTRY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "net/base/net_export.h"
+#include "net/disk_cache/flash/format.h"
+
+namespace net {
+class IOBuffer;
+};
+
+namespace disk_cache {
+
+class LogStructuredStore;
+
+class NET_EXPORT_PRIVATE CacheEntry {
+ public:
+ explicit CacheEntry(LogStructuredStore* store);
+ CacheEntry(LogStructuredStore* store, int32 id);
+ ~CacheEntry();
+
+ bool Init();
+ bool Close();
+
+ int32 id() const;
+ int32 GetDataSize(int index) const;
+
+ int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len);
+ int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len);
+
+ private:
+ struct Stream {
+ Stream();
+ ~Stream();
+ int offset;
+ int size;
+ std::vector<char> write_buffer;
+ };
+
+ bool OnDisk() const;
+ bool InvalidStream(int stream_index) const;
+ int32 Size() const;
+ bool Save();
+
+ LogStructuredStore* store_;
+ int32 id_;
+ Stream streams_[kFlashCacheEntryNumStreams];
+ bool init_;
+ bool closed_;
+
+ DISALLOW_COPY_AND_ASSIGN(CacheEntry);
+};
+
+} // namespace disk_cache
+
+#endif // NET_DISK_CACHE_FLASH_LOG_ENTRY_H_
diff --git a/net/disk_cache/flash/cache_entry_unittest.cc b/net/disk_cache/flash/cache_entry_unittest.cc
new file mode 100644
index 0000000..206f283
--- /dev/null
+++ b/net/disk_cache/flash/cache_entry_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/io_buffer.h"
+#include "net/disk_cache/disk_cache_test_util.h"
+#include "net/disk_cache/flash/cache_entry.h"
+#include "net/disk_cache/flash/flash_cache_test_base.h"
+#include "net/disk_cache/flash/format.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using disk_cache::CacheEntry;
+
+// Tests the behavior of a CacheEntry with empty streams.
+TEST_F(FlashCacheTest, CacheEntryEmpty) {
+ scoped_ptr<CacheEntry> entry(new CacheEntry(log_structured_store_.get()));
+ EXPECT_TRUE(entry->Init());
+ EXPECT_TRUE(entry->Close());
+
+ entry.reset(new CacheEntry(log_structured_store_.get(), entry->id()));
+ EXPECT_TRUE(entry->Init());
+
+ for (int i = 0; i < disk_cache::kFlashCacheEntryNumStreams; ++i) {
+ const int kSize = 1024;
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
+ EXPECT_EQ(0, entry->GetDataSize(i));
+ EXPECT_EQ(0, entry->ReadData(i, 0, buf, kSize));
+ }
+ EXPECT_TRUE(entry->Close());
+}
+
+TEST_F(FlashCacheTest, CacheEntryWriteRead) {
+ scoped_ptr<CacheEntry> entry(new CacheEntry(log_structured_store_.get()));
+ EXPECT_TRUE(entry->Init());
+
+ int sizes[disk_cache::kFlashCacheEntryNumStreams] = {333, 444, 555, 666};
+ scoped_refptr<net::IOBuffer> buffers[disk_cache::kFlashCacheEntryNumStreams];
+
+ for (int i = 0; i < disk_cache::kFlashCacheEntryNumStreams; ++i) {
+ buffers[i] = new net::IOBuffer(sizes[i]);
+ CacheTestFillBuffer(buffers[i]->data(), sizes[i], false);
+ EXPECT_EQ(sizes[i], entry->WriteData(i, 0, buffers[i], sizes[i]));
+ }
+ EXPECT_TRUE(entry->Close());
+
+ int32 id = entry->id();
+ entry.reset(new CacheEntry(log_structured_store_.get(), id));
+ EXPECT_TRUE(entry->Init());
+
+ for (int i = 0; i < disk_cache::kFlashCacheEntryNumStreams; ++i) {
+ EXPECT_EQ(sizes[i], entry->GetDataSize(i));
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(sizes[i]));
+ EXPECT_EQ(sizes[i], entry->ReadData(i, 0, buffer, sizes[i]));
+ EXPECT_EQ(0, memcmp(buffers[i]->data(), buffer->data(), sizes[i]));
+ }
+ EXPECT_TRUE(entry->Close());
+ EXPECT_EQ(id, entry->id());
+}
diff --git a/net/disk_cache/flash/format.h b/net/disk_cache/flash/format.h
index d32344d..660c614 100644
--- a/net/disk_cache/flash/format.h
+++ b/net/disk_cache/flash/format.h
@@ -22,6 +22,11 @@ const size_t kFlashMaxEntryCount = kFlashSegmentSize / kFlashSmallEntrySize - 1;
const int32 kFlashSummarySize = (1 + kFlashMaxEntryCount) * sizeof(int32);
const int32 kFlashSegmentFreeSpace = kFlashSegmentSize - kFlashSummarySize;
+// An entry consists of a fixed number of streams.
+const int32 kFlashCacheEntryNumStreams = 4;
+const int32 kFlashCacheEntryHeaderSize =
+ kFlashCacheEntryNumStreams * sizeof(int32);
+
} // namespace disk_cache
#endif // NET_DISK_CACHE_FLASH_FORMAT_H_
diff --git a/net/disk_cache/flash/storage.cc b/net/disk_cache/flash/storage.cc
index 24c2774..b6af0fe 100644
--- a/net/disk_cache/flash/storage.cc
+++ b/net/disk_cache/flash/storage.cc
@@ -43,7 +43,6 @@ Storage::~Storage() {
}
bool Storage::Read(void* buffer, int32 size, int32 offset) {
- DCHECK(buffer);
DCHECK(offset >= 0 && offset + size <= size_);
int rv = base::ReadPlatformFile(file_, offset, static_cast<char*>(buffer),
@@ -52,7 +51,6 @@ bool Storage::Read(void* buffer, int32 size, int32 offset) {
}
bool Storage::Write(const void* buffer, int32 size, int32 offset) {
- DCHECK(buffer);
DCHECK(offset >= 0 && offset + size <= size_);
int rv = base::WritePlatformFile(file_, offset,