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

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: 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/upload_file_element_reader.h ('k') | net/base/upload_file_element_reader_unittest.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_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/task_runner_util.h"
10 #include "base/threading/thread_restrictions.h" 11 #include "base/threading/thread_restrictions.h"
11 #include "base/threading/worker_pool.h" 12 #include "base/threading/worker_pool.h"
12 #include "net/base/file_stream.h" 13 #include "net/base/file_stream.h"
14 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
14 16
15 namespace net { 17 namespace net {
16 18
17 namespace { 19 namespace {
18 20
19 // In tests, this value is used to override the return value of 21 // In tests, this value is used to override the return value of
20 // UploadFileElementReader::GetContentLength() when set to non-zero. 22 // UploadFileElementReader::GetContentLength() when set to non-zero.
21 uint64 overriding_content_length = 0; 23 uint64 overriding_content_length = 0;
22 24
23 // This method is used to implement Init(). 25 // This function is used to implement Init().
24 void InitInternal(const FilePath& path, 26 int InitInternal(const FilePath& path,
25 uint64 range_offset, 27 uint64 range_offset,
26 uint64 range_length, 28 uint64 range_length,
27 const base::Time& expected_modification_time, 29 const base::Time& expected_modification_time,
28 scoped_ptr<FileStream>* out_file_stream, 30 scoped_ptr<FileStream>* out_file_stream,
29 uint64* out_content_length, 31 uint64* out_content_length) {
30 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);
34 if (rv != OK) { 35 if (rv != OK) {
35 // If the file can't be opened, we'll just upload an empty file. 36 // If the file can't be opened, we'll just upload an empty file.
36 DLOG(WARNING) << "Failed to open \"" << path.value() 37 DLOG(WARNING) << "Failed to open \"" << path.value()
37 << "\" for reading: " << rv; 38 << "\" for reading: " << rv;
38 file_stream.reset(); 39 file_stream.reset();
39 } else if (range_offset) { 40 } else if (range_offset) {
40 rv = file_stream->SeekSync(FROM_BEGIN, range_offset); 41 rv = file_stream->SeekSync(FROM_BEGIN, range_offset);
(...skipping 16 matching lines...) Expand all
57 out_file_stream->swap(file_stream); 58 out_file_stream->swap(file_stream);
58 59
59 // If the underlying file has been changed and the expected file modification 60 // If the underlying file has been changed and the expected file modification
60 // time is set, treat it as error. Note that the expected modification time 61 // time is set, treat it as error. Note that the expected modification time
61 // from WebKit is based on time_t precision. So we have to convert both to 62 // from WebKit is based on time_t precision. So we have to convert both to
62 // time_t to compare. This check is used for sliced files. 63 // time_t to compare. This check is used for sliced files.
63 if (!expected_modification_time.is_null()) { 64 if (!expected_modification_time.is_null()) {
64 base::PlatformFileInfo info; 65 base::PlatformFileInfo info;
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 return ERR_UPLOAD_FILE_CHANGED;
68 return;
69 } 69 }
70 } 70 }
71 71
72 *out_result = OK; 72 return OK;
73 }
74
75 // This function is used to implement Read().
76 int ReadInternal(scoped_refptr<IOBuffer> buf,
77 int buf_length,
78 uint64 bytes_remaining,
79 FileStream* file_stream) {
80 DCHECK_LT(0, buf_length);
81
82 const uint64 num_bytes_to_read =
83 std::min(bytes_remaining, static_cast<uint64>(buf_length));
84
85 if (num_bytes_to_read > 0) {
86 int num_bytes_consumed = 0;
87 // file_stream is NULL if the target file is missing or not readable.
88 if (file_stream) {
89 num_bytes_consumed = file_stream->ReadSync(buf->data(),
90 num_bytes_to_read);
91 }
92 if (num_bytes_consumed <= 0) {
93 // If there's less data to read than we initially observed, then
94 // pad with zero. Otherwise the server will hang waiting for the
95 // rest of the data.
96 memset(buf->data(), 0, num_bytes_to_read);
97 }
98 }
99 return num_bytes_to_read;
73 } 100 }
74 101
75 } // namespace 102 } // namespace
76 103
77 UploadFileElementReader::UploadFileElementReader( 104 UploadFileElementReader::UploadFileElementReader(
78 const FilePath& path, 105 const FilePath& path,
79 uint64 range_offset, 106 uint64 range_offset,
80 uint64 range_length, 107 uint64 range_length,
81 const base::Time& expected_modification_time) 108 const base::Time& expected_modification_time)
82 : path_(path), 109 : path_(path),
(...skipping 10 matching lines...) Expand all
93 base::WorkerPool::PostTask(FROM_HERE, 120 base::WorkerPool::PostTask(FROM_HERE,
94 base::Bind(&base::DeletePointer<FileStream>, 121 base::Bind(&base::DeletePointer<FileStream>,
95 file_stream_.release()), 122 file_stream_.release()),
96 true /* task_is_slow */); 123 true /* task_is_slow */);
97 } 124 }
98 } 125 }
99 126
100 int UploadFileElementReader::Init(const CompletionCallback& callback) { 127 int UploadFileElementReader::Init(const CompletionCallback& callback) {
101 scoped_ptr<FileStream>* file_stream = new scoped_ptr<FileStream>; 128 scoped_ptr<FileStream>* file_stream = new scoped_ptr<FileStream>;
102 uint64* content_length = new uint64; 129 uint64* content_length = new uint64;
103 int* result = new int; 130 const bool posted = base::PostTaskAndReplyWithResult(
104 const bool posted = base::WorkerPool::PostTaskAndReply( 131 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
105 FROM_HERE, 132 FROM_HERE,
106 base::Bind(&InitInternal, 133 base::Bind(&InitInternal,
107 path_, 134 path_,
108 range_offset_, 135 range_offset_,
109 range_length_, 136 range_length_,
110 expected_modification_time_, 137 expected_modification_time_,
111 file_stream, 138 file_stream,
112 content_length, 139 content_length),
113 result),
114 base::Bind(&UploadFileElementReader::OnInitCompleted, 140 base::Bind(&UploadFileElementReader::OnInitCompleted,
115 weak_ptr_factory_.GetWeakPtr(), 141 weak_ptr_factory_.GetWeakPtr(),
116 base::Owned(file_stream), 142 base::Owned(file_stream),
117 base::Owned(content_length), 143 base::Owned(content_length),
118 base::Owned(result), 144 callback));
119 callback),
120 true /* task_is_slow */);
121 DCHECK(posted); 145 DCHECK(posted);
122 return ERR_IO_PENDING; 146 return ERR_IO_PENDING;
123 } 147 }
124 148
125 int UploadFileElementReader::InitSync() { 149 int UploadFileElementReader::InitSync() {
126 // Temporarily allow until fix: http://crbug.com/72001. 150 // Temporarily allow until fix: http://crbug.com/72001.
127 base::ThreadRestrictions::ScopedAllowIO allow_io; 151 base::ThreadRestrictions::ScopedAllowIO allow_io;
128 152
129 scoped_ptr<FileStream> file_stream; 153 scoped_ptr<FileStream> file_stream;
130 uint64 content_length = 0; 154 uint64 content_length = 0;
131 int result = OK; 155 const int result = InitInternal(path_, range_offset_, range_length_,
132 InitInternal(path_, range_offset_, range_length_, expected_modification_time_, 156 expected_modification_time_,
133 &file_stream, &content_length, &result); 157 &file_stream, &content_length);
134 OnInitCompleted(&file_stream, &content_length, &result, CompletionCallback()); 158 OnInitCompleted(&file_stream, &content_length, CompletionCallback(), result);
135 return result; 159 return result;
136 } 160 }
137 161
138 uint64 UploadFileElementReader::GetContentLength() const { 162 uint64 UploadFileElementReader::GetContentLength() const {
139 if (overriding_content_length) 163 if (overriding_content_length)
140 return overriding_content_length; 164 return overriding_content_length;
141 return content_length_; 165 return content_length_;
142 } 166 }
143 167
144 uint64 UploadFileElementReader::BytesRemaining() const { 168 uint64 UploadFileElementReader::BytesRemaining() const {
145 return bytes_remaining_; 169 return bytes_remaining_;
146 } 170 }
147 171
148 int UploadFileElementReader::ReadSync(char* buf, int buf_length) { 172 int UploadFileElementReader::Read(IOBuffer* buf,
173 int buf_length,
174 const CompletionCallback& callback) {
175 DCHECK(!callback.is_null());
176
177 if (BytesRemaining() == 0)
178 return 0;
179
180 // Save the value of file_stream_.get() before base::Passed() invalidates it.
181 FileStream* file_stream_ptr = file_stream_.get();
182 // Pass the ownership of file_stream_ to the worker pool to safely perform
183 // operation even when |this| is destructed before the read completes.
184 const bool posted = base::PostTaskAndReplyWithResult(
185 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
186 FROM_HERE,
187 base::Bind(&ReadInternal,
188 scoped_refptr<IOBuffer>(buf),
189 buf_length,
190 BytesRemaining(),
191 file_stream_ptr),
192 base::Bind(&UploadFileElementReader::OnReadCompleted,
193 weak_ptr_factory_.GetWeakPtr(),
194 base::Passed(&file_stream_),
195 callback));
196 DCHECK(posted);
197 return ERR_IO_PENDING;
198 }
199
200 int UploadFileElementReader::ReadSync(IOBuffer* buf, int buf_length) {
149 // Temporarily allow until fix: http://crbug.com/72001. 201 // Temporarily allow until fix: http://crbug.com/72001.
150 base::ThreadRestrictions::ScopedAllowIO allow_io; 202 base::ThreadRestrictions::ScopedAllowIO allow_io;
151 DCHECK_LT(0, buf_length); 203 const int result = ReadInternal(buf, buf_length, BytesRemaining(),
152 204 file_stream_.get());
153 const uint64 num_bytes_to_read = 205 OnReadCompleted(file_stream_.Pass(), CompletionCallback(), result);
154 static_cast<int>(std::min(BytesRemaining(), 206 return result;
155 static_cast<uint64>(buf_length)));
156 if (num_bytes_to_read > 0) {
157 int num_bytes_consumed = 0;
158 // file_stream_ is NULL if the target file is
159 // missing or not readable.
160 if (file_stream_.get()) {
161 num_bytes_consumed =
162 file_stream_->ReadSync(buf, num_bytes_to_read);
163 }
164 if (num_bytes_consumed <= 0) {
165 // If there's less data to read than we initially observed, then
166 // pad with zero. Otherwise the server will hang waiting for the
167 // rest of the data.
168 memset(buf, 0, num_bytes_to_read);
169 }
170 }
171 DCHECK_GE(bytes_remaining_, num_bytes_to_read);
172 bytes_remaining_ -= num_bytes_to_read;
173 return num_bytes_to_read;
174 } 207 }
175 208
176 void UploadFileElementReader::OnInitCompleted( 209 void UploadFileElementReader::OnInitCompleted(
177 scoped_ptr<FileStream>* file_stream, 210 scoped_ptr<FileStream>* file_stream,
178 uint64* content_length, 211 uint64* content_length,
179 int* result, 212 const CompletionCallback& callback,
180 const CompletionCallback& callback) { 213 int result) {
181 file_stream_.swap(*file_stream); 214 file_stream_.swap(*file_stream);
182 content_length_ = *content_length; 215 content_length_ = *content_length;
183 bytes_remaining_ = GetContentLength(); 216 bytes_remaining_ = GetContentLength();
184 if (!callback.is_null()) 217 if (!callback.is_null())
185 callback.Run(*result); 218 callback.Run(result);
219 }
220
221 void UploadFileElementReader::OnReadCompleted(
222 scoped_ptr<FileStream> file_stream,
223 const CompletionCallback& callback,
224 int result) {
225 file_stream_.swap(file_stream);
226 DCHECK_GE(static_cast<int>(bytes_remaining_), result);
227 bytes_remaining_ -= result;
228 if (!callback.is_null())
229 callback.Run(result);
186 } 230 }
187 231
188 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 232 UploadFileElementReader::ScopedOverridingContentLengthForTests::
189 ScopedOverridingContentLengthForTests(uint64 value) { 233 ScopedOverridingContentLengthForTests(uint64 value) {
190 overriding_content_length = value; 234 overriding_content_length = value;
191 } 235 }
192 236
193 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 237 UploadFileElementReader::ScopedOverridingContentLengthForTests::
194 ~ScopedOverridingContentLengthForTests() { 238 ~ScopedOverridingContentLengthForTests() {
195 overriding_content_length = 0; 239 overriding_content_length = 0;
196 } 240 }
197 241
198 } // namespace net 242 } // namespace net
OLDNEW
« no previous file with comments | « net/base/upload_file_element_reader.h ('k') | net/base/upload_file_element_reader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698