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

Side by Side Diff: net/base/upload_data.cc

Issue 9321003: net: Make UploadData::GetContentLength() asynchronous. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « net/base/upload_data.h ('k') | net/base/upload_data_stream.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 5 #include "net/base/upload_data.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h"
9 #include "base/file_util.h" 10 #include "base/file_util.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "base/threading/worker_pool.h"
15 #include "base/tracked_objects.h"
13 #include "net/base/file_stream.h" 16 #include "net/base/file_stream.h"
14 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
15 18
16 namespace net { 19 namespace net {
17 20
21 namespace {
22
23 // Helper function for GetContentLength().
24 void OnGetContentLengthComplete(
25 const UploadData::ContentLengthCallback& callback,
26 uint64* content_length) {
27 callback.Run(*content_length);
28 }
29
30 } // namespace
31
18 UploadData::Element::Element() 32 UploadData::Element::Element()
19 : type_(TYPE_BYTES), 33 : type_(TYPE_BYTES),
20 file_range_offset_(0), 34 file_range_offset_(0),
21 file_range_length_(kuint64max), 35 file_range_length_(kuint64max),
22 is_last_chunk_(false), 36 is_last_chunk_(false),
23 override_content_length_(false), 37 override_content_length_(false),
24 content_length_computed_(false), 38 content_length_computed_(false),
25 content_length_(-1), 39 content_length_(-1),
26 file_stream_(NULL) { 40 file_stream_(NULL) {
27 } 41 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 content_length_ = 0; 75 content_length_ = 0;
62 76
63 // We need to open the file here to decide if we should report the file's 77 // We need to open the file here to decide if we should report the file's
64 // size or zero. We cache the open file, so that we can still read it when 78 // size or zero. We cache the open file, so that we can still read it when
65 // it comes time to. 79 // it comes time to.
66 file_stream_ = NewFileStreamForReading(); 80 file_stream_ = NewFileStreamForReading();
67 if (!file_stream_) 81 if (!file_stream_)
68 return 0; 82 return 0;
69 83
70 int64 length = 0; 84 int64 length = 0;
71 85 if (!file_util::GetFileSize(file_path_, &length))
72 {
73 // TODO(tzik):
74 // file_util::GetFileSize may cause blocking IO.
75 // Temporary allow until fix: http://crbug.com/72001.
76 base::ThreadRestrictions::ScopedAllowIO allow_io;
77 if (!file_util::GetFileSize(file_path_, &length))
78 return 0; 86 return 0;
79 }
80 87
81 if (file_range_offset_ >= static_cast<uint64>(length)) 88 if (file_range_offset_ >= static_cast<uint64>(length))
82 return 0; // range is beyond eof 89 return 0; // range is beyond eof
83 90
84 // compensate for the offset and clip file_range_length_ to eof 91 // compensate for the offset and clip file_range_length_ to eof
85 content_length_ = std::min(length - file_range_offset_, file_range_length_); 92 content_length_ = std::min(length - file_range_offset_, file_range_length_);
86 return content_length_; 93 return content_length_;
87 } 94 }
88 95
89 FileStream* UploadData::Element::NewFileStreamForReading() { 96 FileStream* UploadData::Element::NewFileStreamForReading() {
90 // In common usage GetContentLength() will call this first and store the 97 // In common usage GetContentLength() will call this first and store the
91 // result into |file_| and a subsequent call (from UploadDataStream) will 98 // result into |file_| and a subsequent call (from UploadDataStream) will
92 // get the cached open FileStream. 99 // get the cached open FileStream.
93 if (file_stream_) { 100 if (file_stream_) {
94 FileStream* file = file_stream_; 101 FileStream* file = file_stream_;
95 file_stream_ = NULL; 102 file_stream_ = NULL;
96 return file; 103 return file;
97 } 104 }
98 105
99 // TODO(tzik):
100 // FileStream::Open and FileStream::Seek may cause blocking IO.
101 // Temporary allow until fix: http://crbug.com/72001.
102 base::ThreadRestrictions::ScopedAllowIO allow_io;
103
104 scoped_ptr<FileStream> file(new FileStream(NULL)); 106 scoped_ptr<FileStream> file(new FileStream(NULL));
105 int64 rv = file->Open(file_path_, 107 int64 rv = file->Open(file_path_,
106 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 108 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
107 if (rv != OK) { 109 if (rv != OK) {
108 // If the file can't be opened, we'll just upload an empty file. 110 // If the file can't be opened, we'll just upload an empty file.
109 DLOG(WARNING) << "Failed to open \"" << file_path_.value() 111 DLOG(WARNING) << "Failed to open \"" << file_path_.value()
110 << "\" for reading: " << rv; 112 << "\" for reading: " << rv;
111 return NULL; 113 return NULL;
112 } 114 }
113 if (file_range_offset_) { 115 if (file_range_offset_) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 elements_.push_back(Element()); 161 elements_.push_back(Element());
160 elements_.back().SetToChunk(bytes, bytes_len, is_last_chunk); 162 elements_.back().SetToChunk(bytes, bytes_len, is_last_chunk);
161 if (chunk_callback_) 163 if (chunk_callback_)
162 chunk_callback_->OnChunkAvailable(); 164 chunk_callback_->OnChunkAvailable();
163 } 165 }
164 166
165 void UploadData::set_chunk_callback(ChunkCallback* callback) { 167 void UploadData::set_chunk_callback(ChunkCallback* callback) {
166 chunk_callback_ = callback; 168 chunk_callback_ = callback;
167 } 169 }
168 170
169 uint64 UploadData::GetContentLength() { 171 void UploadData::GetContentLength(const ContentLengthCallback& callback) {
170 if (is_chunked_) 172 uint64* result = new uint64(0);
171 return 0; 173 const bool task_is_slow = true;
174 const bool posted = base::WorkerPool::PostTaskAndReply(
175 FROM_HERE,
176 base::Bind(&UploadData::DoGetContentLength, this, result),
willchan no longer on Chromium 2012/02/08 20:44:03 I have to think about this more, but I thought I'd
satorux1 2012/02/08 21:02:19 Thank you for sharing the thought. I think one wa
177 base::Bind(&OnGetContentLengthComplete, callback, base::Owned(result)),
178 task_is_slow);
179 DCHECK(posted);
180 }
172 181
173 uint64 len = 0; 182 uint64 UploadData::GetContentLengthSyncHack() {
174 std::vector<Element>::iterator it = elements_.begin(); 183 // Temporarily allow until fix: http://crbug.com/72001.
175 for (; it != elements_.end(); ++it) 184 base::ThreadRestrictions::ScopedAllowIO allow_io;
176 len += (*it).GetContentLength(); 185 uint64 content_length = 0;
177 return len; 186 DoGetContentLength(&content_length);
187 return content_length;
188 }
189
190 uint64 UploadData::GetContentLengthSync() {
191 uint64 content_length = 0;
192 DoGetContentLength(&content_length);
193 return content_length;
178 } 194 }
179 195
180 bool UploadData::IsInMemory() const { 196 bool UploadData::IsInMemory() const {
181 // Chunks are in memory, but UploadData does not have all the chunks at 197 // Chunks are in memory, but UploadData does not have all the chunks at
182 // once. Chunks are provided progressively with AppendChunk() as chunks 198 // once. Chunks are provided progressively with AppendChunk() as chunks
183 // are ready. Check is_chunked_ here, rather than relying on the loop 199 // are ready. Check is_chunked_ here, rather than relying on the loop
184 // below, as there is a case that is_chunked_ is set to true, but the 200 // below, as there is a case that is_chunked_ is set to true, but the
185 // first chunk is not yet delivered. 201 // first chunk is not yet delivered.
186 if (is_chunked_) 202 if (is_chunked_)
187 return false; 203 return false;
188 204
189 for (size_t i = 0; i < elements_.size(); ++i) { 205 for (size_t i = 0; i < elements_.size(); ++i) {
190 if (elements_[i].type() != TYPE_BYTES) 206 if (elements_[i].type() != TYPE_BYTES)
191 return false; 207 return false;
192 } 208 }
193 return true; 209 return true;
194 } 210 }
195 211
196 void UploadData::SetElements(const std::vector<Element>& elements) { 212 void UploadData::SetElements(const std::vector<Element>& elements) {
197 elements_ = elements; 213 elements_ = elements;
198 } 214 }
199 215
216 void UploadData::DoGetContentLength(uint64* content_length) {
217 *content_length = 0;
218
219 if (is_chunked_)
220 return;
221
222 for (size_t i = 0; i < elements_.size(); ++i)
223 *content_length += elements_[i].GetContentLength();
224 }
225
200 UploadData::~UploadData() { 226 UploadData::~UploadData() {
201 } 227 }
202 228
203 } // namespace net 229 } // namespace net
OLDNEW
« no previous file with comments | « net/base/upload_data.h ('k') | net/base/upload_data_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698