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

Side by Side Diff: net/disk_cache/simple/simple_entry_impl.cc

Issue 2807433002: SimpleCache: synchronously reply on reads from idle if data is in memory.
Patch Set: Use the proper limit for the barrier. Created 3 years, 2 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 unified diff | Download patch
« no previous file with comments | « net/disk_cache/simple/simple_entry_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/simple/simple_entry_impl.h" 5 #include "net/disk_cache/simple/simple_entry_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <limits> 9 #include <limits>
10 #include <utility> 10 #include <utility>
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 void InvokeCallbackIfBackendIsAlive( 126 void InvokeCallbackIfBackendIsAlive(
127 const base::WeakPtr<SimpleBackendImpl>& backend, 127 const base::WeakPtr<SimpleBackendImpl>& backend,
128 const net::CompletionCallback& completion_callback, 128 const net::CompletionCallback& completion_callback,
129 int result) { 129 int result) {
130 DCHECK(!completion_callback.is_null()); 130 DCHECK(!completion_callback.is_null());
131 if (!backend.get()) 131 if (!backend.get())
132 return; 132 return;
133 completion_callback.Run(result); 133 completion_callback.Run(result);
134 } 134 }
135 135
136 // If |sync_possible| is false, and callback is available, posts rv to it and
137 // return net::ERR_IO_PENDING; otherwise just passes through rv.
138 int PostToCallbackIfNeeded(bool sync_possible,
139 const net::CompletionCallback& callback,
140 int rv) {
141 if (!sync_possible && !callback.is_null()) {
142 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
143 base::Bind(callback, rv));
144 return net::ERR_IO_PENDING;
145 } else {
146 return rv;
147 }
148 }
149
136 } // namespace 150 } // namespace
137 151
138 using base::Closure; 152 using base::Closure;
139 using base::FilePath; 153 using base::FilePath;
140 using base::Time; 154 using base::Time;
141 using base::TaskRunner; 155 using base::TaskRunner;
142 156
143 // Static function called by base::trace_event::EstimateMemoryUsage() to 157 // Static function called by base::trace_event::EstimateMemoryUsage() to
144 // estimate the memory of SimpleEntryOperation. 158 // estimate the memory of SimpleEntryOperation.
145 // This needs to be in disk_cache namespace. 159 // This needs to be in disk_cache namespace.
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 buf_len < 0) { 377 buf_len < 0) {
364 if (net_log_.IsCapturing()) { 378 if (net_log_.IsCapturing()) {
365 net_log_.AddEvent( 379 net_log_.AddEvent(
366 net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END, 380 net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END,
367 CreateNetLogReadWriteCompleteCallback(net::ERR_INVALID_ARGUMENT)); 381 CreateNetLogReadWriteCompleteCallback(net::ERR_INVALID_ARGUMENT));
368 } 382 }
369 383
370 RecordReadResult(cache_type_, READ_RESULT_INVALID_ARGUMENT); 384 RecordReadResult(cache_type_, READ_RESULT_INVALID_ARGUMENT);
371 return net::ERR_INVALID_ARGUMENT; 385 return net::ERR_INVALID_ARGUMENT;
372 } 386 }
373 if (pending_operations_.empty() && (offset >= GetDataSize(stream_index) ||
374 offset < 0 || !buf_len)) {
375 if (net_log_.IsCapturing()) {
376 net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END,
377 CreateNetLogReadWriteCompleteCallback(0));
378 }
379
380 RecordReadResult(cache_type_, READ_RESULT_NONBLOCK_EMPTY_RETURN);
381 return 0;
382 }
383
384 // TODO(clamy): return immediatly when reading from stream 0.
385 387
386 // TODO(felipeg): Optimization: Add support for truly parallel read 388 // TODO(felipeg): Optimization: Add support for truly parallel read
387 // operations. 389 // operations.
388 bool alone_in_queue = 390 bool alone_in_queue =
389 pending_operations_.size() == 0 && state_ == STATE_READY; 391 pending_operations_.size() == 0 && state_ == STATE_READY;
392
393 if (alone_in_queue) {
394 return ReadDataInternal(/*sync_possible = */ true, stream_index, offset,
395 buf, buf_len, callback);
396 }
397
390 pending_operations_.push(SimpleEntryOperation::ReadOperation( 398 pending_operations_.push(SimpleEntryOperation::ReadOperation(
391 this, stream_index, offset, buf_len, buf, callback, alone_in_queue)); 399 this, stream_index, offset, buf_len, buf, callback, alone_in_queue));
392 RunNextOperationIfNeeded(); 400 RunNextOperationIfNeeded();
393 return net::ERR_IO_PENDING; 401 return net::ERR_IO_PENDING;
394 } 402 }
395 403
396 int SimpleEntryImpl::WriteData(int stream_index, 404 int SimpleEntryImpl::WriteData(int stream_index,
397 int offset, 405 int offset,
398 net::IOBuffer* buf, 406 net::IOBuffer* buf,
399 int buf_len, 407 int buf_len,
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 case SimpleEntryOperation::TYPE_CREATE: 635 case SimpleEntryOperation::TYPE_CREATE:
628 CreateEntryInternal(operation->have_index(), 636 CreateEntryInternal(operation->have_index(),
629 operation->callback(), 637 operation->callback(),
630 operation->out_entry()); 638 operation->out_entry());
631 break; 639 break;
632 case SimpleEntryOperation::TYPE_CLOSE: 640 case SimpleEntryOperation::TYPE_CLOSE:
633 CloseInternal(); 641 CloseInternal();
634 break; 642 break;
635 case SimpleEntryOperation::TYPE_READ: 643 case SimpleEntryOperation::TYPE_READ:
636 RecordReadIsParallelizable(*operation); 644 RecordReadIsParallelizable(*operation);
637 ReadDataInternal(operation->index(), 645 ReadDataInternal(/* sync_possible= */ false, operation->index(),
638 operation->offset(), 646 operation->offset(), operation->buf(),
639 operation->buf(), 647 operation->length(), operation->callback());
640 operation->length(),
641 operation->callback());
642 break; 648 break;
643 case SimpleEntryOperation::TYPE_WRITE: 649 case SimpleEntryOperation::TYPE_WRITE:
644 RecordWriteDependencyType(*operation); 650 RecordWriteDependencyType(*operation);
645 WriteDataInternal(operation->index(), 651 WriteDataInternal(operation->index(),
646 operation->offset(), 652 operation->offset(),
647 operation->buf(), 653 operation->buf(),
648 operation->length(), 654 operation->length(),
649 operation->callback(), 655 operation->callback(),
650 operation->truncate()); 656 operation->truncate());
651 break; 657 break;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 SIMPLE_CACHE_UMA(ENUMERATION, 808 SIMPLE_CACHE_UMA(ENUMERATION,
803 "CheckCRCResult", cache_type_, 809 "CheckCRCResult", cache_type_,
804 crc_check_state_[i], CRC_CHECK_MAX); 810 crc_check_state_[i], CRC_CHECK_MAX);
805 } 811 }
806 } 812 }
807 } else { 813 } else {
808 CloseOperationComplete(); 814 CloseOperationComplete();
809 } 815 }
810 } 816 }
811 817
812 void SimpleEntryImpl::ReadDataInternal(int stream_index, 818 int SimpleEntryImpl::ReadDataInternal(bool sync_possible,
813 int offset, 819 int stream_index,
814 net::IOBuffer* buf, 820 int offset,
815 int buf_len, 821 net::IOBuffer* buf,
816 const CompletionCallback& callback) { 822 int buf_len,
823 const CompletionCallback& callback) {
817 DCHECK(io_thread_checker_.CalledOnValidThread()); 824 DCHECK(io_thread_checker_.CalledOnValidThread());
818 ScopedOperationRunner operation_runner(this); 825 ScopedOperationRunner operation_runner(this);
819 826
820 if (net_log_.IsCapturing()) { 827 if (net_log_.IsCapturing()) {
821 net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_BEGIN, 828 net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_BEGIN,
822 CreateNetLogReadWriteDataCallback(stream_index, offset, 829 CreateNetLogReadWriteDataCallback(stream_index, offset,
823 buf_len, false)); 830 buf_len, false));
824 } 831 }
825 832
826 if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) { 833 if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) {
827 if (!callback.is_null()) { 834 RecordReadResult(cache_type_, READ_RESULT_BAD_STATE);
828 RecordReadResult(cache_type_, READ_RESULT_BAD_STATE);
829 // Note that the API states that client-provided callbacks for entry-level
830 // (i.e. non-backend) operations (e.g. read, write) are invoked even if
831 // the backend was already destroyed.
832 base::ThreadTaskRunnerHandle::Get()->PostTask(
833 FROM_HERE, base::Bind(callback, net::ERR_FAILED));
834 }
835 if (net_log_.IsCapturing()) { 835 if (net_log_.IsCapturing()) {
836 net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END, 836 net_log_.AddEvent(net::NetLogEventType::SIMPLE_CACHE_ENTRY_READ_END,
837 CreateNetLogReadWriteCompleteCallback(net::ERR_FAILED)); 837 CreateNetLogReadWriteCompleteCallback(net::ERR_FAILED));
838 } 838 }
839 return; 839 // Note that the API states that client-provided callbacks for entry-level
840 // (i.e. non-backend) operations (e.g. read, write) are invoked even if
841 // the backend was already destroyed.
842 return PostToCallbackIfNeeded(sync_possible, callback, net::ERR_FAILED);
840 } 843 }
841 DCHECK_EQ(STATE_READY, state_); 844 DCHECK_EQ(STATE_READY, state_);
842 if (offset >= GetDataSize(stream_index) || offset < 0 || !buf_len) { 845 if (offset >= GetDataSize(stream_index) || offset < 0 || !buf_len) {
843 RecordReadResult(cache_type_, READ_RESULT_FAST_EMPTY_RETURN); 846 RecordReadResult(cache_type_, sync_possible
847 ? READ_RESULT_NONBLOCK_EMPTY_RETURN
848 : READ_RESULT_FAST_EMPTY_RETURN);
844 // If there is nothing to read, we bail out before setting state_ to 849 // If there is nothing to read, we bail out before setting state_ to
845 // STATE_IO_PENDING. 850 // STATE_IO_PENDING (so ScopedOperationRunner might start us on next op
846 if (!callback.is_null()) 851 // here).
847 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 852 return PostToCallbackIfNeeded(sync_possible, callback, 0);
848 base::Bind(callback, 0));
849 return;
850 } 853 }
851 854
852 buf_len = std::min(buf_len, GetDataSize(stream_index) - offset); 855 buf_len = std::min(buf_len, GetDataSize(stream_index) - offset);
853 856
854 // Since stream 0 data is kept in memory, it is read immediately. 857 // Since stream 0 data is kept in memory, it is read immediately.
855 if (stream_index == 0) { 858 if (stream_index == 0) {
856 ReadFromBufferAndPostReply(stream_0_data_.get(), offset, buf_len, buf, 859 int rv = ReadFromBuffer(stream_0_data_.get(), offset, buf_len, buf);
857 callback); 860 return PostToCallbackIfNeeded(sync_possible, callback, rv);
858 return;
859 } 861 }
860 862
861 // Sometimes we can read in-ram prefetched stream 1 data immediately, too. 863 // Sometimes we can read in-ram prefetched stream 1 data immediately, too.
862 if (stream_index == 1) { 864 if (stream_index == 1) {
863 if (is_initial_stream1_read_) { 865 if (is_initial_stream1_read_) {
864 SIMPLE_CACHE_UMA(BOOLEAN, "ReadStream1FromPrefetched", cache_type_, 866 SIMPLE_CACHE_UMA(BOOLEAN, "ReadStream1FromPrefetched", cache_type_,
865 stream_1_prefetch_data_ != nullptr); 867 stream_1_prefetch_data_ != nullptr);
866 } 868 }
867 is_initial_stream1_read_ = false; 869 is_initial_stream1_read_ = false;
868 870
869 if (stream_1_prefetch_data_) { 871 if (stream_1_prefetch_data_) {
870 ReadFromBufferAndPostReply(stream_1_prefetch_data_.get(), offset, buf_len, 872 int rv =
871 buf, callback); 873 ReadFromBuffer(stream_1_prefetch_data_.get(), offset, buf_len, buf);
872 return; 874 return PostToCallbackIfNeeded(sync_possible, callback, rv);
873 } 875 }
874 } 876 }
875 877
876 state_ = STATE_IO_PENDING; 878 state_ = STATE_IO_PENDING;
877 if (!doomed_ && backend_.get()) 879 if (!doomed_ && backend_.get())
878 backend_->index()->UseIfExists(entry_hash_); 880 backend_->index()->UseIfExists(entry_hash_);
879 881
880 // Figure out if we should be computing the checksum for this read, 882 // Figure out if we should be computing the checksum for this read,
881 // and whether we should be verifying it, too. 883 // and whether we should be verifying it, too.
882 std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_request; 884 std::unique_ptr<SimpleSynchronousEntry::CRCRequest> crc_request;
(...skipping 15 matching lines...) Expand all
898 Closure task = base::Bind( 900 Closure task = base::Bind(
899 &SimpleSynchronousEntry::ReadData, base::Unretained(synchronous_entry_), 901 &SimpleSynchronousEntry::ReadData, base::Unretained(synchronous_entry_),
900 SimpleSynchronousEntry::EntryOperationData(stream_index, offset, buf_len), 902 SimpleSynchronousEntry::EntryOperationData(stream_index, offset, buf_len),
901 crc_request.get(), entry_stat.get(), base::RetainedRef(buf), 903 crc_request.get(), entry_stat.get(), base::RetainedRef(buf),
902 result.get()); 904 result.get());
903 Closure reply = 905 Closure reply =
904 base::Bind(&SimpleEntryImpl::ReadOperationComplete, this, stream_index, 906 base::Bind(&SimpleEntryImpl::ReadOperationComplete, this, stream_index,
905 offset, callback, base::Passed(&crc_request), 907 offset, callback, base::Passed(&crc_request),
906 base::Passed(&entry_stat), base::Passed(&result)); 908 base::Passed(&entry_stat), base::Passed(&result));
907 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply); 909 worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
910 return net::ERR_IO_PENDING;
908 } 911 }
909 912
910 void SimpleEntryImpl::WriteDataInternal(int stream_index, 913 void SimpleEntryImpl::WriteDataInternal(int stream_index,
911 int offset, 914 int offset,
912 net::IOBuffer* buf, 915 net::IOBuffer* buf,
913 int buf_len, 916 int buf_len,
914 const CompletionCallback& callback, 917 const CompletionCallback& callback,
915 bool truncate) { 918 bool truncate) {
916 DCHECK(io_thread_checker_.CalledOnValidThread()); 919 DCHECK(io_thread_checker_.CalledOnValidThread());
917 ScopedOperationRunner operation_runner(this); 920 ScopedOperationRunner operation_runner(this);
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 } else { 1474 } else {
1472 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE 1475 type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE
1473 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; 1476 : WRITE_FOLLOWS_NON_CONFLICTING_WRITE;
1474 } 1477 }
1475 } 1478 }
1476 SIMPLE_CACHE_UMA(ENUMERATION, 1479 SIMPLE_CACHE_UMA(ENUMERATION,
1477 "WriteDependencyType", cache_type_, 1480 "WriteDependencyType", cache_type_,
1478 type, WRITE_DEPENDENCY_TYPE_MAX); 1481 type, WRITE_DEPENDENCY_TYPE_MAX);
1479 } 1482 }
1480 1483
1481 void SimpleEntryImpl::ReadFromBufferAndPostReply( 1484 int SimpleEntryImpl::ReadFromBuffer(net::GrowableIOBuffer* in_buf,
1482 net::GrowableIOBuffer* in_buf, 1485 int offset,
1483 int offset, 1486 int buf_len,
1484 int buf_len, 1487 net::IOBuffer* out_buf) {
1485 net::IOBuffer* out_buf, 1488 DCHECK_GE(buf_len, 0);
1486 const CompletionCallback& callback) { 1489
1487 int rv; 1490 memcpy(out_buf->data(), in_buf->data() + offset, buf_len);
1488 if (buf_len < 0) { 1491 UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_,
1489 RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE); 1492 data_size_, sparse_data_size_));
1490 rv = 0; 1493 RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
1491 } else { 1494 return buf_len;
1492 memcpy(out_buf->data(), in_buf->data() + offset, buf_len);
1493 UpdateDataFromEntryStat(SimpleEntryStat(base::Time::Now(), last_modified_,
1494 data_size_, sparse_data_size_));
1495 RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
1496 rv = buf_len;
1497 }
1498 if (!callback.is_null()) {
1499 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1500 base::Bind(callback, rv));
1501 }
1502 } 1495 }
1503 1496
1504 int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf, 1497 int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf,
1505 int offset, 1498 int offset,
1506 int buf_len, 1499 int buf_len,
1507 bool truncate) { 1500 bool truncate) {
1508 // Currently, stream 0 is only used for HTTP headers, and always writes them 1501 // Currently, stream 0 is only used for HTTP headers, and always writes them
1509 // with a single, truncating write. Detect these writes and record the size 1502 // with a single, truncating write. Detect these writes and record the size
1510 // changes of the headers. Also, support writes to stream 0 that have 1503 // changes of the headers. Also, support writes to stream 0 that have
1511 // different access patterns, as required by the API contract. 1504 // different access patterns, as required by the API contract.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1558 } 1551 }
1559 crc32s_end_offset_[stream_index] = offset + length; 1552 crc32s_end_offset_[stream_index] = offset + length;
1560 } else if (offset < crc32s_end_offset_[stream_index]) { 1553 } else if (offset < crc32s_end_offset_[stream_index]) {
1561 // If a range for which the crc32 was already computed is rewritten, the 1554 // If a range for which the crc32 was already computed is rewritten, the
1562 // computation of the crc32 need to start from 0 again. 1555 // computation of the crc32 need to start from 0 again.
1563 crc32s_end_offset_[stream_index] = 0; 1556 crc32s_end_offset_[stream_index] = 0;
1564 } 1557 }
1565 } 1558 }
1566 1559
1567 } // namespace disk_cache 1560 } // namespace disk_cache
OLDNEW
« 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