OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/upload_data_stream.h" | 5 #include "net/base/upload_data_stream.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/message_loop.h" | |
8 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
9 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
10 #include "net/base/upload_element_reader.h" | 11 #include "net/base/upload_element_reader.h" |
11 | 12 |
12 namespace net { | 13 namespace net { |
13 | 14 |
14 bool UploadDataStream::merge_chunks_ = true; | 15 bool UploadDataStream::merge_chunks_ = true; |
15 | 16 |
16 // static | 17 // static |
17 void UploadDataStream::ResetMergeChunks() { | 18 void UploadDataStream::ResetMergeChunks() { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 if (result != OK) { | 56 if (result != OK) { |
56 element_readers_.clear(); | 57 element_readers_.clear(); |
57 return result; | 58 return result; |
58 } | 59 } |
59 } | 60 } |
60 | 61 |
61 FinalizeInitialization(); | 62 FinalizeInitialization(); |
62 return OK; | 63 return OK; |
63 } | 64 } |
64 | 65 |
65 int UploadDataStream::Read(IOBuffer* buf, int buf_len) { | 66 int UploadDataStream::Read(IOBuffer* buf, |
67 int buf_len, | |
68 const CompletionCallback& callback) { | |
69 DCHECK(initialized_successfully_); | |
70 | |
71 // Use fast path when all data is in memory, chunked data is also processed | |
72 // with ReadSync() since it requires special logic. | |
73 if (IsInMemory() || is_chunked()) | |
74 return ReadSync(buf, buf_len); | |
75 | |
76 const bool invoked_asynchronously = false; | |
77 return ReadInternal(buf, buf_len, 0, invoked_asynchronously, callback, 0); | |
78 } | |
79 | |
80 int UploadDataStream::ReadSync(IOBuffer* buf, int buf_len) { | |
66 DCHECK(initialized_successfully_); | 81 DCHECK(initialized_successfully_); |
67 | 82 |
68 // Initialize readers for newly appended chunks. | 83 // Initialize readers for newly appended chunks. |
69 if (is_chunked()) { | 84 if (is_chunked()) { |
70 const std::vector<UploadElement>& elements = *upload_data_->elements(); | 85 const std::vector<UploadElement>& elements = *upload_data_->elements(); |
71 DCHECK_LE(element_readers_.size(), elements.size()); | 86 DCHECK_LE(element_readers_.size(), elements.size()); |
72 | 87 |
73 for (size_t i = element_readers_.size(); i < elements.size(); ++i) { | 88 for (size_t i = element_readers_.size(); i < elements.size(); ++i) { |
74 const UploadElement& element = elements[i]; | 89 const UploadElement& element = elements[i]; |
75 DCHECK_EQ(UploadElement::TYPE_BYTES, element.type()); | 90 DCHECK_EQ(UploadElement::TYPE_BYTES, element.type()); |
mmenke
2012/10/11 18:05:40
Wait...so we allow TYPE_BYTES to be added after co
hashimoto
2012/10/12 07:36:56
We allow adding data after construction only if th
mmenke
2012/10/12 21:30:29
None of this is documented anywhere. Could we fix
hashimoto
2012/10/15 11:21:37
Thank you for your kind suggestion.
Added comments
| |
76 UploadElementReader* reader = UploadElementReader::Create(element); | 91 UploadElementReader* reader = UploadElementReader::Create(element); |
77 | 92 |
78 const int rv = reader->InitSync(); | 93 const int rv = reader->InitSync(); |
79 DCHECK_EQ(rv, OK); | 94 DCHECK_EQ(rv, OK); |
80 element_readers_.push_back(reader); | 95 element_readers_.push_back(reader); |
81 } | 96 } |
82 } | 97 } |
83 | 98 |
84 int bytes_copied = 0; | 99 int bytes_copied = 0; |
85 while (bytes_copied < buf_len && element_index_ < element_readers_.size()) { | 100 while (bytes_copied < buf_len && element_index_ < element_readers_.size()) { |
86 UploadElementReader* reader = element_readers_[element_index_]; | 101 UploadElementReader* reader = element_readers_[element_index_]; |
87 bytes_copied += reader->ReadSync(buf->data() + bytes_copied, | 102 scoped_refptr<DrainableIOBuffer> sub_buffer = |
88 buf_len - bytes_copied); | 103 new DrainableIOBuffer(buf, buf_len); |
104 sub_buffer->SetOffset(bytes_copied); | |
105 bytes_copied += reader->ReadSync(sub_buffer, sub_buffer->BytesRemaining()); | |
89 if (reader->BytesRemaining() == 0) | 106 if (reader->BytesRemaining() == 0) |
90 ++element_index_; | 107 ++element_index_; |
91 | 108 |
92 if (is_chunked() && !merge_chunks_) | 109 if (is_chunked() && !merge_chunks_) |
93 break; | 110 break; |
94 } | 111 } |
95 | 112 |
96 current_position_ += bytes_copied; | 113 current_position_ += bytes_copied; |
97 if (is_chunked() && !IsEOF() && bytes_copied == 0) | 114 if (is_chunked() && !IsEOF() && bytes_copied == 0) |
98 return ERR_IO_PENDING; | 115 return ERR_IO_PENDING; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 uint64 total_size = 0; | 189 uint64 total_size = 0; |
173 for (size_t i = 0; i < element_readers_.size(); ++i) { | 190 for (size_t i = 0; i < element_readers_.size(); ++i) { |
174 UploadElementReader* reader = element_readers_[i]; | 191 UploadElementReader* reader = element_readers_[i]; |
175 total_size += reader->GetContentLength(); | 192 total_size += reader->GetContentLength(); |
176 } | 193 } |
177 total_size_ = total_size; | 194 total_size_ = total_size; |
178 } | 195 } |
179 initialized_successfully_ = true; | 196 initialized_successfully_ = true; |
180 } | 197 } |
181 | 198 |
199 int UploadDataStream::ReadInternal(scoped_refptr<IOBuffer> buf, | |
200 int buf_len, | |
201 int bytes_copied, | |
202 bool invoked_asynchronously, | |
203 const CompletionCallback& callback, | |
204 int previous_result) { | |
205 DCHECK(initialized_successfully_); | |
206 DCHECK_GE(previous_result, 0); | |
207 | |
208 // Add the last result. | |
209 bytes_copied += previous_result; | |
210 | |
211 while (bytes_copied < buf_len && element_index_ < element_readers_.size()) { | |
212 UploadElementReader* reader = element_readers_[element_index_]; | |
213 | |
214 if (reader->BytesRemaining() == 0) { | |
215 ++element_index_; | |
216 continue; | |
217 } | |
218 scoped_refptr<DrainableIOBuffer> sub_buffer = | |
219 new DrainableIOBuffer(buf, buf_len); | |
220 sub_buffer->SetOffset(bytes_copied); | |
221 const int result = reader->Read( | |
222 sub_buffer, | |
223 sub_buffer->BytesRemaining(), | |
224 base::Bind(base::IgnoreResult(&UploadDataStream::ReadInternal), | |
225 weak_ptr_factory_.GetWeakPtr(), | |
226 buf, | |
227 buf_len, | |
228 bytes_copied, | |
229 true, // invoked_asynchronously | |
230 callback)); | |
231 if (result == ERR_IO_PENDING) | |
232 return ERR_IO_PENDING; | |
233 | |
234 DCHECK_GE(bytes_copied, 0); | |
235 bytes_copied += result; | |
236 } | |
237 current_position_ += bytes_copied; | |
238 | |
239 // When invoked asynchronously, callback is the only way to return the result. | |
240 if (invoked_asynchronously) | |
241 callback.Run(bytes_copied); | |
242 return bytes_copied; | |
243 } | |
244 | |
182 } // namespace net | 245 } // namespace net |
OLD | NEW |