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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_stream_writer.cc

Issue 502973005: [fsp] Buffer consecutive Write() calls. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added a comment. Created 6 years, 2 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
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/chromeos/file_system_provider/fileapi/buffering_file_st ream_writer.h"
6
7 #include <algorithm>
8
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11
12 namespace chromeos {
13 namespace file_system_provider {
14
15 BufferingFileStreamWriter::BufferingFileStreamWriter(
16 scoped_ptr<storage::FileStreamWriter> file_stream_writer,
17 int intermediate_buffer_length)
18 : file_stream_writer_(file_stream_writer.Pass()),
19 intermediate_buffer_length_(intermediate_buffer_length),
20 intermediate_buffer_(new net::IOBuffer(intermediate_buffer_length_)),
21 buffered_bytes_(0),
22 weak_ptr_factory_(this) {
23 }
24
25 BufferingFileStreamWriter::~BufferingFileStreamWriter() {
26 if (buffered_bytes_)
27 LOG(ERROR) << "File stream writer not flushed. Data will be lost.";
28 }
29
30 int BufferingFileStreamWriter::Write(net::IOBuffer* buffer,
31 int buffer_length,
32 const net::CompletionCallback& callback) {
33 // If |buffer_length| is larger than the intermediate buffer, then call the
34 // inner file stream writer directly. Note, that the intermediate buffer
35 // (used for buffering) must be flushed first.
36 if (buffer_length > intermediate_buffer_length_) {
37 if (buffered_bytes_) {
38 FlushIntermediateBuffer(
39 base::Bind(&BufferingFileStreamWriter::
40 OnFlushIntermediateBufferForDirectWriteCompleted,
41 weak_ptr_factory_.GetWeakPtr(),
42 make_scoped_refptr(buffer),
43 buffer_length,
44 callback));
45 } else {
46 // Nothing to flush, so skip it.
47 OnFlushIntermediateBufferForDirectWriteCompleted(
48 make_scoped_refptr(buffer), buffer_length, callback, net::OK);
49 }
50 return net::ERR_IO_PENDING;
51 }
52
53 // Buffer consecutive writes to larger chunks.
54 const int buffer_bytes =
55 std::min(intermediate_buffer_length_ - buffered_bytes_, buffer_length);
56
57 CopyToIntermediateBuffer(
58 make_scoped_refptr(buffer), 0 /* buffer_offset */, buffer_bytes);
59 const int bytes_left = buffer_length - buffer_bytes;
60
61 if (buffered_bytes_ == intermediate_buffer_length_) {
62 FlushIntermediateBuffer(
63 base::Bind(&BufferingFileStreamWriter::
64 OnFlushIntermediateBufferForBufferedWriteCompleted,
65 weak_ptr_factory_.GetWeakPtr(),
66 make_scoped_refptr(buffer),
67 buffer_bytes,
68 bytes_left,
69 callback));
70 return net::ERR_IO_PENDING;
71 }
72
73 // Optimistically return a success.
74 return buffer_length;
75 }
76
77 int BufferingFileStreamWriter::Cancel(const net::CompletionCallback& callback) {
78 // Since there is no any asynchronous call in this class other than on
79 // |file_stream_writer_|, then there must be an in-flight operation going on.
80 return file_stream_writer_->Cancel(callback);
81 }
82
83 int BufferingFileStreamWriter::Flush(const net::CompletionCallback& callback) {
84 // Flush all the buffered bytes first, then invoke Flush() on the inner file
85 // stream writer.
86 FlushIntermediateBuffer(base::Bind(
87 &BufferingFileStreamWriter::OnFlushIntermediateBufferForFlushCompleted,
88 weak_ptr_factory_.GetWeakPtr(),
89 callback));
90 return net::ERR_IO_PENDING;
91 }
92
93 void BufferingFileStreamWriter::CopyToIntermediateBuffer(
94 scoped_refptr<net::IOBuffer> buffer,
95 int buffer_offset,
96 int buffer_length) {
97 DCHECK_GE(intermediate_buffer_length_, buffer_length + buffered_bytes_);
98 memcpy(intermediate_buffer_->data() + buffered_bytes_,
99 buffer->data() + buffer_offset,
100 buffer_length);
101 buffered_bytes_ += buffer_length;
102 }
103
104 void BufferingFileStreamWriter::FlushIntermediateBuffer(
105 const net::CompletionCallback& callback) {
106 const int result = file_stream_writer_->Write(
107 intermediate_buffer_.get(),
108 buffered_bytes_,
109 base::Bind(&BufferingFileStreamWriter::OnFlushIntermediateBufferCompleted,
110 weak_ptr_factory_.GetWeakPtr(),
111 buffered_bytes_,
112 callback));
113 DCHECK_EQ(net::ERR_IO_PENDING, result);
114 }
115
116 void BufferingFileStreamWriter::OnFlushIntermediateBufferCompleted(
117 int length,
118 const net::CompletionCallback& callback,
119 int result) {
120 if (result < 0) {
121 callback.Run(result);
122 return;
123 }
124
125 DCHECK_EQ(length, result) << "Partial writes are not supported.";
126 buffered_bytes_ = 0;
127
128 callback.Run(net::OK);
129 }
130
131 void
132 BufferingFileStreamWriter::OnFlushIntermediateBufferForDirectWriteCompleted(
133 scoped_refptr<net::IOBuffer> buffer,
134 int length,
135 const net::CompletionCallback& callback,
136 int result) {
137 if (result < 0) {
138 callback.Run(result);
139 return;
140 }
141
142 // The following logic is only valid if the intermediate buffer is empty.
143 DCHECK_EQ(0, buffered_bytes_);
144
145 const int write_result =
146 file_stream_writer_->Write(buffer.get(), length, callback);
147 DCHECK_EQ(net::ERR_IO_PENDING, write_result);
148 }
149
150 void
151 BufferingFileStreamWriter::OnFlushIntermediateBufferForBufferedWriteCompleted(
152 scoped_refptr<net::IOBuffer> buffer,
153 int buffered_bytes,
154 int bytes_left,
155 const net::CompletionCallback& callback,
156 int result) {
157 if (result < 0) {
158 callback.Run(result);
159 return;
160 }
161
162 // Copy the rest of bytes to the buffer.
163 DCHECK_EQ(net::OK, result);
164 DCHECK_EQ(0, buffered_bytes_);
165 DCHECK_GE(intermediate_buffer_length_, bytes_left);
166 CopyToIntermediateBuffer(buffer, buffered_bytes, bytes_left);
167
168 callback.Run(buffered_bytes + bytes_left);
169 }
170
171 void BufferingFileStreamWriter::OnFlushIntermediateBufferForFlushCompleted(
172 const net::CompletionCallback& callback,
173 int result) {
174 if (result < 0) {
175 callback.Run(result);
176 return;
177 }
178
179 const int flush_result = file_stream_writer_->Flush(callback);
180 DCHECK_EQ(net::ERR_IO_PENDING, flush_result);
181 }
182
183 } // namespace file_system_provider
184 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698