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

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

Issue 10910268: net: Make UploadDataStream::Read() asynchronous (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: _ Created 8 years, 3 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
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_file_element_reader.h" 5 #include "net/base/upload_file_element_reader.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
11 #include "base/threading/worker_pool.h" 11 #include "base/threading/worker_pool.h"
12 #include "net/base/file_stream.h" 12 #include "net/base/file_stream.h"
13 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
14 15
15 namespace net { 16 namespace net {
16 17
17 namespace { 18 namespace {
18 19
19 // In tests, this value is used to override the return value of 20 // In tests, this value is used to override the return value of
20 // UploadFileElementReader::GetContentLength() when set to non-zero. 21 // UploadFileElementReader::GetContentLength() when set to non-zero.
21 uint64 overriding_content_length = 0; 22 uint64 overriding_content_length = 0;
22 23
23 // This method is used to implement Init(). 24 // This function is used to implement Init().
24 void InitInternal(const FilePath& path, 25 void InitInternal(const FilePath& path,
25 uint64 range_offset, 26 uint64 range_offset,
26 uint64 range_length, 27 uint64 range_length,
27 const base::Time& expected_modification_time, 28 const base::Time& expected_modification_time,
28 scoped_ptr<FileStream>* out_file_stream, 29 scoped_ptr<FileStream>* out_file_stream,
29 uint64* out_content_length, 30 uint64* out_content_length,
30 int* out_result) { 31 int* out_result) {
31 scoped_ptr<FileStream> file_stream(new FileStream(NULL)); 32 scoped_ptr<FileStream> file_stream(new FileStream(NULL));
32 int64 rv = file_stream->OpenSync( 33 int64 rv = file_stream->OpenSync(
33 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 34 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 if (file_util::GetFileInfo(path, &info) && 66 if (file_util::GetFileInfo(path, &info) &&
66 expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) { 67 expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
67 *out_result = ERR_UPLOAD_FILE_CHANGED; 68 *out_result = ERR_UPLOAD_FILE_CHANGED;
68 return; 69 return;
69 } 70 }
70 } 71 }
71 72
72 *out_result = OK; 73 *out_result = OK;
73 } 74 }
74 75
76 // This function is used to implement Read().
77 void ReadInternal(scoped_refptr<IOBuffer> buf,
78 int buf_length,
79 uint64 bytes_remaining,
80 FileStream* file_stream,
81 int* result) {
82 DCHECK_LT(0, buf_length);
83
84 const uint64 num_bytes_to_read =
85 std::min(bytes_remaining, static_cast<uint64>(buf_length));
86
87 if (num_bytes_to_read > 0) {
88 int num_bytes_consumed = 0;
89 // file_stream is NULL if the target file is
90 // missing or not readable.
91 if (file_stream) {
92 num_bytes_consumed = file_stream->ReadSync(buf->data(),
93 num_bytes_to_read);
94 }
95 if (num_bytes_consumed <= 0) {
96 // If there's less data to read than we initially observed, then
97 // pad with zero. Otherwise the server will hang waiting for the
98 // rest of the data.
99 memset(buf->data(), 0, num_bytes_to_read);
100 }
101 }
102 *result = num_bytes_to_read;
103 }
104
75 } // namespace 105 } // namespace
76 106
77 UploadFileElementReader::UploadFileElementReader( 107 UploadFileElementReader::UploadFileElementReader(
78 const FilePath& path, 108 const FilePath& path,
79 uint64 range_offset, 109 uint64 range_offset,
80 uint64 range_length, 110 uint64 range_length,
81 const base::Time& expected_modification_time) 111 const base::Time& expected_modification_time)
82 : path_(path), 112 : path_(path),
83 range_offset_(range_offset), 113 range_offset_(range_offset),
84 range_length_(range_length), 114 range_length_(range_length),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 uint64 UploadFileElementReader::GetContentLength() const { 166 uint64 UploadFileElementReader::GetContentLength() const {
137 if (overriding_content_length) 167 if (overriding_content_length)
138 return overriding_content_length; 168 return overriding_content_length;
139 return content_length_; 169 return content_length_;
140 } 170 }
141 171
142 uint64 UploadFileElementReader::BytesRemaining() const { 172 uint64 UploadFileElementReader::BytesRemaining() const {
143 return bytes_remaining_; 173 return bytes_remaining_;
144 } 174 }
145 175
146 int UploadFileElementReader::ReadSync(char* buf, int buf_length) { 176 int UploadFileElementReader::Read(IOBuffer* buf,
177 int buf_length,
178 const CompletionCallback& callback) {
179 if (BytesRemaining() <= 0)
willchan no longer on Chromium 2012/09/24 23:37:08 Why <= 0? It returns a uint64.
hashimoto 2012/09/25 10:47:56 Replaced with '=='.
180 return 0;
181
182 // Save the value of file_stream_.get() before base::Passed() invalidats it.
willchan no longer on Chromium 2012/09/24 23:37:08 invalidates Also, why does this make sense? file_
hashimoto 2012/09/25 10:47:56 We must save the value here because the C++ standa
183 FileStream* file_stream_ptr = file_stream_.get();
184 int* result = new int;
185 // Pass the ownership of file_stream_ to the worker pool to safely perform
186 // operation even when |this| is destructed before the read completes.
187 const bool posted = base::WorkerPool::PostTaskAndReply(
188 FROM_HERE,
189 base::Bind(&ReadInternal,
190 scoped_refptr<IOBuffer>(buf),
191 buf_length,
192 BytesRemaining(),
193 file_stream_ptr,
194 result),
195 base::Bind(&UploadFileElementReader::OnReadCompleted,
196 weak_ptr_factory_.GetWeakPtr(),
197 base::Passed(&file_stream_),
198 base::Owned(result),
199 callback),
200 true /* task_is_slow */);
201 DCHECK(posted);
202 return ERR_IO_PENDING;
203 }
204
205 int UploadFileElementReader::ReadSync(IOBuffer* buf, int buf_length) {
147 // Temporarily allow until fix: http://crbug.com/72001. 206 // Temporarily allow until fix: http://crbug.com/72001.
148 base::ThreadRestrictions::ScopedAllowIO allow_io; 207 base::ThreadRestrictions::ScopedAllowIO allow_io;
149 DCHECK_LT(0, buf_length); 208 int result = 0;
150 209 ReadInternal(buf, buf_length, BytesRemaining(), file_stream_.get(), &result);
151 const uint64 num_bytes_to_read = 210 OnReadCompleted(file_stream_.Pass(), &result, CompletionCallback());
152 static_cast<int>(std::min(BytesRemaining(), 211 return result;
153 static_cast<uint64>(buf_length)));
154 if (num_bytes_to_read > 0) {
155 int num_bytes_consumed = 0;
156 // file_stream_ is NULL if the target file is
157 // missing or not readable.
158 if (file_stream_.get()) {
159 num_bytes_consumed =
160 file_stream_->ReadSync(buf, num_bytes_to_read);
161 }
162 if (num_bytes_consumed <= 0) {
163 // If there's less data to read than we initially observed, then
164 // pad with zero. Otherwise the server will hang waiting for the
165 // rest of the data.
166 memset(buf, 0, num_bytes_to_read);
167 }
168 }
169 DCHECK_GE(bytes_remaining_, num_bytes_to_read);
170 bytes_remaining_ -= num_bytes_to_read;
171 return num_bytes_to_read;
172 } 212 }
173 213
174 void UploadFileElementReader::OnInitCompleted( 214 void UploadFileElementReader::OnInitCompleted(
175 scoped_ptr<FileStream>* file_stream, 215 scoped_ptr<FileStream>* file_stream,
176 uint64* content_length, 216 uint64* content_length,
177 int* result, 217 int* result,
178 const CompletionCallback& callback) { 218 const CompletionCallback& callback) {
179 file_stream_.swap(*file_stream); 219 file_stream_.swap(*file_stream);
180 content_length_ = *content_length; 220 content_length_ = *content_length;
181 bytes_remaining_ = GetContentLength(); 221 bytes_remaining_ = GetContentLength();
182 if (!callback.is_null()) 222 if (!callback.is_null())
183 callback.Run(*result); 223 callback.Run(*result);
184 } 224 }
185 225
226 void UploadFileElementReader::OnReadCompleted(
227 scoped_ptr<FileStream> file_stream,
228 int* result,
229 const CompletionCallback& callback) {
230 file_stream_.swap(file_stream);
231 DCHECK_GE(static_cast<int>(bytes_remaining_), *result);
232 bytes_remaining_ -= *result;
233 if (!callback.is_null())
234 callback.Run(*result);
235 }
236
186 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 237 UploadFileElementReader::ScopedOverridingContentLengthForTests::
187 ScopedOverridingContentLengthForTests(uint64 value) { 238 ScopedOverridingContentLengthForTests(uint64 value) {
188 overriding_content_length = value; 239 overriding_content_length = value;
189 } 240 }
190 241
191 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 242 UploadFileElementReader::ScopedOverridingContentLengthForTests::
192 ~ScopedOverridingContentLengthForTests() { 243 ~ScopedOverridingContentLengthForTests() {
193 overriding_content_length = 0; 244 overriding_content_length = 0;
194 } 245 }
195 246
196 } // namespace net 247 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698