summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorfelipeg@chromium.org <felipeg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-28 01:45:57 +0000
committerfelipeg@chromium.org <felipeg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-28 01:45:57 +0000
commit241ed05c1dac1f85ba3dbb51e2df88a55ace5a5c (patch)
tree07347b19dbb611cb40a3c4fc1edcfa68a31de2ab /net
parentca2902e903aba2f9964281dd875de7e4e72c08d8 (diff)
downloadchromium_src-241ed05c1dac1f85ba3dbb51e2df88a55ace5a5c.zip
chromium_src-241ed05c1dac1f85ba3dbb51e2df88a55ace5a5c.tar.gz
chromium_src-241ed05c1dac1f85ba3dbb51e2df88a55ace5a5c.tar.bz2
Add support for in memory index in SimpleCache.
BUG= Review URL: https://chromiumcodereview.appspot.com/13047003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191093 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/disk_cache/simple/simple_backend_impl.cc76
-rw-r--r--net/disk_cache/simple/simple_backend_impl.h21
-rw-r--r--net/disk_cache/simple/simple_disk_format.cc27
-rw-r--r--net/disk_cache/simple/simple_disk_format.h7
-rw-r--r--net/disk_cache/simple/simple_entry_impl.cc54
-rw-r--r--net/disk_cache/simple/simple_entry_impl.h20
-rw-r--r--net/disk_cache/simple/simple_index.cc135
-rw-r--r--net/disk_cache/simple/simple_index.h66
-rw-r--r--net/disk_cache/simple/simple_synchronous_entry.cc12
-rw-r--r--net/net.gyp3
10 files changed, 354 insertions, 67 deletions
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc
index a9da4ad..ad0d88c 100644
--- a/net/disk_cache/simple/simple_backend_impl.cc
+++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -12,6 +12,7 @@
#include "base/threading/worker_pool.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/simple/simple_entry_impl.h"
+#include "net/disk_cache/simple/simple_index.h"
using base::FilePath;
using base::MessageLoopProxy;
@@ -24,6 +25,16 @@ namespace {
const char* kSimpleBackendSubdirectory = "Simple";
+// Must run on IO Thread.
+void DeleteBackendImpl(disk_cache::Backend** backend,
+ const net::CompletionCallback& callback,
+ int result) {
+ DCHECK(*backend);
+ delete *backend;
+ *backend = NULL;
+ callback.Run(result);
+}
+
} // namespace
namespace disk_cache {
@@ -35,7 +46,7 @@ int SimpleBackendImpl::CreateBackend(
int max_bytes,
net::CacheType type,
uint32 flags,
- scoped_refptr<base::TaskRunner> task_runner,
+ scoped_refptr<base::TaskRunner> cache_thread,
net::NetLog* net_log,
Backend** backend,
const CompletionCallback& callback) {
@@ -43,16 +54,23 @@ int SimpleBackendImpl::CreateBackend(
DCHECK_EQ(net::DISK_CACHE, type);
FilePath simple_cache_path =
full_path.AppendASCII(kSimpleBackendSubdirectory);
- WorkerPool::PostTask(FROM_HERE,
- base::Bind(&SimpleBackendImpl::EnsureCachePathExists,
- simple_cache_path,
- MessageLoopProxy::current(), callback,
- backend),
- true);
+
+ // In order to not leak when the EnsureCachePathExists fails, we need to
+ // delete this in DeleteBackendImpl on the IO Thread.
+ *backend = new SimpleBackendImpl(cache_thread, simple_cache_path);
+
+ cache_thread->PostTask(FROM_HERE,
+ base::Bind(&SimpleBackendImpl::EnsureCachePathExists,
+ simple_cache_path,
+ cache_thread,
+ MessageLoopProxy::current(),
+ callback,
+ backend));
return net::ERR_IO_PENDING;
}
SimpleBackendImpl::~SimpleBackendImpl() {
+ index_->Cleanup();
}
net::CacheType SimpleBackendImpl::GetCacheType() const {
@@ -67,18 +85,20 @@ int32 SimpleBackendImpl::GetEntryCount() const {
int SimpleBackendImpl::OpenEntry(const std::string& key,
Entry** entry,
const CompletionCallback& callback) {
- return SimpleEntryImpl::OpenEntry(path_, key, entry, callback);
+ return SimpleEntryImpl::OpenEntry(
+ index_->AsWeakPtr(), path_, key, entry, callback);
}
int SimpleBackendImpl::CreateEntry(const std::string& key,
Entry** entry,
const CompletionCallback& callback) {
- return SimpleEntryImpl::CreateEntry(path_, key, entry, callback);
+ return SimpleEntryImpl::CreateEntry(
+ index_->AsWeakPtr(), path_, key, entry, callback);
}
int SimpleBackendImpl::DoomEntry(const std::string& key,
const net::CompletionCallback& callback) {
- return SimpleEntryImpl::DoomEntry(path_, key, callback);
+ return SimpleEntryImpl::DoomEntry(index_->AsWeakPtr(), path_, key, callback);
}
int SimpleBackendImpl::DoomAllEntries(const CompletionCallback& callback) {
@@ -122,33 +142,39 @@ void SimpleBackendImpl::OnExternalCacheHit(const std::string& key) {
}
SimpleBackendImpl::SimpleBackendImpl(
+ const scoped_refptr<base::TaskRunner>& cache_thread,
const FilePath& path) : path_(path) {
+ index_.reset(new SimpleIndex(cache_thread, path));
+}
+
+void SimpleBackendImpl::Initialize() {
+ index_->Initialize();
}
// static
void SimpleBackendImpl::EnsureCachePathExists(
const FilePath& path,
- const scoped_refptr<base::TaskRunner>& callback_runner,
+ const scoped_refptr<base::TaskRunner>& cache_thread,
+ const scoped_refptr<base::TaskRunner>& io_thread,
const CompletionCallback& callback,
Backend** backend) {
int result = net::OK;
if (!DirectoryExists(path) && !CreateDirectory(path))
result = net::ERR_FAILED;
- callback_runner->PostTask(FROM_HERE,
- base::Bind(&SimpleBackendImpl::OnCachePathCreated,
- result, path, callback, backend));
-}
-// static
-void SimpleBackendImpl::OnCachePathCreated(int result,
- const FilePath& path,
- const CompletionCallback& callback,
- Backend** backend) {
- if (result == net::OK)
- *backend = new SimpleBackendImpl(path);
- else
- *backend = NULL;
- callback.Run(result);
+ if (result == net::OK) {
+ DCHECK(*backend);
+ // TODO(pasko): Move the object creation and initalization out of
+ // CreateBackend and fix this downcast.
+ static_cast<SimpleBackendImpl*>(*backend)->Initialize();
+ io_thread->PostTask(FROM_HERE,
+ base::Bind(callback, result));
+ } else {
+ io_thread->PostTask(FROM_HERE,
+ base::Bind(
+ &DeleteBackendImpl,
+ backend, callback, result));
+ }
}
} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_backend_impl.h b/net/disk_cache/simple/simple_backend_impl.h
index 9e56915..fe9c7d5 100644
--- a/net/disk_cache/simple/simple_backend_impl.h
+++ b/net/disk_cache/simple/simple_backend_impl.h
@@ -25,6 +25,8 @@ namespace disk_cache {
// See http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend
+class SimpleIndex;
+
class SimpleBackendImpl : public Backend {
public:
virtual ~SimpleBackendImpl();
@@ -34,7 +36,7 @@ class SimpleBackendImpl : public Backend {
int max_bytes,
net::CacheType type,
uint32 flags,
- scoped_refptr<base::TaskRunner> thread,
+ scoped_refptr<base::TaskRunner> cache_thread,
net::NetLog* net_log,
Backend** backend,
const CompletionCallback& callback);
@@ -62,24 +64,25 @@ class SimpleBackendImpl : public Backend {
virtual void OnExternalCacheHit(const std::string& key) OVERRIDE;
private:
- explicit SimpleBackendImpl(const base::FilePath& path);
+ SimpleBackendImpl(
+ const scoped_refptr<base::TaskRunner>& cache_thread,
+ const base::FilePath& path);
// Creates the Cache directory if needed. Performs blocking IO, so it cannot
// be called on IO thread.
static void EnsureCachePathExists(
const base::FilePath& path,
- const scoped_refptr<base::TaskRunner>& callback_runner,
+ const scoped_refptr<base::TaskRunner>& cache_thread,
+ const scoped_refptr<base::TaskRunner>& io_thread,
const CompletionCallback& callback,
Backend** backend);
- // IO thread completion of cache creation, called from EnsureCachePath exists
- // to complete initialization of the cache on the IO thread.
- static void OnCachePathCreated(int result,
- const base::FilePath& path,
- const CompletionCallback& callback,
- Backend** backend);
+ // Must run on Cache Thread.
+ void Initialize();
const base::FilePath path_;
+
+ scoped_ptr<SimpleIndex> index_;
};
} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_disk_format.cc b/net/disk_cache/simple/simple_disk_format.cc
new file mode 100644
index 0000000..0207f31
--- /dev/null
+++ b/net/disk_cache/simple/simple_disk_format.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 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/simple/simple_disk_format.h"
+
+#include "base/hash.h"
+#include "base/logging.h"
+#include "base/sha1.h"
+#include "base/stringprintf.h"
+
+namespace disk_cache {
+
+std::string GetEntryHashForKey(const std::string& key) {
+ const std::string sha_hash = base::SHA1HashString(key);
+ const std::string key_hash = base::StringPrintf(
+ "%02x%02x%02x%02x%02x",
+ implicit_cast<unsigned char>(sha_hash[0]),
+ implicit_cast<unsigned char>(sha_hash[1]),
+ implicit_cast<unsigned char>(sha_hash[2]),
+ implicit_cast<unsigned char>(sha_hash[3]),
+ implicit_cast<unsigned char>(sha_hash[4]));
+ DCHECK_EQ(static_cast<size_t>(kEntryHashKeySize), key_hash.size());
+ return key_hash;
+}
+
+} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_disk_format.h b/net/disk_cache/simple/simple_disk_format.h
index 9299a42..ddc4452 100644
--- a/net/disk_cache/simple/simple_disk_format.h
+++ b/net/disk_cache/simple/simple_disk_format.h
@@ -5,6 +5,9 @@
#ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_DISK_FORMAT_H_
#define NET_DISK_CACHE_SIMPLE_SIMPLE_DISK_FORMAT_H_
+#include <string>
+
+#include "base/basictypes.h"
#include "base/port.h"
namespace disk_cache {
@@ -25,6 +28,10 @@ struct SimpleFileHeader {
uint32 key_hash;
};
+// kHashKeySize must conform to the pattern in the GetHashForKey function.
+const int kEntryHashKeySize = 10;
+std::string GetEntryHashForKey(const std::string& key);
+
} // namespace disk_cache
#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_DISK_FORMAT_H_
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 14bcee3..dde4e29 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -12,6 +12,7 @@
#include "base/threading/worker_pool.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/disk_cache/simple/simple_index.h"
#include "net/disk_cache/simple/simple_synchronous_entry.h"
namespace {
@@ -33,27 +34,34 @@ using base::WeakPtr;
using base::WorkerPool;
// static
-int SimpleEntryImpl::OpenEntry(const FilePath& path,
+int SimpleEntryImpl::OpenEntry(WeakPtr<SimpleIndex> index,
+ const FilePath& path,
const std::string& key,
Entry** entry,
const CompletionCallback& callback) {
- SynchronousCreationCallback sync_creation_callback =
- base::Bind(&SimpleEntryImpl::CreationOperationComplete, callback, entry);
- WorkerPool::PostTask(FROM_HERE,
- base::Bind(&SimpleSynchronousEntry::OpenEntry, path, key,
- MessageLoopProxy::current(),
- sync_creation_callback),
- true);
- return net::ERR_IO_PENDING;
+ if (!index || index->Has(key)) {
+ SynchronousCreationCallback sync_creation_callback =
+ base::Bind(&SimpleEntryImpl::CreationOperationComplete,
+ index, callback, key, entry);
+ WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&SimpleSynchronousEntry::OpenEntry, path,
+ key, MessageLoopProxy::current(),
+ sync_creation_callback),
+ true);
+ return net::ERR_IO_PENDING;
+ }
+ return net::ERR_FAILED;
}
// static
-int SimpleEntryImpl::CreateEntry(const FilePath& path,
+int SimpleEntryImpl::CreateEntry(WeakPtr<SimpleIndex> index,
+ const FilePath& path,
const std::string& key,
Entry** entry,
const CompletionCallback& callback) {
SynchronousCreationCallback sync_creation_callback =
- base::Bind(&SimpleEntryImpl::CreationOperationComplete, callback, entry);
+ base::Bind(&SimpleEntryImpl::CreationOperationComplete,
+ index, callback, key, entry);
WorkerPool::PostTask(FROM_HERE,
base::Bind(&SimpleSynchronousEntry::CreateEntry, path,
key, MessageLoopProxy::current(),
@@ -63,9 +71,12 @@ int SimpleEntryImpl::CreateEntry(const FilePath& path,
}
// static
-int SimpleEntryImpl::DoomEntry(const FilePath& path,
+int SimpleEntryImpl::DoomEntry(WeakPtr<SimpleIndex> index,
+ const FilePath& path,
const std::string& key,
const CompletionCallback& callback) {
+ if (index)
+ index->Remove(key);
WorkerPool::PostTask(FROM_HERE,
base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key,
MessageLoopProxy::current(), callback),
@@ -79,7 +90,7 @@ void SimpleEntryImpl::Doom() {
// underlying files. On POSIX, this is fine; the files are still open on the
// SimpleSynchronousEntry, and operations can even happen on them. The files
// will be removed from the filesystem when they are closed.
- DoomEntry(path_, key_, CompletionCallback());
+ DoomEntry(index_, path_, key_, CompletionCallback());
#else
NOTIMPLEMENTED();
#endif
@@ -206,12 +217,14 @@ int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
}
SimpleEntryImpl::SimpleEntryImpl(
- SimpleSynchronousEntry* synchronous_entry)
+ SimpleSynchronousEntry* synchronous_entry,
+ WeakPtr<SimpleIndex> index)
: ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
path_(synchronous_entry->path()),
key_(synchronous_entry->key()),
synchronous_entry_(synchronous_entry),
- synchronous_entry_in_use_by_worker_(false) {
+ synchronous_entry_in_use_by_worker_(false),
+ index_(index) {
DCHECK(synchronous_entry);
SetSynchronousData();
}
@@ -221,14 +234,21 @@ SimpleEntryImpl::~SimpleEntryImpl() {
// static
void SimpleEntryImpl::CreationOperationComplete(
+ WeakPtr<SimpleIndex> index,
const CompletionCallback& completion_callback,
+ const std::string& key,
Entry** out_entry,
SimpleSynchronousEntry* sync_entry) {
if (!sync_entry) {
completion_callback.Run(net::ERR_FAILED);
+ // If OpenEntry failed, we must remove it from our index.
+ if (index)
+ index->Remove(key);
return;
}
- *out_entry = new SimpleEntryImpl(sync_entry);
+ if (index)
+ index->Insert(sync_entry->key());
+ *out_entry = new SimpleEntryImpl(sync_entry, index);
completion_callback.Run(net::OK);
}
@@ -256,12 +276,10 @@ void SimpleEntryImpl::EntryOperationComplete(
void SimpleEntryImpl::SetSynchronousData() {
DCHECK(!synchronous_entry_in_use_by_worker_);
-
// TODO(felipeg): These copies to avoid data races are not optimal. While
// adding an IO thread index (for fast misses etc...), we can store this data
// in that structure. This also solves problems with last_used() on ext4
// filesystems not being accurate.
-
last_used_ = synchronous_entry_->last_used();
last_modified_ = synchronous_entry_->last_modified();
for (int i = 0; i < kSimpleEntryFileCount; ++i)
diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h
index c0ae78c..353ee4a8 100644
--- a/net/disk_cache/simple/simple_entry_impl.h
+++ b/net/disk_cache/simple/simple_entry_impl.h
@@ -11,6 +11,8 @@
#include "base/memory/weak_ptr.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/simple/simple_disk_format.h"
+#include "net/disk_cache/simple/simple_index.h"
+
namespace net {
class IOBuffer;
@@ -25,17 +27,20 @@ class SimpleSynchronousEntry;
// on the worker thread.
class SimpleEntryImpl : public Entry {
public:
- static int OpenEntry(const base::FilePath& path,
+ static int OpenEntry(base::WeakPtr<SimpleIndex> index,
+ const base::FilePath& path,
const std::string& key,
Entry** entry,
const CompletionCallback& callback);
- static int CreateEntry(const base::FilePath& path,
+ static int CreateEntry(base::WeakPtr<SimpleIndex> index,
+ const base::FilePath& path,
const std::string& key,
Entry** entry,
const CompletionCallback& callback);
- static int DoomEntry(const base::FilePath& path,
+ static int DoomEntry(base::WeakPtr<SimpleIndex> index,
+ const base::FilePath& path,
const std::string& key,
const CompletionCallback& callback);
@@ -74,7 +79,8 @@ class SimpleEntryImpl : public Entry {
virtual int ReadyForSparseIO(const CompletionCallback& callback) OVERRIDE;
private:
- explicit SimpleEntryImpl(SimpleSynchronousEntry* synchronous_entry);
+ SimpleEntryImpl(SimpleSynchronousEntry* synchronous_entry,
+ base::WeakPtr<SimpleIndex> index);
virtual ~SimpleEntryImpl();
@@ -83,7 +89,9 @@ class SimpleEntryImpl : public Entry {
// and passes it back to the caller via |out_entry|. Also runs
// |completion_callback|.
static void CreationOperationComplete(
+ base::WeakPtr<SimpleIndex> index,
const CompletionCallback& completion_callback,
+ const std::string& key,
Entry** out_entry,
SimpleSynchronousEntry* sync_entry);
@@ -123,9 +131,11 @@ class SimpleEntryImpl : public Entry {
SimpleSynchronousEntry* synchronous_entry_;
// Set to true when a worker operation is posted on the |synchronous_entry_|,
- // and false after. Used to insure thread safety by not allowing multiple
+ // and false after. Used to ensure thread safety by not allowing multiple
// threads to access the |synchronous_entry_| simultaneously.
bool synchronous_entry_in_use_by_worker_;
+
+ base::WeakPtr<SimpleIndex> index_;
};
} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
new file mode 100644
index 0000000..1004888
--- /dev/null
+++ b/net/disk_cache/simple/simple_index.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2013 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/simple/simple_index.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/message_loop.h"
+#include "base/task_runner.h"
+#include "base/threading/worker_pool.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/disk_cache/simple/simple_disk_format.h"
+
+
+namespace {
+
+bool WriteHashKeyToFile(const base::PlatformFile& file,
+ size_t offset,
+ const std::string& hash_key) {
+ // Append the hash_key to the index file.
+ if (base::WritePlatformFile(file, offset, hash_key.data(), hash_key.size()) !=
+ implicit_cast<int>(hash_key.size())) {
+ LOG(ERROR) << "Failed to write index file.";
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace disk_cache {
+
+SimpleIndex::SimpleIndex(
+ const scoped_refptr<base::TaskRunner>& cache_thread,
+ const base::FilePath& path)
+ : path_(path),
+ cache_thread_(cache_thread) {
+ index_filename_ = path_.AppendASCII("simple-index");
+}
+
+bool SimpleIndex::Initialize() {
+ if (!OpenIndexFile())
+ return false;
+ // TODO(felipeg): Add a checksum to the index file.
+ // TODO(felipeg): If loading the index file fails, we should list all the
+ // files in the directory.
+ // Both TODOs above should be fixed before the field experiment.
+ char hash_key[kEntryHashKeySize];
+ int index_file_offset = 0;
+ while(base::ReadPlatformFile(index_file_,
+ index_file_offset,
+ hash_key,
+ kEntryHashKeySize) == kEntryHashKeySize) {
+ index_file_offset += kEntryHashKeySize;
+ entries_set_.insert(std::string(hash_key, kEntryHashKeySize));
+ }
+
+ CloseIndexFile();
+ return true;
+}
+
+void SimpleIndex::Insert(const std::string& key) {
+ std::string hash_key = GetEntryHashForKey(key);
+ entries_set_.insert(hash_key);
+}
+
+void SimpleIndex::Remove(const std::string& key) {
+ entries_set_.erase(GetEntryHashForKey(key));
+}
+
+bool SimpleIndex::Has(const std::string& key) const {
+ return entries_set_.count(GetEntryHashForKey(key)) != 0;
+}
+
+void SimpleIndex::Cleanup() {
+ scoped_ptr<std::string> buffer(new std::string());
+ buffer->reserve(kEntryHashKeySize * entries_set_.size());
+ for (EntrySet::const_iterator it = entries_set_.begin();
+ it != entries_set_.end(); ++it) {
+ buffer->append(*it);
+ }
+ cache_thread_->PostTask(FROM_HERE,
+ base::Bind(&SimpleIndex::UpdateFile,
+ index_filename_,
+ path_.AppendASCII("index_temp"),
+ base::Passed(&buffer)));
+}
+
+SimpleIndex::~SimpleIndex() {
+ CloseIndexFile();
+}
+
+bool SimpleIndex::OpenIndexFile() {
+ base::PlatformFileError error;
+ index_file_ = base::CreatePlatformFile(index_filename_,
+ base::PLATFORM_FILE_OPEN_ALWAYS |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE,
+ NULL,
+ &error);
+ if (error != base::PLATFORM_FILE_OK) {
+ LOG(ERROR) << "Error opening file " << index_filename_.value();
+ return false;
+ }
+ return true;
+}
+
+bool SimpleIndex::CloseIndexFile() {
+ return base::ClosePlatformFile(index_file_);
+}
+
+// static
+void SimpleIndex::UpdateFile(const base::FilePath& index_filename,
+ const base::FilePath& temp_filename,
+ scoped_ptr<std::string> buffer) {
+ // TODO(felipeg): Add a checksum to the file.
+ int bytes_written = file_util::WriteFile(
+ temp_filename, buffer->data(), buffer->size());
+ DCHECK_EQ(bytes_written, implicit_cast<int>(buffer->size()));
+ if (bytes_written != static_cast<int>(buffer->size())) {
+ // TODO(felipeg): Add better error handling.
+ LOG(ERROR) << "Could not write Simple Cache index to temporary file: "
+ << temp_filename.value();
+ file_util::Delete(temp_filename, /* recursive = */ false);
+ return;
+ }
+
+ // Swap temp and index_file.
+ bool result = file_util::ReplaceFile(temp_filename, index_filename);
+ DCHECK(result);
+}
+
+} // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_index.h b/net/disk_cache/simple/simple_index.h
new file mode 100644
index 0000000..ce0379b
--- /dev/null
+++ b/net/disk_cache/simple/simple_index.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2013 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_SIMPLE_SIMPLE_INDEX_H_
+#define NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "net/disk_cache/disk_cache.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace disk_cache {
+
+// This class is not Thread-safe.
+class SimpleIndex
+ : public base::SupportsWeakPtr<SimpleIndex> {
+ public:
+ SimpleIndex(
+ const scoped_refptr<base::TaskRunner>& cache_thread,
+ const base::FilePath& path);
+
+ virtual ~SimpleIndex();
+
+ // Should be called on CacheThread.
+ bool Initialize();
+
+ void Insert(const std::string& key);
+ void Remove(const std::string& key);
+ bool Has(const std::string& key) const;
+
+ void Cleanup();
+
+ private:
+ typedef std::set<std::string> EntrySet;
+
+ bool OpenIndexFile();
+ bool CloseIndexFile();
+
+ static void UpdateFile(const base::FilePath& index_filename,
+ const base::FilePath& temp_filename,
+ scoped_ptr<std::string> buffer);
+
+ const base::FilePath path_;
+
+ EntrySet entries_set_;
+
+ base::FilePath index_filename_;
+ base::PlatformFile index_file_;
+
+ // We keep the thread from where Initialize() method has been called so that
+ // we run the Cleanup method in the same thread. Usually that should be the
+ // CacheThread.
+ scoped_refptr<base::TaskRunner> cache_thread_;
+};
+
+} // namespace disk_cache
+
+#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index 9f5c91b..cd88df9 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -40,13 +40,8 @@ using base::WritePlatformFile;
namespace {
std::string GetFilenameForKeyAndIndex(const std::string& key, int index) {
- const std::string sha_hash = base::SHA1HashString(key);
- return base::StringPrintf("%02x%02x%02x%02x%02x_%1d",
- implicit_cast<unsigned char>(sha_hash[0]),
- implicit_cast<unsigned char>(sha_hash[1]),
- implicit_cast<unsigned char>(sha_hash[2]),
- implicit_cast<unsigned char>(sha_hash[3]),
- implicit_cast<unsigned char>(sha_hash[4]), index);
+ return disk_cache::GetEntryHashForKey(key) +
+ base::StringPrintf("_%1d", index);
}
int32 DataSizeFromKeyAndFileSize(size_t key_size, int64 file_size) {
@@ -89,7 +84,6 @@ void SimpleSynchronousEntry::CreateEntry(
const SynchronousCreationCallback& callback) {
SimpleSynchronousEntry* sync_entry =
new SimpleSynchronousEntry(callback_runner, path, key);
-
if (!sync_entry->InitializeForCreate()) {
delete sync_entry;
sync_entry = NULL;
@@ -279,7 +273,6 @@ bool SimpleSynchronousEntry::InitializeForCreate() {
DLOG(WARNING) << "Could not create platform files.";
return false;
}
-
for (int i = 0; i < kSimpleEntryFileCount; ++i) {
SimpleFileHeader header;
header.initial_magic_number = kSimpleInitialMagicNumber;
@@ -302,7 +295,6 @@ bool SimpleSynchronousEntry::InitializeForCreate() {
return false;
}
}
-
initialized_ = true;
return true;
}
diff --git a/net/net.gyp b/net/net.gyp
index b4331ea..533c53a 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -384,9 +384,12 @@
'disk_cache/trace.h',
'disk_cache/simple/simple_backend_impl.cc',
'disk_cache/simple/simple_backend_impl.h',
+ 'disk_cache/simple/simple_disk_format.cc',
'disk_cache/simple/simple_disk_format.h',
'disk_cache/simple/simple_entry_impl.cc',
'disk_cache/simple/simple_entry_impl.h',
+ 'disk_cache/simple/simple_index.cc',
+ 'disk_cache/simple/simple_index.h',
'disk_cache/simple/simple_synchronous_entry.cc',
'disk_cache/simple/simple_synchronous_entry.h',
'disk_cache/flash/format.h',