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

Side by Side Diff: content/browser/download/download_file_impl.cc

Issue 2890853002: Downloads: replace BrowserThread::FILE with task scheduler. (Closed)
Patch Set: Address Avi's comments. Created 3 years, 5 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
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 "content/browser/download/download_file_impl.h" 5 #include "content/browser/download/download_file_impl.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/threading/sequenced_task_runner_handle.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 #include "content/browser/byte_stream.h" 17 #include "content/browser/byte_stream.h"
17 #include "content/browser/download/download_create_info.h" 18 #include "content/browser/download/download_create_info.h"
18 #include "content/browser/download/download_destination_observer.h" 19 #include "content/browser/download/download_destination_observer.h"
19 #include "content/browser/download/download_interrupt_reasons_impl.h" 20 #include "content/browser/download/download_interrupt_reasons_impl.h"
20 #include "content/browser/download/download_net_log_parameters.h" 21 #include "content/browser/download/download_net_log_parameters.h"
21 #include "content/browser/download/download_stats.h" 22 #include "content/browser/download/download_stats.h"
22 #include "content/browser/download/parallel_download_utils.h" 23 #include "content/browser/download/parallel_download_utils.h"
23 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 weak_factory_(this) { 114 weak_factory_(this) {
114 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>( 115 source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>(
115 save_info_->offset, save_info_->length, std::move(stream_reader)); 116 save_info_->offset, save_info_->length, std::move(stream_reader));
116 117
117 download_item_net_log.AddEvent( 118 download_item_net_log.AddEvent(
118 net::NetLogEventType::DOWNLOAD_FILE_CREATED, 119 net::NetLogEventType::DOWNLOAD_FILE_CREATED,
119 net_log_.source().ToEventParametersCallback()); 120 net_log_.source().ToEventParametersCallback());
120 net_log_.BeginEvent( 121 net_log_.BeginEvent(
121 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE, 122 net::NetLogEventType::DOWNLOAD_FILE_ACTIVE,
122 download_item_net_log.source().ToEventParametersCallback()); 123 download_item_net_log.source().ToEventParametersCallback());
124
125 DETACH_FROM_SEQUENCE(sequence_checker_);
123 } 126 }
124 127
125 DownloadFileImpl::~DownloadFileImpl() { 128 DownloadFileImpl::~DownloadFileImpl() {
126 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 129 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
130
127 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE); 131 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE);
128 } 132 }
129 133
130 void DownloadFileImpl::Initialize( 134 void DownloadFileImpl::Initialize(
131 const InitializeCallback& initialize_callback, 135 const InitializeCallback& initialize_callback,
132 const CancelRequestCallback& cancel_request_callback, 136 const CancelRequestCallback& cancel_request_callback,
133 const DownloadItem::ReceivedSlices& received_slices, 137 const DownloadItem::ReceivedSlices& received_slices,
134 bool is_parallelizable) { 138 bool is_parallelizable) {
135 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 139 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
136 140
137 update_timer_.reset(new base::RepeatingTimer()); 141 update_timer_.reset(new base::RepeatingTimer());
138 int64_t bytes_so_far = 0; 142 int64_t bytes_so_far = 0;
139 cancel_request_callback_ = cancel_request_callback; 143 cancel_request_callback_ = cancel_request_callback;
140 received_slices_ = received_slices; 144 received_slices_ = received_slices;
141 if (IsSparseFile()) { 145 if (IsSparseFile()) {
142 for (const auto& received_slice : received_slices_) { 146 for (const auto& received_slice : received_slices_) {
143 bytes_so_far += received_slice.received_bytes; 147 bytes_so_far += received_slice.received_bytes;
144 } 148 }
145 } else { 149 } else {
(...skipping 23 matching lines...) Expand all
169 173
170 // Initial pull from the straw from all source streams. 174 // Initial pull from the straw from all source streams.
171 for (auto& source_stream : source_streams_) 175 for (auto& source_stream : source_streams_)
172 RegisterAndActivateStream(source_stream.second.get()); 176 RegisterAndActivateStream(source_stream.second.get());
173 } 177 }
174 178
175 void DownloadFileImpl::AddByteStream( 179 void DownloadFileImpl::AddByteStream(
176 std::unique_ptr<ByteStreamReader> stream_reader, 180 std::unique_ptr<ByteStreamReader> stream_reader,
177 int64_t offset, 181 int64_t offset,
178 int64_t length) { 182 int64_t length) {
179 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 183 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
180 184
181 source_streams_[offset] = 185 source_streams_[offset] =
182 base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader)); 186 base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader));
183 187
184 // There are writers at different offsets now, create the received slices 188 // There are writers at different offsets now, create the received slices
185 // vector if necessary. 189 // vector if necessary.
186 if (received_slices_.empty() && TotalBytesReceived() > 0) { 190 if (received_slices_.empty() && TotalBytesReceived() > 0) {
187 size_t index = AddOrMergeReceivedSliceIntoSortedArray( 191 size_t index = AddOrMergeReceivedSliceIntoSortedArray(
188 DownloadItem::ReceivedSlice(0, TotalBytesReceived()), received_slices_); 192 DownloadItem::ReceivedSlice(0, TotalBytesReceived()), received_slices_);
189 DCHECK_EQ(index, 0u); 193 DCHECK_EQ(index, 0u);
190 } 194 }
191 // If the file is initialized, start to write data, or wait until file opened. 195 // If the file is initialized, start to write data, or wait until file opened.
192 if (file_.in_progress()) 196 if (file_.in_progress())
193 RegisterAndActivateStream(source_streams_[offset].get()); 197 RegisterAndActivateStream(source_streams_[offset].get());
194 } 198 }
195 199
196 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, 200 DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset,
197 const char* data, 201 const char* data,
198 size_t data_len) { 202 size_t data_len) {
199 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 203 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
204
200 WillWriteToDisk(data_len); 205 WillWriteToDisk(data_len);
201 return file_.WriteDataToFile(offset, data, data_len); 206 return file_.WriteDataToFile(offset, data, data_len);
202 } 207 }
203 208
204 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, 209 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream,
205 size_t bytes_available_to_write, 210 size_t bytes_available_to_write,
206 size_t* bytes_to_write) { 211 size_t* bytes_to_write) {
207 if (source_stream->length() == kNoBytesToWrite) { 212 if (source_stream->length() == kNoBytesToWrite) {
208 *bytes_to_write = 0; 213 *bytes_to_write = 0;
209 return true; 214 return true;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) * 272 return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) *
268 (1 << attempt_number); 273 (1 << attempt_number);
269 } 274 }
270 275
271 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { 276 bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) {
272 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; 277 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
273 } 278 }
274 279
275 void DownloadFileImpl::RenameWithRetryInternal( 280 void DownloadFileImpl::RenameWithRetryInternal(
276 std::unique_ptr<RenameParameters> parameters) { 281 std::unique_ptr<RenameParameters> parameters) {
277 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 282 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
278 283
279 base::FilePath new_path = parameters->new_path; 284 base::FilePath new_path = parameters->new_path;
280 285
281 if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) { 286 if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) {
282 int uniquifier = 287 int uniquifier =
283 base::GetUniquePathNumber(new_path, base::FilePath::StringType()); 288 base::GetUniquePathNumber(new_path, base::FilePath::StringType());
284 if (uniquifier > 0) 289 if (uniquifier > 0)
285 new_path = new_path.InsertBeforeExtensionASCII( 290 new_path = new_path.InsertBeforeExtensionASCII(
286 base::StringPrintf(" (%d)", uniquifier)); 291 base::StringPrintf(" (%d)", uniquifier));
287 } 292 }
288 293
289 DownloadInterruptReason reason = file_.Rename(new_path); 294 DownloadInterruptReason reason = file_.Rename(new_path);
290 295
291 // Attempt to retry the rename if possible. If the rename failed and the 296 // Attempt to retry the rename if possible. If the rename failed and the
292 // subsequent open also failed, then in_progress() would be false. We don't 297 // subsequent open also failed, then in_progress() would be false. We don't
293 // try to retry renames if the in_progress() was false to begin with since we 298 // try to retry renames if the in_progress() was false to begin with since we
294 // have less assurance that the file at file_.full_path() was the one we were 299 // have less assurance that the file at file_.full_path() was the one we were
295 // working with. 300 // working with.
296 if (ShouldRetryFailedRename(reason) && file_.in_progress() && 301 if (ShouldRetryFailedRename(reason) && file_.in_progress() &&
297 parameters->retries_left > 0) { 302 parameters->retries_left > 0) {
298 int attempt_number = kMaxRenameRetries - parameters->retries_left; 303 int attempt_number = kMaxRenameRetries - parameters->retries_left;
299 --parameters->retries_left; 304 --parameters->retries_left;
300 if (parameters->time_of_first_failure.is_null()) 305 if (parameters->time_of_first_failure.is_null())
301 parameters->time_of_first_failure = base::TimeTicks::Now(); 306 parameters->time_of_first_failure = base::TimeTicks::Now();
302 BrowserThread::PostDelayedTask( 307 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
303 BrowserThread::FILE,
304 FROM_HERE, 308 FROM_HERE,
305 base::Bind(&DownloadFileImpl::RenameWithRetryInternal, 309 base::Bind(&DownloadFileImpl::RenameWithRetryInternal,
306 weak_factory_.GetWeakPtr(), 310 weak_factory_.GetWeakPtr(),
307 base::Passed(std::move(parameters))), 311 base::Passed(std::move(parameters))),
308 GetRetryDelayForFailedRename(attempt_number)); 312 GetRetryDelayForFailedRename(attempt_number));
309 return; 313 return;
310 } 314 }
311 315
312 if (!parameters->time_of_first_failure.is_null()) 316 if (!parameters->time_of_first_failure.is_null())
313 RecordDownloadFileRenameResultAfterRetry( 317 RecordDownloadFileRenameResultAfterRetry(
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 383
380 bool DownloadFileImpl::InProgress() const { 384 bool DownloadFileImpl::InProgress() const {
381 return file_.in_progress(); 385 return file_.in_progress();
382 } 386 }
383 387
384 void DownloadFileImpl::WasPaused() { 388 void DownloadFileImpl::WasPaused() {
385 record_stream_bandwidth_ = false; 389 record_stream_bandwidth_ = false;
386 } 390 }
387 391
388 void DownloadFileImpl::StreamActive(SourceStream* source_stream) { 392 void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
393 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
389 DCHECK(source_stream->stream_reader()); 394 DCHECK(source_stream->stream_reader());
390 base::TimeTicks start(base::TimeTicks::Now()); 395 base::TimeTicks start(base::TimeTicks::Now());
391 base::TimeTicks now; 396 base::TimeTicks now;
392 scoped_refptr<net::IOBuffer> incoming_data; 397 scoped_refptr<net::IOBuffer> incoming_data;
393 size_t incoming_data_size = 0; 398 size_t incoming_data_size = 0;
394 size_t total_incoming_data_size = 0; 399 size_t total_incoming_data_size = 0;
395 size_t num_buffers = 0; 400 size_t num_buffers = 0;
396 size_t bytes_to_write = 0; 401 size_t bytes_to_write = 0;
397 bool should_terminate = false; 402 bool should_terminate = false;
398 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY); 403 ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 break; 466 break;
462 } 467 }
463 now = base::TimeTicks::Now(); 468 now = base::TimeTicks::Now();
464 } while (state == ByteStreamReader::STREAM_HAS_DATA && 469 } while (state == ByteStreamReader::STREAM_HAS_DATA &&
465 reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta && 470 reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta &&
466 !should_terminate); 471 !should_terminate);
467 472
468 // If we're stopping to yield the thread, post a task so we come back. 473 // If we're stopping to yield the thread, post a task so we come back.
469 if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta && 474 if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta &&
470 !should_terminate) { 475 !should_terminate) {
471 BrowserThread::PostTask( 476 base::SequencedTaskRunnerHandle::Get()->PostTask(
472 BrowserThread::FILE, FROM_HERE, 477 FROM_HERE, base::Bind(&DownloadFileImpl::StreamActive,
473 base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), 478 weak_factory_.GetWeakPtr(), source_stream));
474 source_stream));
475 } 479 }
476 480
477 if (total_incoming_data_size) 481 if (total_incoming_data_size)
478 RecordFileThreadReceiveBuffers(num_buffers); 482 RecordFileThreadReceiveBuffers(num_buffers);
479 483
480 RecordContiguousWriteTime(now - start); 484 RecordContiguousWriteTime(now - start);
481 485
482 // Take care of communication with our observer. 486 // Take care of communication with our observer.
483 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 487 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
484 HandleStreamError(source_stream, reason); 488 HandleStreamError(source_stream, reason);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 } 523 }
520 } 524 }
521 if (net_log_.IsCapturing()) { 525 if (net_log_.IsCapturing()) {
522 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED, 526 net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED,
523 base::Bind(&FileStreamDrainedNetLogCallback, 527 base::Bind(&FileStreamDrainedNetLogCallback,
524 total_incoming_data_size, num_buffers)); 528 total_incoming_data_size, num_buffers));
525 } 529 }
526 } 530 }
527 531
528 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { 532 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) {
529 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 533 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
534
530 ByteStreamReader* stream_reader = source_stream->stream_reader(); 535 ByteStreamReader* stream_reader = source_stream->stream_reader();
531 if (stream_reader) { 536 if (stream_reader) {
532 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive, 537 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive,
533 weak_factory_.GetWeakPtr(), 538 weak_factory_.GetWeakPtr(),
534 source_stream)); 539 source_stream));
535 // Truncate |source_stream|'s length if necessary. 540 // Truncate |source_stream|'s length if necessary.
536 for (const auto& received_slice : received_slices_) { 541 for (const auto& received_slice : received_slices_) {
537 source_stream->TruncateLengthWithWrittenDataBlock( 542 source_stream->TruncateLengthWithWrittenDataBlock(
538 received_slice.offset, received_slice.received_bytes); 543 received_slice.offset, received_slice.received_bytes);
539 } 544 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 if (slices_to_download.size() > 1) { 614 if (slices_to_download.size() > 1) {
610 // If there are 1 or more holes in the file, download is not finished. 615 // If there are 1 or more holes in the file, download is not finished.
611 // Some streams might not have been added to |source_streams_| yet. 616 // Some streams might not have been added to |source_streams_| yet.
612 return false; 617 return false;
613 } 618 }
614 return TotalBytesReceived() == potential_file_length_; 619 return TotalBytesReceived() == potential_file_length_;
615 } 620 }
616 621
617 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, 622 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
618 DownloadInterruptReason reason) { 623 DownloadInterruptReason reason) {
619 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 624 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
625
620 source_stream->stream_reader()->RegisterCallback(base::Closure()); 626 source_stream->stream_reader()->RegisterCallback(base::Closure());
621 source_stream->set_finished(true); 627 source_stream->set_finished(true);
622 num_active_streams_--; 628 num_active_streams_--;
623 629
624 bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite); 630 bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite);
625 631
626 if (IsSparseFile() && !can_recover_from_error) { 632 if (IsSparseFile() && !can_recover_from_error) {
627 // If a neighboring stream request is available, check if it can help 633 // If a neighboring stream request is available, check if it can help
628 // download all the data left by |source stream| or has already done so. We 634 // download all the data left by |source stream| or has already done so. We
629 // want to avoid the situation that a server always fail additional requests 635 // want to avoid the situation that a server always fail additional requests
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 const base::FilePath& new_path, 732 const base::FilePath& new_path,
727 const RenameCompletionCallback& completion_callback) 733 const RenameCompletionCallback& completion_callback)
728 : option(option), 734 : option(option),
729 new_path(new_path), 735 new_path(new_path),
730 retries_left(kMaxRenameRetries), 736 retries_left(kMaxRenameRetries),
731 completion_callback(completion_callback) {} 737 completion_callback(completion_callback) {}
732 738
733 DownloadFileImpl::RenameParameters::~RenameParameters() {} 739 DownloadFileImpl::RenameParameters::~RenameParameters() {}
734 740
735 } // namespace content 741 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | content/browser/download/download_file_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698