OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |