Commit 3c173072 authored by Ben Kelly's avatar Ben Kelly Committed by Commit Bot

SimpleCache: Support access from sequences.

Historically the simple disk_cache backend has assumed all accesses
occurred on the browser IO thread.  In order to support running
cache_storage on a separate sequence this CL removes the IO thread
assumptions from simple disk_cache.

Bug: 960012
Change-Id: Idde0f6049aad403318d32b65a160515ee5d67fa6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1643234Reviewed-by: default avatarMaks Orlovich <morlovich@chromium.org>
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Cr-Commit-Position: refs/heads/master@{#665990}
parent e7ba15aa
......@@ -23,12 +23,12 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/sequenced_task_runner.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "base/trace_event/process_memory_dump.h"
......@@ -286,7 +286,7 @@ net::Error SimpleBackendImpl::Init(CompletionOnceCallback completion_callback) {
base::MakeRefCounted<net::PrioritizedTaskRunner>(worker_pool);
index_ = std::make_unique<SimpleIndex>(
base::ThreadTaskRunnerHandle::Get(), cleanup_tracker_.get(), this,
base::SequencedTaskRunnerHandle::Get(), cleanup_tracker_.get(), this,
GetCacheType(),
std::make_unique<SimpleIndexFile>(cache_runner_, worker_pool.get(),
GetCacheType(), path_));
......
......@@ -41,15 +41,17 @@ namespace disk_cache {
// SimpleBackendImpl is a new cache backend that stores entries in individual
// files.
// See http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend
// See
// http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend
//
// The SimpleBackendImpl provides safe iteration; mutating entries during
// iteration cannot cause a crash. It is undefined whether entries created or
// destroyed during the iteration will be included in any pre-existing
// iterations.
//
// The non-static functions below must be called on the IO thread unless
// otherwise stated.
// The non-static functions below must be called on the source creation sequence
// unless otherwise stated. Historically the source creation sequence has been
// the IO thread, but the simple backend may now be used from other sequences.
class BackendCleanupTracker;
class SimpleEntryImpl;
......@@ -204,8 +206,8 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend,
Int64CompletionOnceCallback callback,
int result);
// Try to create the directory if it doesn't exist. This must run on the IO
// thread.
// Try to create the directory if it doesn't exist. This must run on the
// source creation sequence.
static DiskStatResult InitCacheStructureOnDisk(const base::FilePath& path,
uint64_t suggested_max_size,
net::CacheType cache_type);
......
This diff is collapsed.
......@@ -13,7 +13,7 @@
#include "base/containers/queue.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "base/sequence_checker.h"
#include "net/base/cache_type.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
......@@ -44,9 +44,9 @@ class SimpleFileTracker;
class SimpleSynchronousEntry;
struct SimpleEntryCreationResults;
// SimpleEntryImpl is the IO thread interface to an entry in the very simple
// disk cache. It proxies for the SimpleSynchronousEntry, which performs IO
// on the worker thread.
// SimpleEntryImpl is the source task_runner interface to an entry in the very
// simple disk cache. It proxies for the SimpleSynchronousEntry, which performs
// IO on the worker thread.
class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
public base::RefCounted<SimpleEntryImpl> {
friend class base::RefCounted<SimpleEntryImpl>;
......@@ -307,7 +307,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
// Called after an asynchronous write completes.
// |buf| parameter brings back a reference to net::IOBuffer to the original
// thread, so that we can reduce cross thread malloc/free pair.
// sequence, so that we can reduce cross thread malloc/free pair.
// See http://crbug.com/708644 for details.
void WriteOperationComplete(
int stream_index,
......@@ -367,9 +367,10 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
std::unique_ptr<ActiveEntryProxy> active_entry_proxy_;
// All nonstatic SimpleEntryImpl methods should always be called on the IO
// thread, in all cases. |io_thread_checker_| documents and enforces this.
base::ThreadChecker io_thread_checker_;
// All nonstatic SimpleEntryImpl methods should always be called on the
// source creation sequence, in all cases. |sequence_checker_| documents and
// enforces this.
SEQUENCE_CHECKER(sequence_checker_);
const base::WeakPtr<SimpleBackendImpl> backend_;
SimpleFileTracker* const file_tracker_;
......
......@@ -177,7 +177,7 @@ bool EntryMetadata::Deserialize(net::CacheType cache_type,
}
SimpleIndex::SimpleIndex(
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
scoped_refptr<BackendCleanupTracker> cleanup_tracker,
SimpleIndexDelegate* delegate,
net::CacheType cache_type,
......@@ -186,7 +186,7 @@ SimpleIndex::SimpleIndex(
delegate_(delegate),
cache_type_(cache_type),
index_file_(std::move(index_file)),
io_thread_(io_thread),
task_runner_(task_runner),
// Creating the callback once so it is reused every time
// write_to_disk_timer_.Start() is called.
write_to_disk_cb_(base::Bind(&SimpleIndex::WriteToDisk,
......@@ -194,7 +194,7 @@ SimpleIndex::SimpleIndex(
INDEX_WRITE_REASON_IDLE)) {}
SimpleIndex::~SimpleIndex() {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Fail all callbacks waiting for the index to come up.
for (auto it = to_run_when_initialized_.begin(),
......@@ -205,7 +205,7 @@ SimpleIndex::~SimpleIndex() {
}
void SimpleIndex::Initialize(base::Time cache_mtime) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_ANDROID)
if (app_status_listener_) {
......@@ -238,9 +238,9 @@ void SimpleIndex::SetMaxSize(uint64_t max_bytes) {
}
net::Error SimpleIndex::ExecuteWhenReady(net::CompletionOnceCallback task) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (initialized_)
io_thread_->PostTask(FROM_HERE, base::BindOnce(std::move(task), net::OK));
task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(task), net::OK));
else
to_run_when_initialized_.push_back(std::move(task));
return net::ERR_IO_PENDING;
......@@ -316,7 +316,7 @@ size_t SimpleIndex::EstimateMemoryUsage() const {
}
base::Time SimpleIndex::GetLastUsedTime(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(cache_type_, net::APP_CACHE);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
......@@ -336,7 +336,7 @@ bool SimpleIndex::HasPendingWrite() const {
}
void SimpleIndex::Insert(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Upon insert we don't know yet the size of the entry.
// It will be updated later when the SimpleEntryImpl finishes opening or
// creating the new entry, and then UpdateEntrySize will be called.
......@@ -355,7 +355,7 @@ void SimpleIndex::Insert(uint64_t entry_hash) {
}
void SimpleIndex::Remove(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool need_write = false;
auto it = entries_set_.find(entry_hash);
if (it != entries_set_.end()) {
......@@ -372,13 +372,13 @@ void SimpleIndex::Remove(uint64_t entry_hash) {
}
bool SimpleIndex::Has(uint64_t hash) const {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If not initialized, always return true, forcing it to go to the disk.
return !initialized_ || entries_set_.count(hash) > 0;
}
uint8_t SimpleIndex::GetEntryInMemoryData(uint64_t entry_hash) const {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
return 0;
......@@ -386,7 +386,7 @@ uint8_t SimpleIndex::GetEntryInMemoryData(uint64_t entry_hash) const {
}
void SimpleIndex::SetEntryInMemoryData(uint64_t entry_hash, uint8_t value) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
return;
......@@ -394,7 +394,7 @@ void SimpleIndex::SetEntryInMemoryData(uint64_t entry_hash, uint8_t value) {
}
bool SimpleIndex::UseIfExists(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Always update the last used time, even if it is during initialization.
// It will be merged later.
auto it = entries_set_.find(entry_hash);
......@@ -410,7 +410,7 @@ bool SimpleIndex::UseIfExists(uint64_t entry_hash) {
}
void SimpleIndex::StartEvictionIfNeeded() {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (eviction_in_progress_ || cache_size_ <= high_watermark_)
return;
// Take all live key hashes from the index and sort them by time.
......@@ -467,7 +467,7 @@ void SimpleIndex::StartEvictionIfNeeded() {
}
int32_t SimpleIndex::GetTrailerPrefetchSize(uint64_t entry_hash) const {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(cache_type_, net::APP_CACHE);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
......@@ -476,7 +476,7 @@ int32_t SimpleIndex::GetTrailerPrefetchSize(uint64_t entry_hash) const {
}
void SimpleIndex::SetTrailerPrefetchSize(uint64_t entry_hash, int32_t size) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(cache_type_, net::APP_CACHE);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
......@@ -489,7 +489,7 @@ void SimpleIndex::SetTrailerPrefetchSize(uint64_t entry_hash, int32_t size) {
bool SimpleIndex::UpdateEntrySize(uint64_t entry_hash,
base::StrictNumeric<uint32_t> entry_size) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = entries_set_.find(entry_hash);
if (it == entries_set_.end())
return false;
......@@ -505,7 +505,7 @@ bool SimpleIndex::UpdateEntrySize(uint64_t entry_hash,
}
void SimpleIndex::EvictionDone(int result) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Ignore the result of eviction. We did our best.
eviction_in_progress_ = false;
......@@ -549,7 +549,7 @@ bool SimpleIndex::UpdateEntryIteratorSize(
EntrySet::iterator* it,
base::StrictNumeric<uint32_t> entry_size) {
// Update the total cache size with the new entry size.
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GE(cache_size_, (*it)->second.GetEntrySize());
uint32_t original_size = (*it)->second.GetEntrySize();
cache_size_ -= (*it)->second.GetEntrySize();
......@@ -563,7 +563,7 @@ bool SimpleIndex::UpdateEntryIteratorSize(
void SimpleIndex::MergeInitializingSet(
std::unique_ptr<SimpleIndexLoadResult> load_result) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
EntrySet* index_file_entries = &load_result->entries;
......@@ -619,7 +619,7 @@ void SimpleIndex::MergeInitializingSet(
for (auto it = to_run_when_initialized_.begin(),
end = to_run_when_initialized_.end();
it != end; ++it) {
io_thread_->PostTask(FROM_HERE, base::BindOnce(std::move(*it), net::OK));
task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(*it), net::OK));
}
to_run_when_initialized_.clear();
}
......@@ -627,7 +627,7 @@ void SimpleIndex::MergeInitializingSet(
#if defined(OS_ANDROID)
void SimpleIndex::OnApplicationStateChange(
base::android::ApplicationState state) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// For more info about android activities, see:
// developer.android.com/training/basics/activity-lifecycle/pausing.html
if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
......@@ -641,7 +641,7 @@ void SimpleIndex::OnApplicationStateChange(
#endif
void SimpleIndex::WriteToDisk(IndexWriteToDiskReason reason) {
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!initialized_)
return;
......
......@@ -20,8 +20,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
......@@ -134,7 +134,7 @@ class NET_EXPORT_PRIVATE SimpleIndex
typedef std::vector<uint64_t> HashList;
SimpleIndex(const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
SimpleIndex(const scoped_refptr<base::SequencedTaskRunner>& task_runner,
scoped_refptr<BackendCleanupTracker> cleanup_tracker,
SimpleIndexDelegate* delegate,
net::CacheType cache_type,
......@@ -289,11 +289,12 @@ class NET_EXPORT_PRIVATE SimpleIndex
std::unique_ptr<SimpleIndexFile> index_file_;
scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// All nonstatic SimpleEntryImpl methods should always be called on the IO
// thread, in all cases. |io_thread_checker_| documents and enforces this.
base::ThreadChecker io_thread_checker_;
// All nonstatic SimpleEntryImpl methods should always be called on its
// creation sequance, in all cases. |sequence_checker_| documents and
// enforces this.
SEQUENCE_CHECKER(sequence_checker_);
// Timestamp of the last time we wrote the index to disk.
// PostponeWritingToDisk() may give up postponing and allow the write if it
......
......@@ -48,7 +48,7 @@ struct NET_EXPORT_PRIVATE SimpleIndexLoadResult {
// the format see |SimpleIndexFile::Serialize()| and
// |SimpleIndexFile::LoadFromDisk()|.
//
// The non-static methods must run on the IO thread. All the real
// The non-static methods must run on the source creation sequence. All the real
// work is done in the static methods, which are run on the cache thread
// or in worker threads. Synchronization between methods is the
// responsibility of the caller.
......@@ -121,7 +121,8 @@ class NET_EXPORT_PRIVATE SimpleIndexFile {
int64_t size)>;
// When loading the entries from disk, add this many extra hash buckets to
// prevent reallocation on the IO thread when merging in new live entries.
// prevent reallocation on the creation sequence when merging in new live
// entries.
static const int kExtraSizeForMerge = 512;
// Synchronous (IO performing) implementation of LoadIndexEntries.
......
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