| Index: net/disk_cache/entry_impl.cc
|
| diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc
|
| index 7e130292bfd92ac8bf37f6dc909bc712cb82cc73..7ba6e94cec10a6f9792b77ab43919affd832f409 100644
|
| --- a/net/disk_cache/entry_impl.cc
|
| +++ b/net/disk_cache/entry_impl.cc
|
| @@ -35,6 +35,14 @@ class SyncCallback: public disk_cache::FileIOCallback {
|
| SyncCallback(disk_cache::EntryImpl* entry, net::IOBuffer* buffer,
|
| net::OldCompletionCallback* callback,
|
| net::NetLog::EventType end_event_type)
|
| + : entry_(entry), old_callback_(callback), buf_(buffer),
|
| + start_(TimeTicks::Now()), end_event_type_(end_event_type) {
|
| + entry->AddRef();
|
| + entry->IncrementIoCount();
|
| + }
|
| + SyncCallback(disk_cache::EntryImpl* entry, net::IOBuffer* buffer,
|
| + const net::CompletionCallback& callback,
|
| + net::NetLog::EventType end_event_type)
|
| : entry_(entry), callback_(callback), buf_(buffer),
|
| start_(TimeTicks::Now()), end_event_type_(end_event_type) {
|
| entry->AddRef();
|
| @@ -47,7 +55,8 @@ class SyncCallback: public disk_cache::FileIOCallback {
|
|
|
| private:
|
| disk_cache::EntryImpl* entry_;
|
| - net::OldCompletionCallback* callback_;
|
| + net::OldCompletionCallback* old_callback_;
|
| + net::CompletionCallback callback_;
|
| scoped_refptr<net::IOBuffer> buf_;
|
| TimeTicks start_;
|
| const net::NetLog::EventType end_event_type_;
|
| @@ -57,7 +66,7 @@ class SyncCallback: public disk_cache::FileIOCallback {
|
|
|
| void SyncCallback::OnFileIOComplete(int bytes_copied) {
|
| entry_->DecrementIoCount();
|
| - if (callback_) {
|
| + if (old_callback_ || !callback_.is_null()) {
|
| if (entry_->net_log().IsLoggingAllEvents()) {
|
| entry_->net_log().EndEvent(
|
| end_event_type_,
|
| @@ -65,14 +74,19 @@ void SyncCallback::OnFileIOComplete(int bytes_copied) {
|
| new disk_cache::ReadWriteCompleteParameters(bytes_copied)));
|
| }
|
| entry_->ReportIOTime(disk_cache::EntryImpl::kAsyncIO, start_);
|
| - callback_->Run(bytes_copied);
|
| +
|
| + if (old_callback_)
|
| + old_callback_->Run(bytes_copied);
|
| + else
|
| + callback_.Run(bytes_copied);
|
| }
|
| entry_->Release();
|
| delete this;
|
| }
|
|
|
| void SyncCallback::Discard() {
|
| - callback_ = NULL;
|
| + old_callback_ = NULL;
|
| + callback_.Reset();
|
| buf_ = NULL;
|
| OnFileIOComplete(0);
|
| }
|
| @@ -327,6 +341,26 @@ int EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf,
|
| return result;
|
| }
|
|
|
| +int EntryImpl::ReadDataImpl(
|
| + int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback) {
|
| + if (net_log_.IsLoggingAllEvents()) {
|
| + net_log_.BeginEvent(
|
| + net::NetLog::TYPE_ENTRY_READ_DATA,
|
| + make_scoped_refptr(
|
| + new ReadWriteDataParameters(index, offset, buf_len, false)));
|
| + }
|
| +
|
| + int result = InternalReadData(index, offset, buf, buf_len, callback);
|
| +
|
| + if (result != net::ERR_IO_PENDING && net_log_.IsLoggingAllEvents()) {
|
| + net_log_.EndEvent(
|
| + net::NetLog::TYPE_ENTRY_READ_DATA,
|
| + make_scoped_refptr(new ReadWriteCompleteParameters(result)));
|
| + }
|
| + return result;
|
| +}
|
| +
|
| int EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf,
|
| int buf_len, OldCompletionCallback* callback,
|
| bool truncate) {
|
| @@ -348,6 +382,27 @@ int EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf,
|
| return result;
|
| }
|
|
|
| +int EntryImpl::WriteDataImpl(
|
| + int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback, bool truncate) {
|
| + if (net_log_.IsLoggingAllEvents()) {
|
| + net_log_.BeginEvent(
|
| + net::NetLog::TYPE_ENTRY_WRITE_DATA,
|
| + make_scoped_refptr(
|
| + new ReadWriteDataParameters(index, offset, buf_len, truncate)));
|
| + }
|
| +
|
| + int result = InternalWriteData(index, offset, buf, buf_len, callback,
|
| + truncate);
|
| +
|
| + if (result != net::ERR_IO_PENDING && net_log_.IsLoggingAllEvents()) {
|
| + net_log_.EndEvent(
|
| + net::NetLog::TYPE_ENTRY_WRITE_DATA,
|
| + make_scoped_refptr(new ReadWriteCompleteParameters(result)));
|
| + }
|
| + return result;
|
| +}
|
| +
|
| int EntryImpl::ReadSparseDataImpl(int64 offset, net::IOBuffer* buf, int buf_len,
|
| OldCompletionCallback* callback) {
|
| DCHECK(node_.Data()->dirty || read_only_);
|
| @@ -818,6 +873,27 @@ int EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
|
| return net::ERR_IO_PENDING;
|
| }
|
|
|
| +int EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback) {
|
| + if (callback.is_null())
|
| + return ReadDataImpl(index, offset, buf, buf_len, callback);
|
| +
|
| + DCHECK(node_.Data()->dirty || read_only_);
|
| + if (index < 0 || index >= kNumStreams)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + int entry_size = entry_.Data()->data_size[index];
|
| + if (offset >= entry_size || offset < 0 || !buf_len)
|
| + return 0;
|
| +
|
| + if (buf_len < 0)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + backend_->background_queue()->ReadData(this, index, offset, buf, buf_len,
|
| + callback);
|
| + return net::ERR_IO_PENDING;
|
| +}
|
| +
|
| int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
|
| OldCompletionCallback* callback, bool truncate) {
|
| if (!callback)
|
| @@ -835,6 +911,24 @@ int EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
|
| return net::ERR_IO_PENDING;
|
| }
|
|
|
| +int EntryImpl::WriteData(
|
| + int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback, bool truncate) {
|
| + if (callback.is_null())
|
| + return WriteDataImpl(index, offset, buf, buf_len, callback, truncate);
|
| +
|
| + DCHECK(node_.Data()->dirty || read_only_);
|
| + if (index < 0 || index >= kNumStreams)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + if (offset < 0 || buf_len < 0)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + backend_->background_queue()->WriteData(this, index, offset, buf, buf_len,
|
| + truncate, callback);
|
| + return net::ERR_IO_PENDING;
|
| +}
|
| +
|
| int EntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
|
| net::OldCompletionCallback* callback) {
|
| if (!callback)
|
| @@ -1013,6 +1107,82 @@ int EntryImpl::InternalReadData(int index, int offset, net::IOBuffer* buf,
|
| return (completed || !callback) ? buf_len : net::ERR_IO_PENDING;
|
| }
|
|
|
| +int EntryImpl::InternalReadData(
|
| + int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback) {
|
| + DCHECK(node_.Data()->dirty || read_only_);
|
| + DVLOG(2) << "Read from " << index << " at " << offset << " : " << buf_len;
|
| + if (index < 0 || index >= kNumStreams)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + int entry_size = entry_.Data()->data_size[index];
|
| + if (offset >= entry_size || offset < 0 || !buf_len)
|
| + return 0;
|
| +
|
| + if (buf_len < 0)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + TimeTicks start = TimeTicks::Now();
|
| +
|
| + if (offset + buf_len > entry_size)
|
| + buf_len = entry_size - offset;
|
| +
|
| + UpdateRank(false);
|
| +
|
| + backend_->OnEvent(Stats::READ_DATA);
|
| + backend_->OnRead(buf_len);
|
| +
|
| + Addr address(entry_.Data()->data_addr[index]);
|
| + int eof = address.is_initialized() ? entry_size : 0;
|
| + if (user_buffers_[index].get() &&
|
| + user_buffers_[index]->PreRead(eof, offset, &buf_len)) {
|
| + // Complete the operation locally.
|
| + buf_len = user_buffers_[index]->Read(offset, buf, buf_len);
|
| + ReportIOTime(kRead, start);
|
| + return buf_len;
|
| + }
|
| +
|
| + address.set_value(entry_.Data()->data_addr[index]);
|
| + DCHECK(address.is_initialized());
|
| + if (!address.is_initialized())
|
| + return net::ERR_FAILED;
|
| +
|
| + File* file = GetBackingFile(address, index);
|
| + if (!file)
|
| + return net::ERR_FAILED;
|
| +
|
| + size_t file_offset = offset;
|
| + if (address.is_block_file()) {
|
| + DCHECK_LE(offset + buf_len, kMaxBlockSize);
|
| + file_offset += address.start_block() * address.BlockSize() +
|
| + kBlockHeaderSize;
|
| + }
|
| +
|
| + SyncCallback* io_callback = NULL;
|
| + if (!callback.is_null()) {
|
| + io_callback = new SyncCallback(this, buf, callback,
|
| + net::NetLog::TYPE_ENTRY_READ_DATA);
|
| + }
|
| +
|
| + TimeTicks start_async = TimeTicks::Now();
|
| +
|
| + bool completed;
|
| + if (!file->Read(buf->data(), buf_len, file_offset, io_callback, &completed)) {
|
| + if (io_callback)
|
| + io_callback->Discard();
|
| + return net::ERR_FAILED;
|
| + }
|
| +
|
| + if (io_callback && completed)
|
| + io_callback->Discard();
|
| +
|
| + if (io_callback)
|
| + ReportIOTime(kReadAsync1, start_async);
|
| +
|
| + ReportIOTime(kRead, start);
|
| + return (completed || callback.is_null()) ? buf_len : net::ERR_IO_PENDING;
|
| +}
|
| +
|
| int EntryImpl::InternalWriteData(int index, int offset, net::IOBuffer* buf,
|
| int buf_len, OldCompletionCallback* callback,
|
| bool truncate) {
|
| @@ -1113,6 +1283,106 @@ int EntryImpl::InternalWriteData(int index, int offset, net::IOBuffer* buf,
|
| return (completed || !callback) ? buf_len : net::ERR_IO_PENDING;
|
| }
|
|
|
| +int EntryImpl::InternalWriteData(
|
| + int index, int offset, net::IOBuffer* buf, int buf_len,
|
| + const net::CompletionCallback& callback, bool truncate) {
|
| + DCHECK(node_.Data()->dirty || read_only_);
|
| + DVLOG(2) << "Write to " << index << " at " << offset << " : " << buf_len;
|
| + if (index < 0 || index >= kNumStreams)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + if (offset < 0 || buf_len < 0)
|
| + return net::ERR_INVALID_ARGUMENT;
|
| +
|
| + int max_file_size = backend_->MaxFileSize();
|
| +
|
| + // offset or buf_len could be negative numbers.
|
| + if (offset > max_file_size || buf_len > max_file_size ||
|
| + offset + buf_len > max_file_size) {
|
| + int size = offset + buf_len;
|
| + if (size <= max_file_size)
|
| + size = kint32max;
|
| + backend_->TooMuchStorageRequested(size);
|
| + return net::ERR_FAILED;
|
| + }
|
| +
|
| + TimeTicks start = TimeTicks::Now();
|
| +
|
| + // Read the size at this point (it may change inside prepare).
|
| + int entry_size = entry_.Data()->data_size[index];
|
| + bool extending = entry_size < offset + buf_len;
|
| + truncate = truncate && entry_size > offset + buf_len;
|
| + Trace("To PrepareTarget 0x%x", entry_.address().value());
|
| + if (!PrepareTarget(index, offset, buf_len, truncate))
|
| + return net::ERR_FAILED;
|
| +
|
| + Trace("From PrepareTarget 0x%x", entry_.address().value());
|
| + if (extending || truncate)
|
| + UpdateSize(index, entry_size, offset + buf_len);
|
| +
|
| + UpdateRank(true);
|
| +
|
| + backend_->OnEvent(Stats::WRITE_DATA);
|
| + backend_->OnWrite(buf_len);
|
| +
|
| + if (user_buffers_[index].get()) {
|
| + // Complete the operation locally.
|
| + user_buffers_[index]->Write(offset, buf, buf_len);
|
| + ReportIOTime(kWrite, start);
|
| + return buf_len;
|
| + }
|
| +
|
| + Addr address(entry_.Data()->data_addr[index]);
|
| + if (offset + buf_len == 0) {
|
| + if (truncate) {
|
| + DCHECK(!address.is_initialized());
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| + File* file = GetBackingFile(address, index);
|
| + if (!file)
|
| + return net::ERR_FAILED;
|
| +
|
| + size_t file_offset = offset;
|
| + if (address.is_block_file()) {
|
| + DCHECK_LE(offset + buf_len, kMaxBlockSize);
|
| + file_offset += address.start_block() * address.BlockSize() +
|
| + kBlockHeaderSize;
|
| + } else if (truncate || (extending && !buf_len)) {
|
| + if (!file->SetLength(offset + buf_len))
|
| + return net::ERR_FAILED;
|
| + }
|
| +
|
| + if (!buf_len)
|
| + return 0;
|
| +
|
| + SyncCallback* io_callback = NULL;
|
| + if (!callback.is_null()) {
|
| + io_callback = new SyncCallback(this, buf, callback,
|
| + net::NetLog::TYPE_ENTRY_WRITE_DATA);
|
| + }
|
| +
|
| + TimeTicks start_async = TimeTicks::Now();
|
| +
|
| + bool completed;
|
| + if (!file->Write(buf->data(), buf_len, file_offset, io_callback,
|
| + &completed)) {
|
| + if (io_callback)
|
| + io_callback->Discard();
|
| + return net::ERR_FAILED;
|
| + }
|
| +
|
| + if (io_callback && completed)
|
| + io_callback->Discard();
|
| +
|
| + if (io_callback)
|
| + ReportIOTime(kWriteAsync1, start_async);
|
| +
|
| + ReportIOTime(kWrite, start);
|
| + return (completed || callback.is_null()) ? buf_len : net::ERR_IO_PENDING;
|
| +}
|
| +
|
| // ------------------------------------------------------------------------
|
|
|
| bool EntryImpl::CreateDataBlock(int index, int size) {
|
|
|