Chromium Code Reviews| 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); | |
|
hashimoto
2014/09/11 07:52:16
Could you add a comment to describe how this imple
mtomasz
2014/09/17 04:59:40
Done.
| |
| 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, | |
|
hashimoto
2014/09/11 07:52:16
It's ambiguous whether |offset| is for the argumen
mtomasz
2014/09/17 04:59:40
It's clearly described in the header file.
| |
| 92 int length) { | |
| 93 DCHECK_GE(intermediate_buffer_length_, offset + length + buffered_bytes_); | |
|
hashimoto
2014/09/11 07:52:16
What does the value of "offset + length + buffered
mtomasz
2014/09/17 04:59:40
Position of the last byte to be written. This DCHE
hashimoto
2014/09/22 12:10:31
Then shouldn't this be buffer_length + buffered_by
mtomasz
2014/09/24 01:45:31
That's right. Fixed.
| |
| 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 buffered_bytes_ = 0; | |
| 122 | |
| 123 DCHECK_EQ(length, result) << "Partial writes are not supported."; | |
| 124 callback.Run(net::OK); | |
| 125 } | |
| 126 | |
| 127 void | |
| 128 BufferingFileStreamWriter::OnFlushIntermediateBufferForDirectWriteCompleted( | |
| 129 scoped_refptr<net::IOBuffer> buffer, | |
| 130 int length, | |
| 131 const net::CompletionCallback& callback, | |
| 132 int result) { | |
| 133 if (result < 0) { | |
| 134 callback.Run(result); | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 // Write all bytes directly. | |
| 139 DCHECK_EQ(net::OK, result); | |
|
hashimoto
2014/09/11 07:52:16
nit: Why are you checking this here and in the met
mtomasz
2014/09/17 04:59:40
It's not possible, but since FlushIntermediateBuff
hashimoto
2014/09/22 12:10:31
I still don't see any reason to check |result| whi
mtomasz
2014/09/24 01:45:31
Yeah, seems not really helping much here. Removed.
| |
| 140 DCHECK_EQ(0, buffered_bytes_); | |
| 141 const int write_result = file_stream_writer_->Write(buffer, length, callback); | |
| 142 DCHECK_EQ(net::ERR_IO_PENDING, write_result); | |
| 143 } | |
| 144 | |
| 145 void | |
| 146 BufferingFileStreamWriter::OnFlushIntermediateBufferForBufferedWriteCompleted( | |
| 147 scoped_refptr<net::IOBuffer> buffer, | |
| 148 int buffered_bytes, | |
| 149 int bytes_left, | |
| 150 const net::CompletionCallback& callback, | |
| 151 int result) { | |
| 152 if (result < 0) { | |
| 153 callback.Run(result); | |
| 154 return; | |
| 155 } | |
| 156 | |
| 157 // Copy the rest of bytes to the buffer. | |
| 158 DCHECK_EQ(net::OK, result); | |
| 159 DCHECK_EQ(0, buffered_bytes_); | |
| 160 DCHECK_GE(intermediate_buffer_length_, bytes_left); | |
| 161 CopyToIntermediateBuffer(buffer, buffered_bytes, bytes_left); | |
| 162 | |
| 163 callback.Run(buffered_bytes + bytes_left); | |
| 164 } | |
| 165 | |
| 166 void BufferingFileStreamWriter::OnFlushIntermediateBufferForFlushCompleted( | |
| 167 const net::CompletionCallback& callback, | |
| 168 int result) { | |
| 169 if (result < 0) { | |
| 170 callback.Run(result); | |
| 171 return; | |
| 172 } | |
| 173 | |
| 174 const int flush_result = file_stream_writer_->Flush(callback); | |
| 175 DCHECK_EQ(net::ERR_IO_PENDING, flush_result); | |
| 176 } | |
| 177 | |
| 178 } // namespace file_system_provider | |
| 179 } // namespace chromeos | |
| OLD | NEW |