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

Unified Diff: net/base/upload_data_stream.cc

Issue 10910268: net: Make UploadDataStream::Read() asynchronous (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/upload_data_stream.h ('k') | net/base/upload_data_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/upload_data_stream.cc
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
index a62528d9bf816adacef194387cd06d21178f2fab..5b57a26b1aaa9d3a40277c3152521d515aa2e14e 100644
--- a/net/base/upload_data_stream.cc
+++ b/net/base/upload_data_stream.cc
@@ -25,7 +25,7 @@ UploadDataStream::UploadDataStream(UploadData* upload_data)
total_size_(0),
current_position_(0),
initialized_successfully_(false),
- weak_ptr_factory_(this) {
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
const std::vector<UploadElement>& elements = *upload_data_->elements();
for (size_t i = 0; i < elements.size(); ++i)
element_readers_.push_back(UploadElementReader::Create(elements[i]));
@@ -62,8 +62,26 @@ int UploadDataStream::InitSync() {
return OK;
}
-int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
+int UploadDataStream::Read(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
DCHECK(initialized_successfully_);
+ DCHECK(!callback.is_null());
+ DCHECK_GT(buf_len, 0);
+
+ // Process chunked data with ReadSync() since it requires special logic, and
+ // is always in memory.
+ if (is_chunked())
+ return ReadSync(buf, buf_len);
+
+ const bool invoked_asynchronously = false;
+ return ReadInternal(new DrainableIOBuffer(buf, buf_len),
+ invoked_asynchronously, callback, 0);
+}
+
+int UploadDataStream::ReadSync(IOBuffer* buf, int buf_len) {
+ DCHECK(initialized_successfully_);
+ DCHECK_GT(buf_len, 0);
// Initialize readers for newly appended chunks.
if (is_chunked()) {
@@ -71,6 +89,9 @@ int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
DCHECK_LE(element_readers_.size(), elements.size());
for (size_t i = element_readers_.size(); i < elements.size(); ++i) {
+ // We can initialize readers synchronously here because only bytes can be
+ // appended for chunked data. We leave |total_size_| at zero, since for
+ // chunked uploads, we may not know the total size.
const UploadElement& element = elements[i];
DCHECK_EQ(UploadElement::TYPE_BYTES, element.type());
UploadElementReader* reader = UploadElementReader::Create(element);
@@ -84,8 +105,10 @@ int UploadDataStream::Read(IOBuffer* buf, int buf_len) {
int bytes_copied = 0;
while (bytes_copied < buf_len && element_index_ < element_readers_.size()) {
UploadElementReader* reader = element_readers_[element_index_];
- bytes_copied += reader->ReadSync(buf->data() + bytes_copied,
- buf_len - bytes_copied);
+ scoped_refptr<DrainableIOBuffer> sub_buffer =
+ new DrainableIOBuffer(buf, buf_len);
+ sub_buffer->SetOffset(bytes_copied);
+ bytes_copied += reader->ReadSync(sub_buffer, sub_buffer->BytesRemaining());
if (reader->BytesRemaining() == 0)
++element_index_;
@@ -179,4 +202,48 @@ void UploadDataStream::FinalizeInitialization() {
initialized_successfully_ = true;
}
+int UploadDataStream::ReadInternal(scoped_refptr<DrainableIOBuffer> buf,
+ bool invoked_asynchronously,
+ const CompletionCallback& callback,
+ int previous_result) {
+ DCHECK(initialized_successfully_);
+ DCHECK_GE(previous_result, 0);
+
+ // Add the last result.
+ buf->DidConsume(previous_result);
+
+ while (element_index_ < element_readers_.size()) {
+ UploadElementReader* reader = element_readers_[element_index_];
+
+ if (reader->BytesRemaining() == 0) {
+ ++element_index_;
+ continue;
+ }
+
+ if (buf->BytesRemaining() == 0)
+ break;
+
+ const int result = reader->Read(
+ buf,
+ buf->BytesRemaining(),
+ base::Bind(base::IgnoreResult(&UploadDataStream::ReadInternal),
+ weak_ptr_factory_.GetWeakPtr(),
+ buf,
+ true, // invoked_asynchronously
+ callback));
+ if (result == ERR_IO_PENDING)
+ return ERR_IO_PENDING;
+ DCHECK_GE(result, 0);
+ buf->DidConsume(result);
+ }
+
+ const int bytes_copied = buf->BytesConsumed();
+ current_position_ += bytes_copied;
+
+ // When invoked asynchronously, callback is the only way to return the result.
+ if (invoked_asynchronously)
+ callback.Run(bytes_copied);
+ return bytes_copied;
+}
+
} // namespace net
« no previous file with comments | « net/base/upload_data_stream.h ('k') | net/base/upload_data_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698