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

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 // Represents an outstanding read request, waiting for the buffer to be filled
24 // from the source FileStreamReader.
25 struct ReadaheadFileStreamReader::Request {
vandebo (ex-Chrome) 2014/03/04 18:51:32 You only have one of these... There's no need to
tommycli 2014/03/04 21:14:58 Done.
26 Request(net::IOBuffer* buf, int buf_len,
27 const net::CompletionCallback& callback)
28 : buf(buf),
29 buf_len(buf_len),
30 callback(callback) {
31 }
32
33 ~Request() {}
34
35 scoped_refptr<net::IOBuffer> buf;
36 const int buf_len;
vandebo (ex-Chrome) 2014/03/04 18:51:32 Instead of storing the IOBuffer and length and wra
tommycli 2014/03/04 21:14:58 Done.
37 const net::CompletionCallback callback;
38 };
39
40 ReadaheadFileStreamReader::ReadaheadFileStreamReader(FileStreamReader* source)
41 : source_(source),
42 source_error_(0),
43 current_offset_(0),
44 source_has_pending_read_(false),
45 weak_factory_(this) {
46 }
47
48 ReadaheadFileStreamReader::~ReadaheadFileStreamReader() {}
49
50 int ReadaheadFileStreamReader::Read(
51 net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) {
52 DCHECK(!pending_read_.get());
53
54 // Dispatch a request to fill up our buffers if needed.
55 if (source_.get() && !source_has_pending_read_ &&
vandebo (ex-Chrome) 2014/03/04 18:51:32 push these conditionals down into ReadFromSource(I
tommycli 2014/03/04 21:14:58 Done.
56 buffers_.size() < kDesiredNumberOfBuffers) {
57 ReadFromSource();
58 }
59
60 // Consume from our existing buffers and return immediately if possible.
vandebo (ex-Chrome) 2014/03/04 18:51:32 Maybe push lines 60-66 into ConsumeFromBuffer and
tommycli 2014/03/04 21:14:58 Done.
61 if (!buffers_.empty())
62 return ConsumeFromBuffer(buf, buf_len);
63
64 // Pass through the stored source error or EOF if existent.
65 if (!source_.get())
66 return source_error_;
67
68 // We are waiting for an source read to complete, so save the request.
69 DCHECK(!pending_read_.get());
70 pending_read_.reset(new Request(buf, buf_len, callback));
71 return net::ERR_IO_PENDING;
72 }
73
74 int64 ReadaheadFileStreamReader::GetLength(
75 const net::Int64CompletionCallback& callback) {
76 return source_->GetLength(callback);
77 }
78
79 int ReadaheadFileStreamReader::ConsumeFromBuffer(net::IOBuffer* buf,
80 int buf_len) {
81 DCHECK(!buffers_.empty());
82
83 // |buf| continues to exist after |sink| goes out of scope.
vandebo (ex-Chrome) 2014/03/04 18:51:32 This comment doesn't seem necessary, since sink li
tommycli 2014/03/04 21:14:58 Done.
84 scoped_refptr<net::DrainableIOBuffer> sink(
85 new net::DrainableIOBuffer(buf, buf_len));
86
87 while (sink->BytesRemaining() > 0 && !buffers_.empty()) {
88 net::DrainableIOBuffer* head_buffer = buffers_.front().get();
vandebo (ex-Chrome) 2014/03/04 18:51:32 If you're calling the destination sink, might as w
tommycli 2014/03/04 21:14:58 Done.
89
90 DCHECK(head_buffer->BytesRemaining() > 0);
91
92 int copy_len = std::min(head_buffer->BytesRemaining(),
93 sink->BytesRemaining());
94 std::copy(head_buffer->data(), head_buffer->data() + copy_len,
95 sink->data());
96
97 head_buffer->DidConsume(copy_len);
98 sink->DidConsume(copy_len);
99
100 if (head_buffer->BytesRemaining() == 0) {
101 buffers_.pop();
vandebo (ex-Chrome) 2014/03/04 18:51:32 This is unfortunate - we're going to free a meg of
tommycli 2014/03/04 21:14:58 Last patchset adds something to reuse the just-exh
102
103 // Get a new buffer to replace the one we just used up.
104 if (!source_has_pending_read_ && source_.get())
105 ReadFromSource();
106 }
107 }
108
109 return sink->BytesConsumed();
110 }
111
112 void ReadaheadFileStreamReader::ReadFromSource() {
113 DCHECK(!source_has_pending_read_);
114 source_has_pending_read_ = true;
115
116 // We don't create the DrainableIOBuffer wrapper until the callback, when
117 // we know the size of the content written to the buffer.
118 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
119 int result = source_->Read(
120 buf,
121 kBufferSize,
122 base::Bind(&ReadaheadFileStreamReader::OnFinishReadFromSource,
123 weak_factory_.GetWeakPtr(), buf));
124
125 if (result != net::ERR_IO_PENDING) {
126 OnFinishReadFromSource(buf, result);
127 }
128 }
129
130 void ReadaheadFileStreamReader::OnFinishReadFromSource(net::IOBuffer* buf,
131 int result) {
132 DCHECK(result != net::ERR_IO_PENDING);
133 DCHECK(source_has_pending_read_);
134 source_has_pending_read_ = false;
135
136 if (result <= 0) {
137 source_.reset();
138 source_error_ = result;
139
140 // If there's a read waiting on this source-read, finish it with the error.
141 if (pending_read_.get()) {
vandebo (ex-Chrome) 2014/03/04 18:51:32 If you push lines 65 and 66 into ComsumeFromBuffer
tommycli 2014/03/04 21:14:58 Done.
142 pending_read_->callback.Run(result);
143 pending_read_.reset();
144 }
145
146 return;
147 }
148
149 scoped_refptr<net::DrainableIOBuffer> drainable_buffer(
150 new net::DrainableIOBuffer(buf, result));
151 buffers_.push(drainable_buffer);
152
153 // If there's a read request waiting for the source FileStreamReader to
154 // finish reading, fulfill that request now.
155 if (pending_read_.get()) {
156 // Free up pending read immediately, as the read completion callback often
157 // dispatches another read.
158 scoped_ptr<Request> request(pending_read_.Pass());
159
160 request->callback.Run(ConsumeFromBuffer(request->buf, request->buf_len));
161 }
162 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698