Commit 82ce8a41 authored by agayev@chromium.org's avatar agayev@chromium.org

Adding disk_cache::Entry implementation.

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


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192896 0039d316-1c4b-4281-b951-d872f2087c98
parent 74b264fd
// 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/location.h"
#include "base/message_loop_proxy.h"
#include "base/task_runner_util.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/flash/flash_entry_impl.h"
#include "net/disk_cache/flash/internal_entry.h"
namespace disk_cache {
FlashEntryImpl::FlashEntryImpl(const std::string& key,
LogStore* store,
base::MessageLoopProxy* cache_thread)
: init_(false),
key_(key),
new_internal_entry_(new InternalEntry(key, store)),
cache_thread_(cache_thread) {
memset(stream_sizes_, 0, sizeof(stream_sizes_));
}
FlashEntryImpl::FlashEntryImpl(int32 id,
LogStore* store,
base::MessageLoopProxy* cache_thread)
: init_(false),
old_internal_entry_(new InternalEntry(id, store)),
cache_thread_(cache_thread) {
}
int FlashEntryImpl::Init(const CompletionCallback& callback) {
if (new_internal_entry_) {
DCHECK(callback.is_null());
init_ = true;
return net::OK;
}
DCHECK(!callback.is_null() && old_internal_entry_);
callback_ = callback;
PostTaskAndReplyWithResult(cache_thread_, FROM_HERE,
Bind(&InternalEntry::Init, old_internal_entry_),
Bind(&FlashEntryImpl::OnInitComplete, this));
return net::ERR_IO_PENDING;
}
void FlashEntryImpl::Doom() {
DCHECK(init_);
NOTREACHED();
}
void FlashEntryImpl::Close() {
DCHECK(init_);
Release();
}
std::string FlashEntryImpl::GetKey() const {
DCHECK(init_);
return key_;
}
base::Time FlashEntryImpl::GetLastUsed() const {
DCHECK(init_);
NOTREACHED();
return base::Time::Now();
}
base::Time FlashEntryImpl::GetLastModified() const {
DCHECK(init_);
NOTREACHED();
return base::Time::Now();
}
int32 FlashEntryImpl::GetDataSize(int index) const {
DCHECK(init_);
return new_internal_entry_->GetDataSize(index);
}
int FlashEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
DCHECK(init_);
return new_internal_entry_->ReadData(index, offset, buf, buf_len, callback);
}
int FlashEntryImpl::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback,
bool truncate) {
DCHECK(init_);
return new_internal_entry_->WriteData(index, offset, buf, buf_len, callback);
}
int FlashEntryImpl::ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
DCHECK(init_);
NOTREACHED();
return net::ERR_FAILED;
}
int FlashEntryImpl::WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
DCHECK(init_);
NOTREACHED();
return net::ERR_FAILED;
}
int FlashEntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
const CompletionCallback& callback) {
DCHECK(init_);
NOTREACHED();
return net::ERR_FAILED;
}
bool FlashEntryImpl::CouldBeSparse() const {
DCHECK(init_);
NOTREACHED();
return false;
}
void FlashEntryImpl::CancelSparseIO() {
DCHECK(init_);
NOTREACHED();
}
int FlashEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
DCHECK(init_);
NOTREACHED();
return net::ERR_FAILED;
}
void FlashEntryImpl::OnInitComplete(
scoped_ptr<KeyAndStreamSizes> key_and_stream_sizes) {
DCHECK(!callback_.is_null());
if (!key_and_stream_sizes) {
callback_.Run(net::ERR_FAILED);
} else {
key_ = key_and_stream_sizes->key;
memcpy(stream_sizes_, key_and_stream_sizes->stream_sizes,
sizeof(stream_sizes_));
init_ = true;
callback_.Run(net::OK);
}
}
FlashEntryImpl::~FlashEntryImpl() {
cache_thread_->PostTask(FROM_HERE,
Bind(&InternalEntry::Close, new_internal_entry_));
}
} // namespace disk_cache
// 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_ENTRY_IMPL_H_
#define NET_DISK_CACHE_FLASH_ENTRY_IMPL_H_
#include <string>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/flash/internal_entry.h"
namespace base {
class MessageLoopProxy;
} // namespace base
namespace disk_cache {
class InternalEntry;
class IOBuffer;
class LogStore;
// We use split objects to minimize the context switches between the main thread
// and the cache thread in the most common case of creating a new entry.
//
// All calls on a new entry are served synchronously. When an object is
// destructed (via final Close() call), a message is posted to the cache thread
// to save the object to storage.
//
// When an entry is not new, every asynchronous call is posted to the cache
// thread, just as before; synchronous calls like GetKey() and GetDataSize() are
// served from the main thread.
class NET_EXPORT_PRIVATE FlashEntryImpl
: public Entry,
public base::RefCountedThreadSafe<FlashEntryImpl> {
friend class base::RefCountedThreadSafe<FlashEntryImpl>;
public:
FlashEntryImpl(const std::string& key,
LogStore* store,
base::MessageLoopProxy* cache_thread);
FlashEntryImpl(int32 id,
LogStore* store,
base::MessageLoopProxy* cache_thread);
int Init(const CompletionCallback& callback);
// disk_cache::Entry interface.
virtual void Doom() OVERRIDE;
virtual void Close() OVERRIDE;
virtual std::string GetKey() const OVERRIDE;
virtual base::Time GetLastUsed() const OVERRIDE;
virtual base::Time GetLastModified() const OVERRIDE;
virtual int32 GetDataSize(int index) const OVERRIDE;
virtual int ReadData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int WriteData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback,
bool truncate) OVERRIDE;
virtual int ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual int GetAvailableRange(int64 offset, int len, int64* start,
const CompletionCallback& callback) OVERRIDE;
virtual bool CouldBeSparse() const OVERRIDE;
virtual void CancelSparseIO() OVERRIDE;
virtual int ReadyForSparseIO(const CompletionCallback& callback) OVERRIDE;
private:
void OnInitComplete(scoped_ptr<KeyAndStreamSizes> key_and_stream_sizes);
virtual ~FlashEntryImpl();
bool init_;
std::string key_;
int stream_sizes_[kFlashLogStoreEntryNumStreams];
// Used if |this| is an newly created entry.
scoped_refptr<InternalEntry> new_internal_entry_;
// Used if |this| is an existing entry.
scoped_refptr<InternalEntry> old_internal_entry_;
// Copy of the callback for asynchronous calls on |old_internal_entry_|.
CompletionCallback callback_;
scoped_refptr<base::MessageLoopProxy> cache_thread_;
DISALLOW_COPY_AND_ASSIGN(FlashEntryImpl);
};
} // namespace disk_cache
#endif // NET_DISK_CACHE_FLASH_ENTRY_IMPL_H_
// 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();
}
// 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 "net/disk_cache/flash/internal_entry.h"
#include "base/memory/ref_counted.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/flash/log_store.h"
#include "net/disk_cache/flash/log_store_entry.h"
using net::IOBuffer;
using net::StringIOBuffer;
using net::CompletionCallback;
namespace disk_cache {
KeyAndStreamSizes::KeyAndStreamSizes() {
}
InternalEntry::InternalEntry(const std::string& key, LogStore* store)
: store_(store),
entry_(new LogStoreEntry(store_)) {
entry_->Init();
WriteKey(entry_.get(), key);
}
InternalEntry::InternalEntry(int32 id, LogStore* store)
: store_(store),
entry_(new LogStoreEntry(store_, id)) {
}
InternalEntry::~InternalEntry() {
}
scoped_ptr<KeyAndStreamSizes> InternalEntry::Init() {
scoped_ptr<KeyAndStreamSizes> null;
if (entry_->IsNew())
return null.Pass();
if (!entry_->Init())
return null.Pass();
scoped_ptr<KeyAndStreamSizes> rv(new KeyAndStreamSizes);
if (!ReadKey(entry_.get(), &rv->key))
return null.Pass();
for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i)
rv->stream_sizes[i] = entry_->GetDataSize(i+1);
return rv.Pass();
}
int32 InternalEntry::GetDataSize(int index) const {
return entry_->GetDataSize(++index);
}
int InternalEntry::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
return entry_->ReadData(++index, offset, buf, buf_len);
}
int InternalEntry::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
const CompletionCallback& callback) {
return entry_->WriteData(++index, offset, buf, buf_len);
}
void InternalEntry::Close() {
entry_->Close();
}
bool InternalEntry::WriteKey(LogStoreEntry* entry, const std::string& key) {
int key_size = static_cast<int>(key.size());
scoped_refptr<IOBuffer> key_buf(new StringIOBuffer(key));
return entry->WriteData(0, 0, key_buf, key_size) == key_size;
}
bool InternalEntry::ReadKey(LogStoreEntry* entry, std::string* key) {
int key_size = entry->GetDataSize(0);
scoped_refptr<net::IOBuffer> key_buf(new net::IOBuffer(key_size));
if (entry->ReadData(0, 0, key_buf, key_size) != key_size)
return false;
key->assign(key_buf->data(), key_size);
return true;
}
} // namespace disk_cache
// 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_INTERNAL_ENTRY_H_
#define NET_DISK_CACHE_FLASH_INTERNAL_ENTRY_H_
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/disk_cache/flash/format.h"
namespace net {
class IOBuffer;
} // namespace net
namespace disk_cache {
struct KeyAndStreamSizes {
KeyAndStreamSizes();
std::string key;
int stream_sizes[kFlashLogStoreEntryNumStreams];
};
class LogStore;
class LogStoreEntry;
// Actual entry implementation that does all the work of reading, writing and
// storing data.
class NET_EXPORT_PRIVATE InternalEntry
: public base::RefCountedThreadSafe<InternalEntry> {
friend class base::RefCountedThreadSafe<InternalEntry>;
public:
InternalEntry(const std::string& key, LogStore* store);
InternalEntry(int32 id, LogStore* store);
scoped_ptr<KeyAndStreamSizes> Init();
int32 GetDataSize(int index) const;
int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
const net::CompletionCallback& callback);
int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
const net::CompletionCallback& callback);
void Close();
private:
bool WriteKey(LogStoreEntry* entry, const std::string& key);
bool ReadKey(LogStoreEntry* entry, std::string* key);
~InternalEntry();
LogStore* store_;
scoped_ptr<LogStoreEntry> entry_;
DISALLOW_COPY_AND_ASSIGN(InternalEntry);
};
} // namespace disk_cache
#endif // NET_DISK_CACHE_FLASH_INTERNAL_ENTRY_H_
...@@ -27,7 +27,7 @@ LogStoreEntry::~LogStoreEntry() { ...@@ -27,7 +27,7 @@ LogStoreEntry::~LogStoreEntry() {
bool LogStoreEntry::Init() { bool LogStoreEntry::Init() {
DCHECK(!init_); DCHECK(!init_);
if (!ReadOnly()) { if (IsNew()) {
init_ = true; init_ = true;
return true; return true;
} }
...@@ -53,13 +53,13 @@ bool LogStoreEntry::Init() { ...@@ -53,13 +53,13 @@ bool LogStoreEntry::Init() {
bool LogStoreEntry::Close() { bool LogStoreEntry::Close() {
DCHECK(init_ && !closed_); DCHECK(init_ && !closed_);
if (ReadOnly()) { if (IsNew()) {
closed_ = deleted_ ? true : Save();
} else {
store_->CloseEntry(id_); store_->CloseEntry(id_);
if (deleted_) if (deleted_)
store_->DeleteEntry(id_, Size()); store_->DeleteEntry(id_, Size());
closed_ = true; closed_ = true;
} else {
closed_ = deleted_ ? true : Save();
} }
return closed_; return closed_;
} }
...@@ -86,7 +86,7 @@ int LogStoreEntry::ReadData(int index, int offset, net::IOBuffer* buf, ...@@ -86,7 +86,7 @@ int LogStoreEntry::ReadData(int index, int offset, net::IOBuffer* buf,
if (offset + buf_len > stream_size) if (offset + buf_len > stream_size)
buf_len = stream_size - offset; buf_len = stream_size - offset;
if (ReadOnly()) { if (!IsNew()) {
offset += streams_[index].offset; offset += streams_[index].offset;
if (store_->ReadData(id_, buf->data(), buf_len, offset)) if (store_->ReadData(id_, buf->data(), buf_len, offset))
return buf_len; return buf_len;
...@@ -122,8 +122,8 @@ void LogStoreEntry::Delete() { ...@@ -122,8 +122,8 @@ void LogStoreEntry::Delete() {
deleted_ = true; deleted_ = true;
} }
bool LogStoreEntry::ReadOnly() const { bool LogStoreEntry::IsNew() const {
return id_ != -1; return id_ == -1;
} }
bool LogStoreEntry::InvalidStream(int stream_index) const { bool LogStoreEntry::InvalidStream(int stream_index) const {
...@@ -140,7 +140,7 @@ int32 LogStoreEntry::Size() const { ...@@ -140,7 +140,7 @@ int32 LogStoreEntry::Size() const {
} }
bool LogStoreEntry::Save() { bool LogStoreEntry::Save() {
DCHECK(init_ && !closed_ && !deleted_ && !ReadOnly()); DCHECK(init_ && !closed_ && !deleted_ && IsNew());
int32 stream_sizes[kFlashLogStoreEntryNumStreams]; int32 stream_sizes[kFlashLogStoreEntryNumStreams];
COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize, COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize,
invalid_log_store_entry_header_size); invalid_log_store_entry_header_size);
......
...@@ -30,6 +30,7 @@ class NET_EXPORT_PRIVATE LogStoreEntry { ...@@ -30,6 +30,7 @@ class NET_EXPORT_PRIVATE LogStoreEntry {
bool Close(); bool Close();
int32 id() const; int32 id() const;
bool IsNew() const;
int32 GetDataSize(int index) const; int32 GetDataSize(int index) const;
int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len); int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len);
...@@ -45,7 +46,6 @@ class NET_EXPORT_PRIVATE LogStoreEntry { ...@@ -45,7 +46,6 @@ class NET_EXPORT_PRIVATE LogStoreEntry {
std::vector<char> write_buffer; std::vector<char> write_buffer;
}; };
bool ReadOnly() const;
bool InvalidStream(int stream_index) const; bool InvalidStream(int stream_index) const;
int32 Size() const; int32 Size() const;
bool Save(); bool Save();
......
...@@ -391,7 +391,11 @@ ...@@ -391,7 +391,11 @@
'disk_cache/simple/simple_index.h', 'disk_cache/simple/simple_index.h',
'disk_cache/simple/simple_synchronous_entry.cc', 'disk_cache/simple/simple_synchronous_entry.cc',
'disk_cache/simple/simple_synchronous_entry.h', 'disk_cache/simple/simple_synchronous_entry.h',
'disk_cache/flash/flash_entry_impl.cc',
'disk_cache/flash/flash_entry_impl.h',
'disk_cache/flash/format.h', 'disk_cache/flash/format.h',
'disk_cache/flash/internal_entry.cc',
'disk_cache/flash/internal_entry.h',
'disk_cache/flash/log_store.cc', 'disk_cache/flash/log_store.cc',
'disk_cache/flash/log_store.h', 'disk_cache/flash/log_store.h',
'disk_cache/flash/log_store_entry.cc', 'disk_cache/flash/log_store_entry.cc',
...@@ -1434,6 +1438,7 @@ ...@@ -1434,6 +1438,7 @@
'disk_cache/entry_unittest.cc', 'disk_cache/entry_unittest.cc',
'disk_cache/mapped_file_unittest.cc', 'disk_cache/mapped_file_unittest.cc',
'disk_cache/storage_block_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_entry_unittest.cc',
'disk_cache/flash/log_store_unittest.cc', 'disk_cache/flash/log_store_unittest.cc',
'disk_cache/flash/segment_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