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

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: fix a bug in GetDataSize() 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..f9fea2a9662f08554e46c636507907c4060400f4 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -87,7 +87,28 @@ int SimpleEntryImpl::DoomEntry(WeakPtr<SimpleIndex> index,
}
void SimpleEntryImpl::Doom() {
gavinp 2013/04/17 08:12:35 I think doom is one of the only operations that al
felipeg 2013/04/17 10:06:43 Done.
+ LOG(INFO) << " DOOM " << key_;
DCHECK(io_thread_checker_.CalledOnValidThread());
+ if (synchronous_entry_in_use_by_worker_) {
+ // Postpone doom operation.
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::DoomInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+ DCHECK(operations_.size() == 0);
+ DCHECK(!synchronous_entry_in_use_by_worker_);
+
+ DoomInternal();
+ // TODO(felipeg): Maybe we should have a flag is_doomed_ and do some DCHECKS
+ // around the code, to see if we dont call read in a doomed entry.
gavinp 2013/04/17 08:12:35 I believe it's correct and valid to Read/Write in
felipeg 2013/04/17 10:06:43 Done.
+ RunNextOperationIfNeeded();
+}
+
+void SimpleEntryImpl::DoomInternal() {
+ LOG(INFO) << " DOOM " << key_;
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(!synchronous_entry_in_use_by_worker_);
#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
@@ -100,13 +121,26 @@ void SimpleEntryImpl::Doom() {
}
void SimpleEntryImpl::Close() {
+ LOG(INFO) << " CLOSE " << key_;
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 (synchronous_entry_in_use_by_worker_) {
+ LOG(INFO) << " CLOSE " << key_;
+ // 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;
}
+ LOG(INFO) << " CLOSE " << key_;
+ DCHECK(operations_.size() == 0);
+ DCHECK(!synchronous_entry_in_use_by_worker_);
+
+ 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;
@@ -132,20 +166,49 @@ int32 SimpleEntryImpl::GetDataSize(int index) const {
return data_size_[index];
}
+
+
int SimpleEntryImpl::ReadData(int index,
int offset,
net::IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
+ LOG(INFO) << " READ " << key_;
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);
+ if (synchronous_entry_in_use_by_worker_ && !read_only_operation_) {
+ // Postpone read operation.
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::ReadDataInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ callback));
+ return net::ERR_IO_PENDING;
}
+ DCHECK(operations_.size() == 0);
+ ReadDataInternal(index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ callback);
+ return net::ERR_IO_PENDING;
+}
+
+void SimpleEntryImpl::ReadDataInternal(int index,
+ int offset,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ LOG(INFO) << " READ " << key_;
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(!synchronous_entry_in_use_by_worker_);
+ read_only_operation_ = true;
synchronous_entry_in_use_by_worker_ = true;
if (index_)
index_->UseIfExists(key_);
@@ -156,10 +219,14 @@ 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,
gavinp 2013/04/17 08:17:14 This is really dangerous, calling with the naked b
gavinp 2013/04/17 09:40:16 Boy this stuff is subtle. I was wrong: I failed t
buf_len, sync_operation_callback),
true);
- return net::ERR_IO_PENDING;
+}
+
+// TODO(felipeg): Maybe in case of failure from a write operation, we could try
+// to invalidate all operations in the queue of the current entry.
+static void WriteDataNoOp(int noop) {
}
int SimpleEntryImpl::WriteData(int index,
gavinp 2013/04/17 09:23:56 I think ReadData / WriteData can be made a lot sim
felipeg 2013/04/17 10:06:43 Done.
@@ -168,14 +235,56 @@ int SimpleEntryImpl::WriteData(int index,
int buf_len,
const CompletionCallback& callback,
bool truncate) {
+ LOG(INFO) << " WRITE " << key_ << " buf " << buf << " buf_len " << buf_len << " truncate " << truncate;
DCHECK(io_thread_checker_.CalledOnValidThread());
+
if (synchronous_entry_in_use_by_worker_) {
- NOTIMPLEMENTED();
- CHECK(false);
+ LOG(INFO) << " WRITE " << key_;
+ // Postpone write operation.
+ operations_.push(
+ base::Bind(&SimpleEntryImpl::WriteDataInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ callback,
+ truncate));
+ // When writting, if there is already a pending operation, we have to return
+ // pending.
+ return net::ERR_IO_PENDING;
}
+ LOG(INFO) << " WRITE " << key_;
+ DCHECK(operations_.size() == 0);
+ WriteDataInternal(index,
+ offset,
+ make_scoped_refptr(buf),
+ buf_len,
+ //callback,
+ base::Bind(&WriteDataNoOp),
+ truncate);
+ //return net::ERR_IO_PENDING;
+ // Pretend everything goes fine, and make HTTP Cache Transaction happy.
+ return buf_len;
+}
+
+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(!synchronous_entry_in_use_by_worker_);
+ read_only_operation_ = false;
synchronous_entry_in_use_by_worker_ = true;
if (index_)
index_->UseIfExists(key_);
+
+ // TODO(felipeg): last_used_ last_modified_
+
+ data_size_[index] = buf_len;
+
SynchronousOperationCallback sync_operation_callback =
base::Bind(&SimpleEntryImpl::EntryOperationComplete,
index_, callback, weak_ptr_factory_.GetWeakPtr(),
@@ -183,10 +292,10 @@ 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;
+ LOG(INFO) << " WRITE " << key_;
}
int SimpleEntryImpl::ReadSparseData(int64 offset,
@@ -246,6 +355,7 @@ SimpleEntryImpl::SimpleEntryImpl(
key_(synchronous_entry->key()),
synchronous_entry_(synchronous_entry),
synchronous_entry_in_use_by_worker_(false),
+ read_only_operation_(false),
index_(index) {
DCHECK(synchronous_entry);
SetSynchronousData();
@@ -291,10 +401,21 @@ void SimpleEntryImpl::EntryOperationComplete(
}
if (entry) {
+ if (entry->read_only_operation_)
+ LOG(INFO) << " READ EntryOperationComplete " << entry->key();
+ else
+ LOG(INFO) << " WRITE EntryOperationComplete " << entry->key();
DCHECK(entry->synchronous_entry_in_use_by_worker_);
+ entry->read_only_operation_ = false;
entry->synchronous_entry_in_use_by_worker_ = false;
entry->SetSynchronousData();
+
+ entry->RunNextOperationIfNeeded();
+
+ completion_callback.Run(result);
} else {
+
+ LOG(INFO) << " EntryOperationComplete " << entry->key();
// |entry| must have had Close() called while this operation was in flight.
// Since the simple cache now only supports one pending entry operation in
// flight at a time, it's safe to now call Close() on |sync_entry|.
@@ -302,8 +423,23 @@ void SimpleEntryImpl::EntryOperationComplete(
base::Bind(&SimpleSynchronousEntry::Close,
base::Unretained(sync_entry)),
true);
+
+ completion_callback.Run(result);
}
- completion_callback.Run(result);
+}
+
+void SimpleEntryImpl::RunNextOperationIfNeeded() {
+ LOG(INFO) << " RunNextOperationIfNeeded " << key_;
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ if (operations_.size() <= 0)
+ return;
+ base::Closure operation = operations_.front();
+ operations_.pop();
+
+ LOG(INFO) << " operation.Run " << key_;
+ // TODO(felipeg): maybe we should post task. But it could shuffle even more
+ // the order of new operations in this entry.
gavinp 2013/04/17 08:17:14 The callers should be totally insensitive to the o
felipeg 2013/04/17 10:06:43 No post is better because when debugging our minds
+ operation.Run();
}
void SimpleEntryImpl::SetSynchronousData() {
« 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