| 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,
|
|
|