1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_stream_reader.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
13 namespace file_system_provider {
15 BufferingFileStreamReader::BufferingFileStreamReader(
16 scoped_ptr<webkit_blob::FileStreamReader> file_stream_reader,
18 : file_stream_reader_(file_stream_reader.Pass()),
19 buffer_size_(buffer_size),
20 preloading_buffer_(new net::IOBuffer(buffer_size_)),
21 preloading_buffer_offset_(0),
23 weak_ptr_factory_(this) {
26 BufferingFileStreamReader::~BufferingFileStreamReader() {
29 int BufferingFileStreamReader::Read(net::IOBuffer* buffer,
31 const net::CompletionCallback& callback) {
32 // Return as much as available in the internal buffer. It may be less than
33 // |buffer_length|, what is valid.
34 const int bytes_read =
35 CopyFromPreloadingBuffer(make_scoped_refptr(buffer), buffer_length);
39 // If the internal buffer is empty, and more bytes than the internal buffer
40 // size is requested, then call the internal file stream reader directly.
41 if (buffer_length >= buffer_size_) {
43 file_stream_reader_->Read(buffer, buffer_length, callback);
44 DCHECK_EQ(result, net::ERR_IO_PENDING);
48 // Nothing copied, so contents have to be preloaded.
49 Preload(base::Bind(&BufferingFileStreamReader::OnPreloadCompleted,
50 weak_ptr_factory_.GetWeakPtr(),
51 make_scoped_refptr(buffer),
55 return net::ERR_IO_PENDING;
58 int64 BufferingFileStreamReader::GetLength(
59 const net::Int64CompletionCallback& callback) {
60 const int64 result = file_stream_reader_->GetLength(callback);
61 DCHECK_EQ(net::ERR_IO_PENDING, result);
66 int BufferingFileStreamReader::CopyFromPreloadingBuffer(
67 scoped_refptr<net::IOBuffer> buffer,
69 const int read_bytes = std::min(buffer_length, buffered_bytes_);
71 memcpy(buffer->data(),
72 preloading_buffer_->data() + preloading_buffer_offset_,
74 preloading_buffer_offset_ += read_bytes;
75 buffered_bytes_ -= read_bytes;
80 void BufferingFileStreamReader::Preload(
81 const net::CompletionCallback& callback) {
82 // TODO(mtomasz): Dynamically calculate the chunk size. Start from a small
83 // one, then increase for consecutive requests. That would improve performance
84 // when reading just small chunks, instead of the entire file.
85 const int preload_bytes = buffer_size_;
88 file_stream_reader_->Read(preloading_buffer_, preload_bytes, callback);
89 DCHECK_EQ(result, net::ERR_IO_PENDING);
92 void BufferingFileStreamReader::OnPreloadCompleted(
93 scoped_refptr<net::IOBuffer> buffer,
95 const net::CompletionCallback& callback,
102 preloading_buffer_offset_ = 0;
103 buffered_bytes_ = result;
105 callback.Run(CopyFromPreloadingBuffer(buffer, buffer_length));
108 } // namespace file_system_provider
109 } // namespace chromeos