OLD | NEW |
---|---|
(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 } | |
27 | |
28 int BufferingFileStreamWriter::Write(net::IOBuffer* buffer, | |
29 int buffer_length, | |
30 const net::CompletionCallback& callback) { | |
31 // If |buffer_length| is larger than the intermediate buffer, then call the | |
32 // internal file stream writer directly. Note, that the intermediate buffer | |
33 // (used for buffering) must be flushed first. | |
34 if (buffer_length > intermediate_buffer_length_) { | |
35 if (buffered_bytes_) { | |
36 FlushIntermediateBuffer( | |
37 base::Bind(&BufferingFileStreamWriter:: | |
38 OnFlushIntermediateBufferForDirectWriteCompleted, | |
39 weak_ptr_factory_.GetWeakPtr(), | |
40 make_scoped_refptr(buffer), | |
41 buffer_length, | |
42 callback)); | |
43 } else { | |
44 // Nothing to flush, so skip it. | |
45 OnFlushIntermediateBufferForDirectWriteCompleted( | |
46 make_scoped_refptr(buffer), buffer_length, callback, net::OK); | |
47 } | |
48 return net::ERR_IO_PENDING; | |
49 } | |
50 | |
51 // Buffer consecutive writes to larger chunks. | |
52 const int buffer_bytes = | |
53 std::min(intermediate_buffer_length_ - buffered_bytes_, buffer_length); | |
54 | |
55 CopyToIntermediateBuffer( | |
56 make_scoped_refptr(buffer), 0 /* offset */, buffer_bytes); | |
57 const int bytes_left = buffer_length - buffer_bytes; | |
58 | |
59 if (buffered_bytes_ == intermediate_buffer_length_) { | |
60 FlushIntermediateBuffer( | |
61 base::Bind(&BufferingFileStreamWriter:: | |
62 OnFlushIntermediateBufferForBufferedWriteCompleted, | |
63 weak_ptr_factory_.GetWeakPtr(), | |
64 make_scoped_refptr(buffer), | |
65 buffer_bytes, | |
66 bytes_left, | |
67 callback)); | |
68 return net::ERR_IO_PENDING; | |
69 } | |
70 | |
71 // Optimistically return a success. | |
72 return buffer_length; | |
73 } | |
74 | |
75 int BufferingFileStreamWriter::Cancel(const net::CompletionCallback& callback) { | |
76 return file_stream_writer_->Cancel(callback); | |
77 } | |
78 | |
79 int BufferingFileStreamWriter::Flush(const net::CompletionCallback& callback) { | |
80 // Flush all the buffered bytes first, then invoke Flush() on the inner file | |
81 // stream writer. | |
82 FlushIntermediateBuffer(base::Bind( | |
83 &BufferingFileStreamWriter::OnFlushIntermediateBufferForFlushCompleted, | |
84 weak_ptr_factory_.GetWeakPtr(), | |
85 callback)); | |
86 return net::ERR_IO_PENDING; | |
87 } | |
88 | |
89 void BufferingFileStreamWriter::CopyToIntermediateBuffer( | |
90 scoped_refptr<net::IOBuffer> buffer, | |
91 int offset, | |
92 int length) { | |
93 DCHECK_GE(intermediate_buffer_length_, offset + length + buffered_bytes_); | |
94 memcpy(intermediate_buffer_->data() + buffered_bytes_, | |
95 buffer->data() + offset, | |
96 length); | |
97 buffered_bytes_ += length; | |
98 } | |
99 | |
100 void BufferingFileStreamWriter::FlushIntermediateBuffer( | |
101 const net::CompletionCallback& callback) { | |
102 const int result = file_stream_writer_->Write( | |
103 intermediate_buffer_, | |
104 buffered_bytes_, | |
105 base::Bind(&BufferingFileStreamWriter::OnFlushIntermediateBufferCompleted, | |
106 weak_ptr_factory_.GetWeakPtr(), | |
107 buffered_bytes_, | |
108 callback)); | |
109 DCHECK_EQ(net::ERR_IO_PENDING, result); | |
110 } | |
111 | |
112 void BufferingFileStreamWriter::OnFlushIntermediateBufferCompleted( | |
113 int length, | |
114 const net::CompletionCallback& callback, | |
115 int result) { | |
116 if (result < 0) { | |
117 callback.Run(result); | |
118 return; | |
119 } | |
120 | |
121 DCHECK_EQ(length, result) << "Partial reads are not supported."; | |
122 buffered_bytes_ = 0; | |
123 callback.Run(net::OK); | |
124 } | |
125 | |
126 void | |
127 BufferingFileStreamWriter::OnFlushIntermediateBufferForDirectWriteCompleted( | |
128 scoped_refptr<net::IOBuffer> buffer, | |
129 int length, | |
130 const net::CompletionCallback& callback, | |
131 int result) { | |
132 if (result < 0) { | |
133 callback.Run(result); | |
134 return; | |
135 } | |
136 | |
137 // Write all bytes directly. | |
138 DCHECK_EQ(net::OK, result); | |
139 DCHECK_EQ(0, buffered_bytes_); | |
140 const int write_result = file_stream_writer_->Write(buffer, length, callback); | |
141 DCHECK_EQ(net::ERR_IO_PENDING, write_result); | |
142 } | |
143 | |
144 void | |
145 BufferingFileStreamWriter::OnFlushIntermediateBufferForBufferedWriteCompleted( | |
146 scoped_refptr<net::IOBuffer> buffer, | |
147 int buffered_bytes, | |
148 int bytes_left, | |
149 const net::CompletionCallback& callback, | |
150 int result) { | |
151 if (result < 0) { | |
152 callback.Run(result); | |
153 return; | |
154 } | |
155 | |
156 // Copy the rest of bytes to the buffer. | |
157 DCHECK_EQ(net::OK, result); | |
158 DCHECK_EQ(0, buffered_bytes_); | |
159 DCHECK_GE(intermediate_buffer_length_, bytes_left); | |
160 CopyToIntermediateBuffer(buffer, buffered_bytes, bytes_left); | |
161 | |
162 callback.Run(buffered_bytes + bytes_left); | |
163 } | |
164 | |
165 void BufferingFileStreamWriter::OnFlushIntermediateBufferForFlushCompleted( | |
166 const net::CompletionCallback& callback, | |
167 int result) { | |
168 if (result < 0) { | |
169 callback.Run(result); | |
170 return; | |
171 } | |
172 | |
173 const int flush_result = file_stream_writer_->Flush(callback); | |
174 DCHECK_EQ(net::ERR_IO_PENDING, flush_result); | |
hashimoto
2014/08/28 08:32:17
It seems FileStreamWriter::Flush doesn't return ER
mtomasz
2014/08/29 02:49:00
Done.
| |
175 } | |
176 | |
177 } // namespace file_system_provider | |
178 } // namespace chromeos | |
OLD | NEW |