Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Unified Diff: net/disk_cache/simple/simple_entry_impl.cc

Issue 14130015: Support overlapping operations on the SimpleEntryImpl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add unittests Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/disk_cache/simple/simple_entry_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/disk_cache/simple/simple_entry_impl.cc
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index 1917a88715091ac1a37be9dae3b8fd104b6f4edf..7d2de7a76a99a767740c95f445d202980ef289fd 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -88,6 +88,7 @@ int SimpleEntryImpl::DoomEntry(WeakPtr<SimpleIndex> index,
void SimpleEntryImpl::Doom() {
DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(!operation_running_);
#if defined(OS_POSIX)
// This call to static SimpleEntryImpl::DoomEntry() will just erase the
// underlying files. On POSIX, this is fine; the files are still open on the
@@ -101,12 +102,22 @@ void SimpleEntryImpl::Doom() {
void SimpleEntryImpl::Close() {
DCHECK(io_thread_checker_.CalledOnValidThread());
- if (!synchronous_entry_in_use_by_worker_) {
- WorkerPool::PostTask(FROM_HERE,
- base::Bind(&SimpleSynchronousEntry::Close,
- base::Unretained(synchronous_entry_)),
- true);
+ if (operation_running_) {
gavinp 2013/04/17 11:04:36 I think if you rebase on top of https://codereview
felipeg 2013/04/17 11:51:22 If I am going to land before you, I think I should
gavinp 2013/04/17 13:13:45 Agreed. And whoever wins the race dodges the merge
+ // Postpone close operation.
+ // Push the close operation to the end of the line. This way we run all
+ // operations before we are able close.
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::Close,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
}
+ DCHECK(operations_.size() == 0);
+ DCHECK(!operation_running_);
+
+ WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&SimpleSynchronousEntry::Close,
+ base::Unretained(synchronous_entry_)),
+ true);
// Entry::Close() is expected to release this entry. See disk_cache.h for
// details.
delete this;
@@ -138,15 +149,32 @@ int SimpleEntryImpl::ReadData(int index,
int buf_len,
const CompletionCallback& callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does
- // make overlapping read requests when multiple transactions access the same
- // entry as read only. This might make calling SimpleSynchronousEntry::Close()
- // correctly more tricky (see SimpleEntryImpl::EntryOperationComplete).
- if (synchronous_entry_in_use_by_worker_) {
- NOTIMPLEMENTED();
- CHECK(false);
- }
- synchronous_entry_in_use_by_worker_ = true;
+ if (index < 0 || index >= kSimpleEntryFileCount || buf_len < 0)
+ return net::ERR_INVALID_ARGUMENT;
+ if (offset >= data_size_[index] || offset < 0 || !buf_len)
+ return 0;
+ // TODO(felipeg): Optimization: Add support for truly parallel read
+ // operations.
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::ReadDataInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ callback));
+ RunNextOperationIfNeeded();
+ return net::ERR_IO_PENDING;
+}
+
+void SimpleEntryImpl::ReadDataInternal(int index,
gavinp 2013/04/17 11:04:36 Method ordering: this should go to the end of the
felipeg 2013/04/17 11:51:22 Done.
+ int offset,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(!operation_running_);
+ operation_running_ = true;
if (index_)
index_->UseIfExists(key_);
SynchronousOperationCallback sync_operation_callback =
@@ -156,10 +184,9 @@ int SimpleEntryImpl::ReadData(int index,
WorkerPool::PostTask(FROM_HERE,
base::Bind(&SimpleSynchronousEntry::ReadData,
base::Unretained(synchronous_entry_),
- index, offset, make_scoped_refptr(buf),
+ index, offset, buf,
buf_len, sync_operation_callback),
true);
- return net::ERR_IO_PENDING;
}
int SimpleEntryImpl::WriteData(int index,
@@ -169,13 +196,41 @@ int SimpleEntryImpl::WriteData(int index,
const CompletionCallback& callback,
bool truncate) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- if (synchronous_entry_in_use_by_worker_) {
- NOTIMPLEMENTED();
- CHECK(false);
- }
- synchronous_entry_in_use_by_worker_ = true;
+ if (index < 0 || index >= kSimpleEntryFileCount || offset < 0 || buf_len < 0)
+ return net::ERR_INVALID_ARGUMENT;
+
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::WriteDataInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ callback,
+ truncate));
+ RunNextOperationIfNeeded();
+
+ // TODO(felipeg): Optimization: Add support for optimistic writes, quickly
+ // returning net::OK here.
+ return net::ERR_IO_PENDING;
+}
+
+void SimpleEntryImpl::WriteDataInternal(int index,
+ int offset,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ const CompletionCallback& callback,
+ bool truncate) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(!operation_running_);
+ operation_running_ = true;
if (index_)
index_->UseIfExists(key_);
+
+ last_used_ = base::Time::Now();
+ last_modified_ = base::Time::Now();
+ data_size_[index] = buf_len;
+
SynchronousOperationCallback sync_operation_callback =
base::Bind(&SimpleEntryImpl::EntryOperationComplete,
index_, callback, weak_ptr_factory_.GetWeakPtr(),
@@ -183,10 +238,9 @@ int SimpleEntryImpl::WriteData(int index,
WorkerPool::PostTask(FROM_HERE,
base::Bind(&SimpleSynchronousEntry::WriteData,
base::Unretained(synchronous_entry_),
- index, offset, make_scoped_refptr(buf),
+ index, offset, buf,
buf_len, sync_operation_callback, truncate),
true);
- return net::ERR_IO_PENDING;
}
int SimpleEntryImpl::ReadSparseData(int64 offset,
@@ -245,7 +299,7 @@ SimpleEntryImpl::SimpleEntryImpl(
path_(synchronous_entry->path()),
key_(synchronous_entry->key()),
synchronous_entry_(synchronous_entry),
- synchronous_entry_in_use_by_worker_(false),
+ operation_running_(false),
index_(index) {
DCHECK(synchronous_entry);
SetSynchronousData();
@@ -291,9 +345,10 @@ void SimpleEntryImpl::EntryOperationComplete(
}
if (entry) {
- DCHECK(entry->synchronous_entry_in_use_by_worker_);
- entry->synchronous_entry_in_use_by_worker_ = false;
+ DCHECK(entry->operation_running_);
+ entry->operation_running_ = false;
entry->SetSynchronousData();
+ entry->RunNextOperationIfNeeded();
} else {
// |entry| must have had Close() called while this operation was in flight.
// Since the simple cache now only supports one pending entry operation in
@@ -306,9 +361,19 @@ void SimpleEntryImpl::EntryOperationComplete(
completion_callback.Run(result);
}
+bool SimpleEntryImpl::RunNextOperationIfNeeded() {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ if (operations_.size() <= 0 || operation_running_)
+ return false;
+ base::Closure operation = operations_.front();
+ operations_.pop();
+ operation.Run();
+ return true;
+}
+
void SimpleEntryImpl::SetSynchronousData() {
DCHECK(io_thread_checker_.CalledOnValidThread());
- DCHECK(!synchronous_entry_in_use_by_worker_);
+ DCHECK(!operation_running_);
// 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
« no previous file with comments | « net/disk_cache/simple/simple_entry_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698