Commit bb72e614 authored by agayev@chromium.org's avatar agayev@chromium.org

FlashCache refactorings.

BUG=157187
TEST=net_unittests --gtest_filter="FlashCacheTest.*" --gtest_repeat=10 --shuffle

Review URL: https://chromiumcodereview.appspot.com/14265009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194792 0039d316-1c4b-4281-b951-d872f2087c98
parent 5bd7f7ac
......@@ -11,14 +11,7 @@
#include "net/disk_cache/flash/log_store.h"
#include "net/disk_cache/flash/storage.h"
namespace {
const int32 kSegmentCount = 10;
const base::FilePath::StringType kCachePath = FILE_PATH_LITERAL("cache");
} // namespace
FlashCacheTest::FlashCacheTest() : num_segments_in_storage_(kSegmentCount) {
FlashCacheTest::FlashCacheTest() {
int seed = static_cast<int>(base::Time::Now().ToInternalValue());
srand(seed);
}
......@@ -27,19 +20,10 @@ FlashCacheTest::~FlashCacheTest() {
}
void FlashCacheTest::SetUp() {
const base::FilePath::StringType kCachePath = FILE_PATH_LITERAL("cache");
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
const base::FilePath path(temp_dir_.path().Append(kCachePath));
int32 storage_size = num_segments_in_storage_ * disk_cache::kFlashSegmentSize;
storage_.reset(new disk_cache::Storage(path, storage_size));
ASSERT_TRUE(storage_->Init());
log_store_.reset(new disk_cache::LogStore(storage_.get()));
ASSERT_TRUE(log_store_->Init());
path_ = temp_dir_.path().Append(kCachePath);
}
void FlashCacheTest::TearDown() {
ASSERT_TRUE(log_store_->Close());
log_store_.reset();
storage_.reset();
}
......@@ -9,12 +9,19 @@
#include "base/compiler_specific.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "net/disk_cache/flash/format.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const int32 kNumTestSegments = 10;
const int32 kStorageSize = kNumTestSegments * disk_cache::kFlashSegmentSize;
} // namespace
namespace disk_cache {
class LogStore;
class Storage;
} // namespace disk_cache
......@@ -26,10 +33,8 @@ class FlashCacheTest : public testing::Test {
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
scoped_ptr<disk_cache::LogStore> log_store_;
scoped_ptr<disk_cache::Storage> storage_;
base::ScopedTempDir temp_dir_;
int32 num_segments_in_storage_;
base::FilePath path_;
private:
DISALLOW_COPY_AND_ASSIGN(FlashCacheTest);
......
// 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/ref_counted.h"
#include "base/string_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/disk_cache/flash/flash_cache_test_base.h"
#include "net/disk_cache/flash/flash_entry_impl.h"
#include "net/disk_cache/flash/format.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::CompletionCallback;
TEST_F(FlashCacheTest, FlashEntryCreate) {
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(MessageLoop::TYPE_IO, 0)));
const std::string key = "foo.com";
disk_cache::FlashEntryImpl* entry =
new disk_cache::FlashEntryImpl(key,
log_store_.get(),
cache_thread.message_loop_proxy());
entry->AddRef();
EXPECT_EQ(net::OK, entry->Init(CompletionCallback()));
EXPECT_EQ(key, entry->GetKey());
EXPECT_EQ(0, entry->GetDataSize(0));
EXPECT_EQ(0, entry->GetDataSize(1));
EXPECT_EQ(0, entry->GetDataSize(2));
const int kSize1 = 100;
scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
CacheTestFillBuffer(buffer1->data(), kSize1, false);
EXPECT_EQ(0, entry->ReadData(0, 0, buffer1, kSize1, CompletionCallback()));
base::strlcpy(buffer1->data(), "the data", kSize1);
EXPECT_EQ(kSize1, entry->WriteData(0, 0, buffer1, kSize1,
CompletionCallback(), false));
memset(buffer1->data(), 0, kSize1);
EXPECT_EQ(kSize1, entry->ReadData(0, 0, buffer1, kSize1,
CompletionCallback()));
EXPECT_STREQ("the data", buffer1->data());
entry->Close();
}
......@@ -12,16 +12,16 @@
namespace disk_cache {
LogStore::LogStore(Storage* storage)
: storage_(storage),
num_segments_(storage->size() / kFlashSegmentSize),
LogStore::LogStore(const base::FilePath& path, int32 size)
: storage_(path, size),
num_segments_(size / kFlashSegmentSize),
open_segments_(num_segments_),
write_index_(0),
current_entry_id_(-1),
current_entry_num_bytes_left_to_write_(0),
init_(false),
closed_(false) {
DCHECK(storage->size() % kFlashSegmentSize == 0);
DCHECK(size % kFlashSegmentSize == 0);
}
LogStore::~LogStore() {
......@@ -31,9 +31,12 @@ LogStore::~LogStore() {
bool LogStore::Init() {
DCHECK(!init_);
if (!storage_.Init())
return false;
// TODO(agayev): Once we start persisting segment metadata to disk, we will
// start from where we left off during the last shutdown.
scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_));
scoped_ptr<Segment> segment(new Segment(write_index_, false, &storage_));
if (!segment->Init())
return false;
......@@ -69,7 +72,7 @@ bool LogStore::CreateEntry(int32 size, int32* id) {
}
write_index_ = GetNextSegmentIndex();
scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_));
scoped_ptr<Segment> segment(new Segment(write_index_, false, &storage_));
if (!segment->Init())
return false;
......@@ -119,7 +122,7 @@ bool LogStore::OpenEntry(int32 id) {
}
// Segment is not open.
scoped_ptr<Segment> segment(new Segment(index, true, storage_));
scoped_ptr<Segment> segment(new Segment(index, true, &storage_));
if (!segment->Init() || !segment->HaveOffset(id))
return false;
......
......@@ -11,11 +11,11 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "net/base/net_export.h"
#include "net/disk_cache/flash/storage.h"
namespace disk_cache {
class Segment;
class Storage;
// This class implements a general purpose store for storing and retrieving
// entries consisting of arbitrary binary data. The store has log semantics,
......@@ -24,7 +24,7 @@ class Storage;
// any given time, while concurrent reading of multiple entries is supported.
class NET_EXPORT_PRIVATE LogStore {
public:
explicit LogStore(Storage* storage);
LogStore(const base::FilePath& path, int32 size);
~LogStore();
// Performs initialization. Must be the first function called and further
......@@ -58,19 +58,15 @@ class NET_EXPORT_PRIVATE LogStore {
void CloseEntry(int32 id);
private:
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest,
LogStoreReadFromClosedSegment);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest,
LogStoreSegmentSelectionIsFifo);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest,
LogStoreInUseSegmentIsSkipped);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest,
LogStoreReadFromCurrentAfterClose);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreReadFromClosedSegment);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreSegmentSelectionIsFifo);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreInUseSegmentIsSkipped);
FRIEND_TEST_ALL_PREFIXES(FlashCacheTest, LogStoreReadFromCurrentAfterClose);
int32 GetNextSegmentIndex();
bool InUse(int32 segment_index) const;
Storage* storage_;
Storage storage_;
int32 num_segments_;
......
......@@ -7,6 +7,7 @@
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/disk_cache/flash/flash_cache_test_base.h"
#include "net/disk_cache/flash/format.h"
#include "net/disk_cache/flash/log_store.h"
#include "net/disk_cache/flash/log_store_entry.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -14,11 +15,14 @@ using disk_cache::LogStoreEntry;
// Tests the behavior of a LogStoreEntry with empty streams.
TEST_F(FlashCacheTest, LogStoreEntryEmpty) {
scoped_ptr<LogStoreEntry> entry(new LogStoreEntry(log_store_.get()));
disk_cache::LogStore log_store(path_, kStorageSize);
ASSERT_TRUE(log_store.Init());
scoped_ptr<LogStoreEntry> entry(new LogStoreEntry(&log_store));
EXPECT_TRUE(entry->Init());
EXPECT_TRUE(entry->Close());
entry.reset(new LogStoreEntry(log_store_.get(), entry->id()));
entry.reset(new LogStoreEntry(&log_store, entry->id()));
EXPECT_TRUE(entry->Init());
for (int i = 0; i < disk_cache::kFlashLogStoreEntryNumStreams; ++i) {
......@@ -28,10 +32,14 @@ TEST_F(FlashCacheTest, LogStoreEntryEmpty) {
EXPECT_EQ(0, entry->ReadData(i, 0, buf, kSize));
}
EXPECT_TRUE(entry->Close());
ASSERT_TRUE(log_store.Close());
}
TEST_F(FlashCacheTest, LogStoreEntryWriteRead) {
scoped_ptr<LogStoreEntry> entry(new LogStoreEntry(log_store_.get()));
disk_cache::LogStore log_store(path_, kStorageSize);
ASSERT_TRUE(log_store.Init());
scoped_ptr<LogStoreEntry> entry(new LogStoreEntry(&log_store));
EXPECT_TRUE(entry->Init());
int sizes[disk_cache::kFlashLogStoreEntryNumStreams] = {333, 444, 555, 666};
......@@ -46,7 +54,7 @@ TEST_F(FlashCacheTest, LogStoreEntryWriteRead) {
EXPECT_TRUE(entry->Close());
int32 id = entry->id();
entry.reset(new LogStoreEntry(log_store_.get(), id));
entry.reset(new LogStoreEntry(&log_store, id));
EXPECT_TRUE(entry->Init());
for (int i = 0; i < disk_cache::kFlashLogStoreEntryNumStreams; ++i) {
......@@ -57,4 +65,5 @@ TEST_F(FlashCacheTest, LogStoreEntryWriteRead) {
}
EXPECT_TRUE(entry->Close());
EXPECT_EQ(id, entry->id());
ASSERT_TRUE(log_store.Close());
}
......@@ -11,101 +11,118 @@
namespace disk_cache {
TEST_F(FlashCacheTest, LogStoreCreateEntry) {
LogStore log_store(path_, kStorageSize);
EXPECT_TRUE(log_store.Init());
const int32 kSize = 100;
const std::string buf(kSize, 0);
int32 id;
EXPECT_TRUE(log_store_->CreateEntry(kSize, &id));
EXPECT_TRUE(log_store_->WriteData(buf.data(), kSize/2));
EXPECT_TRUE(log_store_->WriteData(buf.data(), kSize/2));
log_store_->CloseEntry(id);
EXPECT_TRUE(log_store.CreateEntry(kSize, &id));
EXPECT_TRUE(log_store.WriteData(buf.data(), kSize/2));
EXPECT_TRUE(log_store.WriteData(buf.data(), kSize/2));
log_store.CloseEntry(id);
EXPECT_TRUE(log_store.Close());
}
// Also tests reading from current segment.
TEST_F(FlashCacheTest, LogStoreOpenEntry) {
LogStore log_store(path_, kStorageSize);
EXPECT_TRUE(log_store.Init());
const int32 kSize = 100;
const std::vector<char> expected(kSize, 'b');
int32 id;
EXPECT_TRUE(log_store_->CreateEntry(kSize, &id));
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize));
log_store_->CloseEntry(id);
EXPECT_TRUE(log_store.CreateEntry(kSize, &id));
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize));
log_store.CloseEntry(id);
EXPECT_TRUE(log_store_->OpenEntry(id));
EXPECT_TRUE(log_store.OpenEntry(id));
std::vector<char> actual(kSize, 0);
EXPECT_TRUE(log_store_->ReadData(id, &actual[0], kSize, 0));
log_store_->CloseEntry(id);
EXPECT_TRUE(log_store.ReadData(id, &actual[0], kSize, 0));
log_store.CloseEntry(id);
EXPECT_EQ(expected, actual);
EXPECT_TRUE(log_store.Close());
}
// Also tests that writing advances segments.
TEST_F(FlashCacheTest, LogStoreReadFromClosedSegment) {
LogStore log_store(path_, kStorageSize);
EXPECT_TRUE(log_store.Init());
const int32 kSize = disk_cache::kFlashSegmentFreeSpace;
const std::vector<char> expected(kSize, 'a');
// First two entries go to segment 0.
int32 id1;
EXPECT_EQ(0, log_store_->write_index_);
EXPECT_TRUE(log_store_->CreateEntry(kSize/2, &id1));
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize/2));
log_store_->CloseEntry(id1);
EXPECT_EQ(0, log_store.write_index_);
EXPECT_TRUE(log_store.CreateEntry(kSize/2, &id1));
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize/2));
log_store.CloseEntry(id1);
int32 id2;
EXPECT_EQ(0, log_store_->write_index_);
EXPECT_TRUE(log_store_->CreateEntry(kSize/2, &id2));
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize/2));
log_store_->CloseEntry(id2);
EXPECT_EQ(0, log_store.write_index_);
EXPECT_TRUE(log_store.CreateEntry(kSize/2, &id2));
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize/2));
log_store.CloseEntry(id2);
// This entry goes to segment 1.
int32 id3;
EXPECT_TRUE(log_store_->CreateEntry(kSize, &id3));
EXPECT_EQ(1, log_store_->write_index_);
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize));
log_store_->CloseEntry(id3);
EXPECT_TRUE(log_store.CreateEntry(kSize, &id3));
EXPECT_EQ(1, log_store.write_index_);
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize));
log_store.CloseEntry(id3);
// We read from segment 0.
EXPECT_TRUE(log_store_->OpenEntry(id1));
EXPECT_TRUE(log_store.OpenEntry(id1));
std::vector<char> actual(kSize, 0);
EXPECT_TRUE(log_store_->ReadData(id1, &actual[0], kSize, id1));
log_store_->CloseEntry(id1);
EXPECT_TRUE(log_store.ReadData(id1, &actual[0], kSize, id1));
log_store.CloseEntry(id1);
EXPECT_EQ(expected, actual);
EXPECT_TRUE(log_store.Close());
}
TEST_F(FlashCacheTest, LogStoreReadFromCurrentAfterClose) {
LogStore log_store(path_, kStorageSize);
EXPECT_TRUE(log_store.Init());
const int32 kSize = disk_cache::kFlashSegmentFreeSpace;
const std::vector<char> expected(kSize, 'a');
int32 id1;
EXPECT_EQ(0, log_store_->write_index_);
EXPECT_TRUE(log_store_->CreateEntry(kSize/2, &id1));
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize/2));
log_store_->CloseEntry(id1);
EXPECT_EQ(0, log_store.write_index_);
EXPECT_TRUE(log_store.CreateEntry(kSize/2, &id1));
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize/2));
log_store.CloseEntry(id1);
// Create a reference to above entry.
EXPECT_TRUE(log_store_->OpenEntry(id1));
EXPECT_TRUE(log_store.OpenEntry(id1));
// This entry fills the first segment.
int32 id2;
EXPECT_EQ(0, log_store_->write_index_);
EXPECT_TRUE(log_store_->CreateEntry(kSize/2, &id2));
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize/2));
log_store_->CloseEntry(id2);
EXPECT_EQ(0, log_store.write_index_);
EXPECT_TRUE(log_store.CreateEntry(kSize/2, &id2));
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize/2));
log_store.CloseEntry(id2);
// Creating this entry forces closing of the first segment.
int32 id3;
EXPECT_TRUE(log_store_->CreateEntry(kSize, &id3));
EXPECT_EQ(1, log_store_->write_index_);
EXPECT_TRUE(log_store_->WriteData(&expected[0], kSize));
log_store_->CloseEntry(id3);
EXPECT_TRUE(log_store.CreateEntry(kSize, &id3));
EXPECT_EQ(1, log_store.write_index_);
EXPECT_TRUE(log_store.WriteData(&expected[0], kSize));
log_store.CloseEntry(id3);
// Now attempt to read from the closed segment.
std::vector<char> actual(kSize, 0);
EXPECT_TRUE(log_store_->ReadData(id1, &actual[0], kSize, id1));
log_store_->CloseEntry(id1);
EXPECT_TRUE(log_store.ReadData(id1, &actual[0], kSize, id1));
log_store.CloseEntry(id1);
EXPECT_EQ(expected, actual);
EXPECT_TRUE(log_store.Close());
}
// TODO(agayev): Add a test that confirms that in-use segment is not selected as
......
......@@ -37,8 +37,11 @@ const int32 kSegmentFreeSpace = disk_cache::kFlashSegmentSize -
} // namespace
TEST_F(FlashCacheTest, SegmentUserTracking) {
disk_cache::Storage storage(path_, kStorageSize);
ASSERT_TRUE(storage.Init());
scoped_ptr<disk_cache::Segment> segment(
new disk_cache::Segment(0, false, storage_.get()));
new disk_cache::Segment(0, false, &storage));
EXPECT_TRUE(segment->Init());
EXPECT_TRUE(segment->HasNoUsers());
......@@ -55,30 +58,36 @@ TEST_F(FlashCacheTest, SegmentUserTracking) {
}
TEST_F(FlashCacheTest, SegmentCreateDestroy) {
disk_cache::Storage storage(path_, kStorageSize);
ASSERT_TRUE(storage.Init());
int32 index = 0;
scoped_ptr<disk_cache::Segment> segment(
new disk_cache::Segment(index, false, storage_.get()));
new disk_cache::Segment(index, false, &storage));
EXPECT_TRUE(segment->Init());
EXPECT_TRUE(segment->Close());
index = num_segments_in_storage_ - 1;
segment.reset(new disk_cache::Segment(index, false, storage_.get()));
index = kNumTestSegments - 1;
segment.reset(new disk_cache::Segment(index, false, &storage));
EXPECT_TRUE(segment->Init());
EXPECT_TRUE(segment->Close());
int32 invalid_index = num_segments_in_storage_;
segment.reset(new disk_cache::Segment(invalid_index, false, storage_.get()));
int32 invalid_index = kNumTestSegments;
segment.reset(new disk_cache::Segment(invalid_index, false, &storage));
EXPECT_FALSE(segment->Init());
invalid_index = -1;
segment.reset(new disk_cache::Segment(invalid_index, false, storage_.get()));
segment.reset(new disk_cache::Segment(invalid_index, false, &storage));
EXPECT_FALSE(segment->Init());
}
TEST_F(FlashCacheTest, SegmentWriteDataReadData) {
int32 index = rand() % num_segments_in_storage_;
disk_cache::Storage storage(path_, kStorageSize);
ASSERT_TRUE(storage.Init());
int32 index = rand() % kNumTestSegments;
scoped_ptr<disk_cache::Segment> segment(
new disk_cache::Segment(index, false, storage_.get()));
new disk_cache::Segment(index, false, &storage));
EXPECT_TRUE(segment->Init());
SmallEntry entry1;
......@@ -88,7 +97,7 @@ TEST_F(FlashCacheTest, SegmentWriteDataReadData) {
segment->StoreOffset(offset);
EXPECT_TRUE(segment->Close());
segment.reset(new disk_cache::Segment(index, true, storage_.get()));
segment.reset(new disk_cache::Segment(index, true, &storage));
EXPECT_TRUE(segment->Init());
SmallEntry entry2;
EXPECT_TRUE(segment->ReadData(entry2.data, entry2.size, offset));
......@@ -97,9 +106,12 @@ TEST_F(FlashCacheTest, SegmentWriteDataReadData) {
}
TEST_F(FlashCacheTest, SegmentFillWithSmallEntries) {
int32 index = rand() % num_segments_in_storage_;
disk_cache::Storage storage(path_, kStorageSize);
ASSERT_TRUE(storage.Init());
int32 index = rand() % kNumTestSegments;
scoped_ptr<disk_cache::Segment> segment(
new disk_cache::Segment(index, false, storage_.get()));
new disk_cache::Segment(index, false, &storage));
EXPECT_TRUE(segment->Init());
SmallEntry entry;
......@@ -117,9 +129,12 @@ TEST_F(FlashCacheTest, SegmentFillWithSmallEntries) {
}
TEST_F(FlashCacheTest, SegmentFillWithLargeEntries) {
int32 index = rand() % num_segments_in_storage_;
disk_cache::Storage storage(path_, kStorageSize);
ASSERT_TRUE(storage.Init());
int32 index = rand() % kNumTestSegments;
scoped_ptr<disk_cache::Segment> segment(
new disk_cache::Segment(index, false, storage_.get()));
new disk_cache::Segment(index, false, &storage));
EXPECT_TRUE(segment->Init());
scoped_ptr<LargeEntry> entry(new LargeEntry);
......
......@@ -14,11 +14,13 @@ namespace {
const int32 kSizes[] = {512, 1024, 4096, 133, 1333, 13333};
const int32 kOffsets[] = {0, 1, 3333, 125, 12443, 4431};
const int32 kStorageSize = 16 * 1024 * 1024;
} // namespace
TEST_F(FlashCacheTest, StorageReadWrite) {
disk_cache::Storage storage(path_, kStorageSize);
EXPECT_TRUE(storage.Init());
for (size_t i = 0; i < arraysize(kOffsets); ++i) {
int32 size = kSizes[i];
int32 offset = kOffsets[i];
......@@ -28,10 +30,10 @@ TEST_F(FlashCacheTest, StorageReadWrite) {
CacheTestFillBuffer(write_buffer->data(), size, false);
bool rv = storage_->Write(write_buffer->data(), size, offset);
bool rv = storage.Write(write_buffer->data(), size, offset);
EXPECT_TRUE(rv);
rv = storage_->Read(read_buffer->data(), size, offset);
rv = storage.Read(read_buffer->data(), size, offset);
EXPECT_TRUE(rv);
EXPECT_EQ(0, memcmp(read_buffer->data(), write_buffer->data(), size));
......
......@@ -1479,7 +1479,6 @@
'disk_cache/simple/simple_index_unittest.cc',
'disk_cache/simple/simple_util_unittest.cc',
'disk_cache/storage_block_unittest.cc',
'disk_cache/flash/flash_entry_unittest.cc',
'disk_cache/flash/log_store_entry_unittest.cc',
'disk_cache/flash/log_store_unittest.cc',
'disk_cache/flash/segment_unittest.cc',
......
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