Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Side by Side Diff: chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.cc

Issue 178473022: MTP Streaming: Readahead Buffer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.h"
6
7 #include <algorithm>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13
14 using webkit_blob::FileStreamReader;
15
16 namespace {
17
18 const int kDesiredNumberOfBuffers = 2; // So we are always one buffer ahead.
19 const int kBufferSize = 1024*1024; // 1MB to minimize transaction costs.
20
21 } // namespace
22
23 ReadaheadFileStreamReader::ReadaheadFileStreamReader(
24 FileStreamReader* underlying)
25 : underlying_(underlying),
26 underlying_error_(0),
27 current_offset_(0),
28 underlying_has_pending_read_(false),
29 weak_factory_(this) {
30 }
31
32 ReadaheadFileStreamReader::~ReadaheadFileStreamReader() {}
33
34 int ReadaheadFileStreamReader::Read(
35 net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) {
36 DCHECK(!pending_read_.get());
37
38 // Dispatch a request to fill up our buffers if needed.
39 if (underlying_.get() && !underlying_has_pending_read_ &&
40 buffers_.size() < kDesiredNumberOfBuffers) {
41 ReadFromUnderlying();
42 }
43
44 // Consume from our existing buffers and return immediately if possible.
45 if (!buffers_.empty())
46 return ConsumeFromBuffer(buf, buf_len);
47
48 // Pass through the stored underlying error or EOF if existent.
49 if (!underlying_.get())
50 return underlying_error_;
51
52 // We are waiting for an underlying read to complete, so save the request.
vandebo (ex-Chrome) 2014/03/03 22:24:54 DCHECK(!pending_read.get());
tommycli 2014/03/04 00:39:40 Done.
53 pending_read_.reset(new Request(buf, buf_len, callback));
54 return net::ERR_IO_PENDING;
55 }
56
57 int64 ReadaheadFileStreamReader::GetLength(
58 const net::Int64CompletionCallback& callback) {
59 return underlying_->GetLength(callback);
60 }
61
62 ReadaheadFileStreamReader::Request::Request(
63 net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback)
64 : buf(buf), buf_len(buf_len), callback(callback) {
vandebo (ex-Chrome) 2014/03/03 22:24:54 http://google-styleguide.googlecode.com/svn/trunk/
tommycli 2014/03/04 00:39:40 Done.
65 }
66
67 ReadaheadFileStreamReader::Request::~Request() {}
68
69 int ReadaheadFileStreamReader::ConsumeFromBuffer(net::IOBuffer* buf,
70 int buf_len) {
71 DCHECK(!buffers_.empty());
72
vandebo (ex-Chrome) 2014/03/03 22:24:54 Probably want a while loop here - there might only
tommycli 2014/03/04 00:39:40 Done.
73 net::DrainableIOBuffer* head_buffer = buffers_.front().get();
74
75 DCHECK(head_buffer->BytesRemaining() > 0);
76
77 int copy_len = std::min(buf_len, head_buffer->BytesRemaining());
78 std::copy(head_buffer->data(), head_buffer->data() + copy_len, buf->data());
79 head_buffer->DidConsume(copy_len);
80
81 if (head_buffer->BytesRemaining() == 0) {
82 buffers_.pop();
83
84 // Get a new buffer to replace the one we just used up.
85 if (!underlying_has_pending_read_ && underlying_.get())
86 ReadFromUnderlying();
87 }
88
89 return copy_len;
90 }
91
92 void ReadaheadFileStreamReader::ReadFromUnderlying() {
93 DCHECK(!underlying_has_pending_read_);
94 underlying_has_pending_read_ = true;
95
96 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
vandebo (ex-Chrome) 2014/03/03 22:24:54 Why not make a DrainableIOBuffer here instead of c
tommycli 2014/03/04 00:39:40 Added a comment. DrainableIOBuffer just wraps the
vandebo (ex-Chrome) 2014/03/04 18:51:32 Right. I figured that out, but forgot to remove m
tommycli 2014/03/04 21:14:58 Done.
97 int result = underlying_->Read(
98 buf,
99 kBufferSize,
100 base::Bind(&ReadaheadFileStreamReader::OnFinishReadFromUnderlying,
101 weak_factory_.GetWeakPtr(), buf));
102
103 if (result != net::ERR_IO_PENDING) {
vandebo (ex-Chrome) 2014/03/03 22:24:54 If we get ERR_IO_PENDING, you'll leave the request
tommycli 2014/03/04 00:39:40 As intended. If we get ERR_IO_PENDING, OnFinishRea
104 OnFinishReadFromUnderlying(buf, result);
105 }
106 }
107
108 void ReadaheadFileStreamReader::OnFinishReadFromUnderlying(net::IOBuffer* buf,
109 int result) {
110 DCHECK(result != net::ERR_IO_PENDING);
111 DCHECK(underlying_has_pending_read_);
112 underlying_has_pending_read_ = false;
113
114 if (result <= 0) {
115 underlying_.reset();
116 underlying_error_ = result;
vandebo (ex-Chrome) 2014/03/03 22:24:54 Doesn't this leave request hanging? You probably
tommycli 2014/03/04 00:39:40 Done. I didn't use a FinishRequest, as I couldn't
117 return;
118 }
119
120 scoped_refptr<net::DrainableIOBuffer> drainable_buffer(
121 new net::DrainableIOBuffer(buf, result));
122 buffers_.push(drainable_buffer);
123
vandebo (ex-Chrome) 2014/03/03 22:24:54 Should this kick off another read if buffers_.size
tommycli 2014/03/04 00:39:40 The ConsumeFromBuffer call within this if-block sh
124 // If there's a read request waiting for the underlying FileStreamReader to
125 // finish reading, fulfill that request now.
126 if (pending_read_.get()) {
127 // Free up pending read immediately, as the read completion callback often
128 // dispatches another read.
129 scoped_ptr<Request> request(pending_read_.Pass());
130
131 request->callback.Run(ConsumeFromBuffer(request->buf, request->buf_len));
132 }
133 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698