summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-08 21:16:53 +0000
committeragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-08 21:16:53 +0000
commit82ce8a41cfb0bff9902bce4aa3adc726c1f0a2cf (patch)
treef3dc58413e1f9e62142bb85af9e48d98bf3b1052
parent74b264fd1b3aaeef944d1c50173e85f7965afbd1 (diff)
downloadchromium_src-82ce8a41cfb0bff9902bce4aa3adc726c1f0a2cf.zip
chromium_src-82ce8a41cfb0bff9902bce4aa3adc726c1f0a2cf.tar.gz
chromium_src-82ce8a41cfb0bff9902bce4aa3adc726c1f0a2cf.tar.bz2
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
-rw-r--r--net/disk_cache/flash/flash_entry_impl.cc149
-rw-r--r--net/disk_cache/flash/flash_entry_impl.h98
-rw-r--r--net/disk_cache/flash/flash_entry_unittest.cc48
-rw-r--r--net/disk_cache/flash/internal_entry.cc86
-rw-r--r--net/disk_cache/flash/internal_entry.h63
-rw-r--r--net/disk_cache/flash/log_store_entry.cc16
-rw-r--r--net/disk_cache/flash/log_store_entry.h2
-rw-r--r--net/net.gyp5
8 files changed, 458 insertions, 9 deletions
diff --git a/net/disk_cache/flash/flash_entry_impl.cc b/net/disk_cache/flash/flash_entry_impl.cc
new file mode 100644
index 0000000..3d64b03
--- /dev/null
+++ b/net/disk_cache/flash/flash_entry_impl.cc
@@ -0,0 +1,149 @@
+// 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
diff --git a/net/disk_cache/flash/flash_entry_impl.h b/net/disk_cache/flash/flash_entry_impl.h
new file mode 100644
index 0000000..32f489f
--- /dev/null
+++ b/net/disk_cache/flash/flash_entry_impl.h
@@ -0,0 +1,98 @@
+// 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_
diff --git a/net/disk_cache/flash/flash_entry_unittest.cc b/net/disk_cache/flash/flash_entry_unittest.cc
new file mode 100644
index 0000000..ea6eaaac
--- /dev/null
+++ b/net/disk_cache/flash/flash_entry_unittest.cc
@@ -0,0 +1,48 @@
+// 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();
+}
diff --git a/net/disk_cache/flash/internal_entry.cc b/net/disk_cache/flash/internal_entry.cc
new file mode 100644
index 0000000..14659732
--- /dev/null
+++ b/net/disk_cache/flash/internal_entry.cc
@@ -0,0 +1,86 @@
+// 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
diff --git a/net/disk_cache/flash/internal_entry.h b/net/disk_cache/flash/internal_entry.h
new file mode 100644
index 0000000..eeb2793
--- /dev/null
+++ b/net/disk_cache/flash/internal_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_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_
diff --git a/net/disk_cache/flash/log_store_entry.cc b/net/disk_cache/flash/log_store_entry.cc
index 7909c66..1e26ec5 100644
--- a/net/disk_cache/flash/log_store_entry.cc
+++ b/net/disk_cache/flash/log_store_entry.cc
@@ -27,7 +27,7 @@ LogStoreEntry::~LogStoreEntry() {
bool LogStoreEntry::Init() {
DCHECK(!init_);
- if (!ReadOnly()) {
+ if (IsNew()) {
init_ = true;
return true;
}
@@ -53,13 +53,13 @@ bool LogStoreEntry::Init() {
bool LogStoreEntry::Close() {
DCHECK(init_ && !closed_);
- if (ReadOnly()) {
+ if (IsNew()) {
+ closed_ = deleted_ ? true : Save();
+ } else {
store_->CloseEntry(id_);
if (deleted_)
store_->DeleteEntry(id_, Size());
closed_ = true;
- } else {
- closed_ = deleted_ ? true : Save();
}
return closed_;
}
@@ -86,7 +86,7 @@ int LogStoreEntry::ReadData(int index, int offset, net::IOBuffer* buf,
if (offset + buf_len > stream_size)
buf_len = stream_size - offset;
- if (ReadOnly()) {
+ if (!IsNew()) {
offset += streams_[index].offset;
if (store_->ReadData(id_, buf->data(), buf_len, offset))
return buf_len;
@@ -122,8 +122,8 @@ void LogStoreEntry::Delete() {
deleted_ = true;
}
-bool LogStoreEntry::ReadOnly() const {
- return id_ != -1;
+bool LogStoreEntry::IsNew() const {
+ return id_ == -1;
}
bool LogStoreEntry::InvalidStream(int stream_index) const {
@@ -140,7 +140,7 @@ int32 LogStoreEntry::Size() const {
}
bool LogStoreEntry::Save() {
- DCHECK(init_ && !closed_ && !deleted_ && !ReadOnly());
+ DCHECK(init_ && !closed_ && !deleted_ && IsNew());
int32 stream_sizes[kFlashLogStoreEntryNumStreams];
COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize,
invalid_log_store_entry_header_size);
diff --git a/net/disk_cache/flash/log_store_entry.h b/net/disk_cache/flash/log_store_entry.h
index ef184ee1..5791949 100644
--- a/net/disk_cache/flash/log_store_entry.h
+++ b/net/disk_cache/flash/log_store_entry.h
@@ -30,6 +30,7 @@ class NET_EXPORT_PRIVATE LogStoreEntry {
bool Close();
int32 id() const;
+ bool IsNew() const;
int32 GetDataSize(int index) const;
int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len);
@@ -45,7 +46,6 @@ class NET_EXPORT_PRIVATE LogStoreEntry {
std::vector<char> write_buffer;
};
- bool ReadOnly() const;
bool InvalidStream(int stream_index) const;
int32 Size() const;
bool Save();
diff --git a/net/net.gyp b/net/net.gyp
index fcbb2e8..4a4f1fa 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -391,7 +391,11 @@
'disk_cache/simple/simple_index.h',
'disk_cache/simple/simple_synchronous_entry.cc',
'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/internal_entry.cc',
+ 'disk_cache/flash/internal_entry.h',
'disk_cache/flash/log_store.cc',
'disk_cache/flash/log_store.h',
'disk_cache/flash/log_store_entry.cc',
@@ -1434,6 +1438,7 @@
'disk_cache/entry_unittest.cc',
'disk_cache/mapped_file_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',