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 0e860d70664132df34f7b3b5405f3532168c52b7..c9edd8e1c235a492b877e7700aef43aebf5e3cdb 100644 |
--- a/net/disk_cache/simple/simple_entry_impl.cc |
+++ b/net/disk_cache/simple/simple_entry_impl.cc |
@@ -133,6 +133,20 @@ void InvokeCallbackIfBackendIsAlive( |
completion_callback.Run(result); |
} |
+// If |sync_possible| is false, and callback is available, posts rv to it and |
+// return net::ERR_IO_PENDING; otherwise just passes through rv. |
+int PostToCallbackIfNeeded(bool sync_possible, |
+ const net::CompletionCallback& callback, |
+ int rv) { |
+ if (!sync_possible && !callback.is_null()) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
+ base::Bind(callback, rv)); |
+ return net::ERR_IO_PENDING; |
+ } else { |
+ return rv; |
+ } |
+} |
+ |
} // namespace |
using base::Closure; |
@@ -370,23 +384,17 @@ int SimpleEntryImpl::ReadData(int stream_index, |
RecordReadResult(cache_type_, READ_RESULT_INVALID_ARGUMENT); |
return net::ERR_INVALID_ARGUMENT; |
} |
- if (pending_operations_.empty() && (offset >= GetDataSize(stream_index) || |
- offset < 0 || !buf_len)) { |
- if (net_log_.IsCapturing()) { |
- net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END, |
- CreateNetLogReadWriteCompleteCallback(0)); |
- } |
- |
- RecordReadResult(cache_type_, READ_RESULT_NONBLOCK_EMPTY_RETURN); |
- return 0; |
- } |
- |
- // TODO(clamy): return immediatly when reading from stream 0. |
// TODO(felipeg): Optimization: Add support for truly parallel read |
// operations. |
bool alone_in_queue = |
pending_operations_.size() == 0 && state_ == STATE_READY; |
+ |
+ if (alone_in_queue) { |
+ return ReadDataInternal(/*sync_possible = */ true, stream_index, offset, |
+ buf, buf_len, callback); |
+ } |
+ |
pending_operations_.push(SimpleEntryOperation::ReadOperation( |
this, stream_index, offset, buf_len, buf, callback, alone_in_queue)); |
RunNextOperationIfNeeded(); |
@@ -634,11 +642,9 @@ void SimpleEntryImpl::RunNextOperationIfNeeded() { |
break; |
case SimpleEntryOperation::TYPE_READ: |
RecordReadIsParallelizable(*operation); |
- ReadDataInternal(operation->index(), |
- operation->offset(), |
- operation->buf(), |
- operation->length(), |
- operation->callback()); |
+ ReadDataInternal(/* sync_possible= */ false, operation->index(), |
+ operation->offset(), operation->buf(), |
+ operation->length(), operation->callback()); |
break; |
case SimpleEntryOperation::TYPE_WRITE: |
RecordWriteDependencyType(*operation); |
@@ -809,11 +815,12 @@ void SimpleEntryImpl::CloseInternal() { |
} |
} |
-void SimpleEntryImpl::ReadDataInternal(int stream_index, |
- int offset, |
- net::IOBuffer* buf, |
- int buf_len, |
- const CompletionCallback& callback) { |
+int SimpleEntryImpl::ReadDataInternal(bool sync_possible, |
+ int stream_index, |
+ int offset, |
+ net::IOBuffer* buf, |
+ int buf_len, |
+ const CompletionCallback& callback) { |
DCHECK(io_thread_checker_.CalledOnValidThread()); |
ScopedOperationRunner operation_runner(this); |
@@ -824,38 +831,33 @@ void SimpleEntryImpl::ReadDataInternal(int stream_index, |
} |
if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) { |
- if (!callback.is_null()) { |
- RecordReadResult(cache_type_, READ_RESULT_BAD_STATE); |
- // Note that the API states that client-provided callbacks for entry-level |
- // (i.e. non-backend) operations (e.g. read, write) are invoked even if |
- // the backend was already destroyed. |
- base::ThreadTaskRunnerHandle::Get()->PostTask( |
- FROM_HERE, base::Bind(callback, net::ERR_FAILED)); |
- } |
+ RecordReadResult(cache_type_, READ_RESULT_BAD_STATE); |
if (net_log_.IsCapturing()) { |
net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END, |
CreateNetLogReadWriteCompleteCallback(net::ERR_FAILED)); |
} |
- return; |
+ // Note that the API states that client-provided callbacks for entry-level |
+ // (i.e. non-backend) operations (e.g. read, write) are invoked even if |
+ // the backend was already destroyed. |
+ return PostToCallbackIfNeeded(sync_possible, callback, net::ERR_FAILED); |
} |
DCHECK_EQ(STATE_READY, state_); |
if (offset >= GetDataSize(stream_index) || offset < 0 || !buf_len) { |
- RecordReadResult(cache_type_, READ_RESULT_FAST_EMPTY_RETURN); |
+ RecordReadResult(cache_type_, sync_possible |
+ ? READ_RESULT_NONBLOCK_EMPTY_RETURN |
+ : READ_RESULT_FAST_EMPTY_RETURN); |
// If there is nothing to read, we bail out before setting state_ to |
- // STATE_IO_PENDING. |
- if (!callback.is_null()) |
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
- base::Bind(callback, 0)); |
- return; |
+ // STATE_IO_PENDING (so ScopedOperationRunner might start us on next op |
+ // here). |
+ return PostToCallbackIfNeeded(sync_possible, callback, 0); |
} |
buf_len = std::min(buf_len, GetDataSize(stream_index) - offset); |
// Since stream 0 data is kept in memory, it is read immediately. |
if (stream_index == 0) { |
- ReadFromBufferAndPostReply(stream_0_data_.get(), offset, buf_len, buf, |
- callback); |
- return; |
+ int rv = ReadFromBuffer(stream_0_data_.get(), offset, buf_len, buf); |
+ return PostToCallbackIfNeeded(sync_possible, callback, rv); |
} |
// Sometimes we can read in-ram prefetched stream 1 data immediately, too. |
@@ -867,9 +869,9 @@ void SimpleEntryImpl::ReadDataInternal(int stream_index, |
is_initial_stream1_read_ = false; |
if (stream_1_prefetch_data_) { |
- ReadFromBufferAndPostReply(stream_1_prefetch_data_.get(), offset, buf_len, |
- buf, callback); |
- return; |
+ int rv = |
+ ReadFromBuffer(stream_1_prefetch_data_.get(), offset, buf_len, buf); |
+ return PostToCallbackIfNeeded(sync_possible, callback, rv); |
} |
} |
@@ -905,6 +907,7 @@ void SimpleEntryImpl::ReadDataInternal(int stream_index, |
offset, callback, base::Passed(&crc_request), |
base::Passed(&entry_stat), base::Passed(&result)); |
worker_pool_->PostTaskAndReply(FROM_HERE, task, reply); |
+ return net::ERR_IO_PENDING; |
} |
void SimpleEntryImpl::WriteDataInternal(int stream_index, |
@@ -1478,27 +1481,17 @@ void SimpleEntryImpl::RecordWriteDependencyType( |
type, WRITE_DEPENDENCY_TYPE_MAX); |
} |
-void SimpleEntryImpl::ReadFromBufferAndPostReply( |
- net::GrowableIOBuffer* in_buf, |
- int offset, |
- int buf_len, |
- net::IOBuffer* out_buf, |
- const CompletionCallback& callback) { |
- int rv; |
- if (buf_len < 0) { |
- RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE); |
- rv = 0; |
- } else { |
- memcpy(out_buf->data(), in_buf->data() + offset, buf_len); |
- UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_, |
- data_size_, sparse_data_size_)); |
- RecordReadResult(cache_type_, READ_RESULT_SUCCESS); |
- rv = buf_len; |
- } |
- if (!callback.is_null()) { |
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
- base::Bind(callback, rv)); |
- } |
+int SimpleEntryImpl::ReadFromBuffer(net::GrowableIOBuffer* in_buf, |
+ int offset, |
+ int buf_len, |
+ net::IOBuffer* out_buf) { |
+ DCHECK_GE(buf_len, 0); |
+ |
+ memcpy(out_buf->data(), in_buf->data() + offset, buf_len); |
+ UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_, |
+ data_size_, sparse_data_size_)); |
+ RecordReadResult(cache_type_, READ_RESULT_SUCCESS); |
+ return buf_len; |
} |
int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf, |