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

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

Issue 141843002: Revert 245509 "net: Use FileStream asynchronously from UploadFil..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 11 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 | « trunk/src/net/base/upload_file_element_reader.h ('k') | no next file » | 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/task_runner_util.h"
11 #include "net/base/file_stream.h" 11 #include "net/base/file_stream.h"
12 #include "net/base/io_buffer.h" 12 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h" 13 #include "net/base/net_errors.h"
14 14
15 namespace net { 15 namespace net {
16 16
17 namespace { 17 namespace {
18 18
19 // In tests, this value is used to override the return value of 19 // In tests, this value is used to override the return value of
20 // UploadFileElementReader::GetContentLength() when set to non-zero. 20 // UploadFileElementReader::GetContentLength() when set to non-zero.
21 uint64 overriding_content_length = 0; 21 uint64 overriding_content_length = 0;
22 22
23 // This function is used to implement Init().
24 template<typename FileStreamDeleter>
25 int InitInternal(const base::FilePath& path,
26 uint64 range_offset,
27 uint64 range_length,
28 const base::Time& expected_modification_time,
29 scoped_ptr<FileStream, FileStreamDeleter>* out_file_stream,
30 uint64* out_content_length) {
31 scoped_ptr<FileStream> file_stream(new FileStream(NULL));
32 int64 rv = file_stream->OpenSync(
33 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
34 if (rv != OK) {
35 // If the file can't be opened, the upload should fail.
36 DLOG(WARNING) << "Failed to open \"" << path.value()
37 << "\" for reading: " << rv;
38 return rv;
39 } else if (range_offset) {
40 rv = file_stream->SeekSync(FROM_BEGIN, range_offset);
41 if (rv < 0) {
42 DLOG(WARNING) << "Failed to seek \"" << path.value()
43 << "\" to offset: " << range_offset << " (" << rv << ")";
44 return rv;
45 }
46 }
47
48 int64 length = 0;
49 if (!base::GetFileSize(path, &length)) {
50 DLOG(WARNING) << "Failed to get file size of \"" << path.value() << "\"";
51 return ERR_FILE_NOT_FOUND;
52 }
53
54 if (range_offset < static_cast<uint64>(length)) {
55 // Compensate for the offset.
56 length = std::min(length - range_offset, range_length);
57 }
58
59 // 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 // 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 if (!expected_modification_time.is_null()) {
64 base::File::Info info;
65 if (!base::GetFileInfo(path, &info)) {
66 DLOG(WARNING) << "Failed to get file info of \"" << path.value() << "\"";
67 return ERR_FILE_NOT_FOUND;
68 }
69
70 if (expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
71 return ERR_UPLOAD_FILE_CHANGED;
72 }
73 }
74
75 *out_content_length = length;
76 out_file_stream->reset(file_stream.release());
77
78 return OK;
79 }
80
81 // This function is used to implement Read().
82 int ReadInternal(scoped_refptr<IOBuffer> buf,
83 int buf_length,
84 uint64 bytes_remaining,
85 FileStream* file_stream) {
86 DCHECK_LT(0, buf_length);
87
88 const uint64 num_bytes_to_read =
89 std::min(bytes_remaining, static_cast<uint64>(buf_length));
90
91 int result = 0;
92 if (num_bytes_to_read > 0) {
93 DCHECK(file_stream); // file_stream is non-null if content_length_ > 0.
94 result = file_stream->ReadSync(buf->data(), num_bytes_to_read);
95 if (result == 0) // Reached end-of-file earlier than expected.
96 result = ERR_UPLOAD_FILE_CHANGED;
97 }
98 return result;
99 }
100
23 } // namespace 101 } // namespace
24 102
103 UploadFileElementReader::FileStreamDeleter::FileStreamDeleter(
104 base::TaskRunner* task_runner) : task_runner_(task_runner) {
105 DCHECK(task_runner_.get());
106 }
107
108 UploadFileElementReader::FileStreamDeleter::~FileStreamDeleter() {}
109
110 void UploadFileElementReader::FileStreamDeleter::operator() (
111 FileStream* file_stream) const {
112 if (file_stream) {
113 task_runner_->PostTask(FROM_HERE,
114 base::Bind(&base::DeletePointer<FileStream>,
115 file_stream));
116 }
117 }
118
25 UploadFileElementReader::UploadFileElementReader( 119 UploadFileElementReader::UploadFileElementReader(
26 base::TaskRunner* task_runner, 120 base::TaskRunner* task_runner,
27 const base::FilePath& path, 121 const base::FilePath& path,
28 uint64 range_offset, 122 uint64 range_offset,
29 uint64 range_length, 123 uint64 range_length,
30 const base::Time& expected_modification_time) 124 const base::Time& expected_modification_time)
31 : task_runner_(task_runner), 125 : task_runner_(task_runner),
32 path_(path), 126 path_(path),
33 range_offset_(range_offset), 127 range_offset_(range_offset),
34 range_length_(range_length), 128 range_length_(range_length),
35 expected_modification_time_(expected_modification_time), 129 expected_modification_time_(expected_modification_time),
130 file_stream_(NULL, FileStreamDeleter(task_runner_.get())),
36 content_length_(0), 131 content_length_(0),
37 bytes_remaining_(0), 132 bytes_remaining_(0),
38 weak_ptr_factory_(this) { 133 weak_ptr_factory_(this) {
39 DCHECK(task_runner_.get()); 134 DCHECK(task_runner_.get());
40 } 135 }
41 136
42 UploadFileElementReader::~UploadFileElementReader() { 137 UploadFileElementReader::~UploadFileElementReader() {
43 } 138 }
44 139
45 const UploadFileElementReader* UploadFileElementReader::AsFileReader() const { 140 const UploadFileElementReader* UploadFileElementReader::AsFileReader() const {
46 return this; 141 return this;
47 } 142 }
48 143
49 int UploadFileElementReader::Init(const CompletionCallback& callback) { 144 int UploadFileElementReader::Init(const CompletionCallback& callback) {
50 DCHECK(!callback.is_null()); 145 DCHECK(!callback.is_null());
51 Reset(); 146 Reset();
52 147
53 file_stream_.reset(new FileStream(NULL, task_runner_.get())); 148 ScopedFileStreamPtr* file_stream =
54 int result = file_stream_->Open( 149 new ScopedFileStreamPtr(NULL, FileStreamDeleter(task_runner_.get()));
55 path_, 150 uint64* content_length = new uint64;
56 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 151 const bool posted = base::PostTaskAndReplyWithResult(
57 base::PLATFORM_FILE_ASYNC, 152 task_runner_.get(),
58 base::Bind(&UploadFileElementReader::OnOpenCompleted, 153 FROM_HERE,
154 base::Bind(&InitInternal<FileStreamDeleter>,
155 path_,
156 range_offset_,
157 range_length_,
158 expected_modification_time_,
159 file_stream,
160 content_length),
161 base::Bind(&UploadFileElementReader::OnInitCompleted,
59 weak_ptr_factory_.GetWeakPtr(), 162 weak_ptr_factory_.GetWeakPtr(),
163 base::Owned(file_stream),
164 base::Owned(content_length),
60 callback)); 165 callback));
61 DCHECK_GT(0, result); 166 DCHECK(posted);
62 return result; 167 return ERR_IO_PENDING;
63 } 168 }
64 169
65 uint64 UploadFileElementReader::GetContentLength() const { 170 uint64 UploadFileElementReader::GetContentLength() const {
66 if (overriding_content_length) 171 if (overriding_content_length)
67 return overriding_content_length; 172 return overriding_content_length;
68 return content_length_; 173 return content_length_;
69 } 174 }
70 175
71 uint64 UploadFileElementReader::BytesRemaining() const { 176 uint64 UploadFileElementReader::BytesRemaining() const {
72 return bytes_remaining_; 177 return bytes_remaining_;
73 } 178 }
74 179
75 int UploadFileElementReader::Read(IOBuffer* buf, 180 int UploadFileElementReader::Read(IOBuffer* buf,
76 int buf_length, 181 int buf_length,
77 const CompletionCallback& callback) { 182 const CompletionCallback& callback) {
78 DCHECK(!callback.is_null()); 183 DCHECK(!callback.is_null());
79 184
80 uint64 num_bytes_to_read = 185 if (BytesRemaining() == 0)
81 std::min(BytesRemaining(), static_cast<uint64>(buf_length));
82 if (num_bytes_to_read == 0)
83 return 0; 186 return 0;
84 187
85 int result = file_stream_->Read( 188 // Save the value of file_stream_.get() before base::Passed() invalidates it.
86 buf, num_bytes_to_read, 189 FileStream* file_stream_ptr = file_stream_.get();
190 // Pass the ownership of file_stream_ to the worker pool to safely perform
191 // operation even when |this| is destructed before the read completes.
192 const bool posted = base::PostTaskAndReplyWithResult(
193 task_runner_.get(),
194 FROM_HERE,
195 base::Bind(&ReadInternal,
196 scoped_refptr<IOBuffer>(buf),
197 buf_length,
198 BytesRemaining(),
199 file_stream_ptr),
87 base::Bind(&UploadFileElementReader::OnReadCompleted, 200 base::Bind(&UploadFileElementReader::OnReadCompleted,
88 weak_ptr_factory_.GetWeakPtr(), 201 weak_ptr_factory_.GetWeakPtr(),
202 base::Passed(&file_stream_),
89 callback)); 203 callback));
90 DCHECK_GT(0, result); 204 DCHECK(posted);
91 return result; 205 return ERR_IO_PENDING;
92 } 206 }
93 207
94 void UploadFileElementReader::Reset() { 208 void UploadFileElementReader::Reset() {
95 weak_ptr_factory_.InvalidateWeakPtrs(); 209 weak_ptr_factory_.InvalidateWeakPtrs();
96 bytes_remaining_ = 0; 210 bytes_remaining_ = 0;
97 content_length_ = 0; 211 content_length_ = 0;
98 file_stream_.reset(); 212 file_stream_.reset();
99 } 213 }
100 214
101 void UploadFileElementReader::OnOpenCompleted( 215 void UploadFileElementReader::OnInitCompleted(
216 ScopedFileStreamPtr* file_stream,
217 uint64* content_length,
102 const CompletionCallback& callback, 218 const CompletionCallback& callback,
103 int result) { 219 int result) {
104 DCHECK(!callback.is_null()); 220 file_stream_.swap(*file_stream);
105 221 content_length_ = *content_length;
106 if (result < 0) { 222 bytes_remaining_ = GetContentLength();
107 DLOG(WARNING) << "Failed to open \"" << path_.value() 223 if (!callback.is_null())
108 << "\" for reading: " << result;
109 callback.Run(result); 224 callback.Run(result);
110 return;
111 }
112
113 if (range_offset_) {
114 int result = file_stream_->Seek(
115 FROM_BEGIN, range_offset_,
116 base::Bind(&UploadFileElementReader::OnSeekCompleted,
117 weak_ptr_factory_.GetWeakPtr(),
118 callback));
119 DCHECK_GT(0, result);
120 if (result != ERR_IO_PENDING)
121 callback.Run(result);
122 } else {
123 OnSeekCompleted(callback, OK);
124 }
125 }
126
127 void UploadFileElementReader::OnSeekCompleted(
128 const CompletionCallback& callback,
129 int64 result) {
130 DCHECK(!callback.is_null());
131
132 if (result < 0) {
133 DLOG(WARNING) << "Failed to seek \"" << path_.value()
134 << "\" to offset: " << range_offset_ << " (" << result << ")";
135 callback.Run(result);
136 return;
137 }
138
139 base::File::Info* file_info = new base::File::Info;
140 bool posted = base::PostTaskAndReplyWithResult(
141 task_runner_,
142 FROM_HERE,
143 base::Bind(&base::GetFileInfo,
144 path_,
145 file_info),
146 base::Bind(&UploadFileElementReader::OnGetFileInfoCompleted,
147 weak_ptr_factory_.GetWeakPtr(),
148 callback,
149 base::Owned(file_info)));
150 DCHECK(posted);
151 }
152
153 void UploadFileElementReader::OnGetFileInfoCompleted(
154 const CompletionCallback& callback,
155 base::File::Info* file_info,
156 bool result) {
157 DCHECK(!callback.is_null());
158 if (!result) {
159 DLOG(WARNING) << "Failed to get file info of \"" << path_.value() << "\"";
160 callback.Run(ERR_FILE_NOT_FOUND);
161 return;
162 }
163
164 int64 length = file_info->size;
165 if (range_offset_ < static_cast<uint64>(length)) {
166 // Compensate for the offset.
167 length = std::min(length - range_offset_, range_length_);
168 }
169
170 // If the underlying file has been changed and the expected file modification
171 // time is set, treat it as error. Note that the expected modification time
172 // from WebKit is based on time_t precision. So we have to convert both to
173 // time_t to compare. This check is used for sliced files.
174 if (!expected_modification_time_.is_null() &&
175 expected_modification_time_.ToTimeT() !=
176 file_info->last_modified.ToTimeT()) {
177 callback.Run(ERR_UPLOAD_FILE_CHANGED);
178 return;
179 }
180
181 content_length_ = length;
182 bytes_remaining_ = GetContentLength();
183 callback.Run(OK);
184 } 225 }
185 226
186 void UploadFileElementReader::OnReadCompleted( 227 void UploadFileElementReader::OnReadCompleted(
228 ScopedFileStreamPtr file_stream,
187 const CompletionCallback& callback, 229 const CompletionCallback& callback,
188 int result) { 230 int result) {
189 DCHECK(!callback.is_null()); 231 file_stream_.swap(file_stream);
190
191 if (result == 0) // Reached end-of-file earlier than expected.
192 result = ERR_UPLOAD_FILE_CHANGED;
193
194 if (result > 0) { 232 if (result > 0) {
195 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result)); 233 DCHECK_GE(bytes_remaining_, static_cast<uint64>(result));
196 bytes_remaining_ -= result; 234 bytes_remaining_ -= result;
197 } 235 }
198 callback.Run(result); 236 if (!callback.is_null())
237 callback.Run(result);
199 } 238 }
200 239
201 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 240 UploadFileElementReader::ScopedOverridingContentLengthForTests::
202 ScopedOverridingContentLengthForTests(uint64 value) { 241 ScopedOverridingContentLengthForTests(uint64 value) {
203 overriding_content_length = value; 242 overriding_content_length = value;
204 } 243 }
205 244
206 UploadFileElementReader::ScopedOverridingContentLengthForTests:: 245 UploadFileElementReader::ScopedOverridingContentLengthForTests::
207 ~ScopedOverridingContentLengthForTests() { 246 ~ScopedOverridingContentLengthForTests() {
208 overriding_content_length = 0; 247 overriding_content_length = 0;
209 } 248 }
210 249
211 } // namespace net 250 } // namespace net
OLDNEW
« no previous file with comments | « trunk/src/net/base/upload_file_element_reader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698