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