1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <algorithm> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/message_loop/message_loop.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/io_buffer.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/net_errors.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileStreamReader; 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const size_t kDesiredNumberOfBuffers = 2; // So we are always one buffer ahead. 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kBufferSize = 1024*1024; // 1MB to minimize transaction costs. 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ReadaheadFileStreamReader::ReadaheadFileStreamReader(FileStreamReader* source) 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : source_(source), 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_error_(0), 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_has_pending_read_(false), 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_(this) { 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ReadaheadFileStreamReader::~ReadaheadFileStreamReader() {} 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ReadaheadFileStreamReader::Read( 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) { 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!pending_sink_buffer_.get()); 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(pending_read_callback_.is_null()); 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReadFromSourceIfNeeded(); 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::DrainableIOBuffer> sink = 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new net::DrainableIOBuffer(buf, buf_len); 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int result = FinishReadFromCacheOrStoredError(sink.get()); 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We are waiting for an source read to complete, so save the request. 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result == net::ERR_IO_PENDING) { 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!pending_sink_buffer_.get()); 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(pending_read_callback_.is_null()); 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_sink_buffer_ = sink; 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_read_callback_ = callback; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return result; 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int64 ReadaheadFileStreamReader::GetLength( 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const net::Int64CompletionCallback& callback) { 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return source_->GetLength(callback); 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ReadaheadFileStreamReader::FinishReadFromCacheOrStoredError( 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::DrainableIOBuffer* sink) { 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If we don't have any ready cache, return the pending read code, or 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the stored error code. 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (buffers_.empty()) { 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source_.get()) { 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(source_has_pending_read_); 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return net::ERR_IO_PENDING; 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return source_error_; 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (sink->BytesRemaining() > 0 && !buffers_.empty()) { 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::DrainableIOBuffer* source_buffer = buffers_.front().get(); 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(source_buffer->BytesRemaining() > 0); 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int copy_len = std::min(source_buffer->BytesRemaining(), 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink->BytesRemaining()); 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::copy(source_buffer->data(), source_buffer->data() + copy_len, 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink->data()); 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_buffer->DidConsume(copy_len); 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink->DidConsume(copy_len); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source_buffer->BytesRemaining() == 0) { 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers_.pop(); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Get a new buffer to replace the one we just used up. 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReadFromSourceIfNeeded(); 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return sink->BytesConsumed(); 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ReadaheadFileStreamReader::ReadFromSourceIfNeeded() { 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!source_.get() || source_has_pending_read_ || 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers_.size() >= kDesiredNumberOfBuffers) { 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_has_pending_read_ = true; 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize)); 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result = source_->Read( 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buf.get(), 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kBufferSize, 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&ReadaheadFileStreamReader::OnFinishReadFromSource, 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.GetWeakPtr(), 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buf)); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result != net::ERR_IO_PENDING) 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnFinishReadFromSource(buf.get(), result); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ReadaheadFileStreamReader::OnFinishReadFromSource(net::IOBuffer* buf, 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int result) { 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(result != net::ERR_IO_PENDING); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(source_has_pending_read_); 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_has_pending_read_ = false; 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Either store the data read from |source_|, or store the error code. 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result > 0) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::DrainableIOBuffer> drainable_buffer( 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new net::DrainableIOBuffer(buf, result)); 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers_.push(drainable_buffer); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReadFromSourceIfNeeded(); 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_.reset(); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source_error_ = result; 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If there's a read request waiting for the source FileStreamReader to 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // finish reading, fulfill that request now from the cache or stored error. 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (pending_sink_buffer_.get()) { 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!pending_read_callback_.is_null()); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Free the pending callback before running it, as the callback often 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // dispatches another read. 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::DrainableIOBuffer> sink = pending_sink_buffer_; 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_sink_buffer_ = NULL; 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::CompletionCallback completion_callback = pending_read_callback_; 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_read_callback_.Reset(); 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci completion_callback.Run(FinishReadFromCacheOrStoredError(sink.get())); 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 148