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

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

Issue 2748103014: Allow the initial request to take over failed parallel requests. (Closed)
Patch Set: rebase again Created 3 years, 9 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
« no previous file with comments | « content/browser/download/download_file_impl.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 "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"
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 source_stream)); 397 source_stream));
398 } 398 }
399 399
400 if (total_incoming_data_size) 400 if (total_incoming_data_size)
401 RecordFileThreadReceiveBuffers(num_buffers); 401 RecordFileThreadReceiveBuffers(num_buffers);
402 402
403 RecordContiguousWriteTime(now - start); 403 RecordContiguousWriteTime(now - start);
404 404
405 // Take care of communication with our observer. 405 // Take care of communication with our observer.
406 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 406 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
407 // Error case for both upstream source and file write. 407 HandleStreamError(source_stream, reason);
408 // Shut down processing and signal an error to our observer.
409 // Our observer will clean us up.
410 source_stream->stream_reader()->RegisterCallback(base::Closure());
411 weak_factory_.InvalidateWeakPtrs();
412 SendUpdate(); // Make info up to date before error.
413 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
414 BrowserThread::PostTask(
415 BrowserThread::UI, FROM_HERE,
416 base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
417 reason, TotalBytesReceived(), base::Passed(&hash_state)));
418 num_active_streams_--;
419 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { 408 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) {
420 // Signal successful completion or termination of the current stream. 409 // Signal successful completion or termination of the current stream.
421 source_stream->stream_reader()->RegisterCallback(base::Closure()); 410 source_stream->stream_reader()->RegisterCallback(base::Closure());
422 source_stream->set_finished(true); 411 source_stream->set_finished(true);
423 num_active_streams_--; 412 num_active_streams_--;
424 413
425 // Inform observers. 414 // Inform observers.
426 SendUpdate(); 415 SendUpdate();
427 416
428 // All the stream reader are completed, shut down file IO processing. 417 // All the stream reader are completed, shut down file IO processing.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 return false; 548 return false;
560 } 549 }
561 DCHECK_EQ(slices_to_download[0].offset, 550 DCHECK_EQ(slices_to_download[0].offset,
562 stream_for_last_slice->offset() + 551 stream_for_last_slice->offset() +
563 stream_for_last_slice->bytes_written()); 552 stream_for_last_slice->bytes_written());
564 } 553 }
565 554
566 return true; 555 return true;
567 } 556 }
568 557
558 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
559 DownloadInterruptReason reason) {
560 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
561 source_stream->stream_reader()->RegisterCallback(base::Closure());
562 source_stream->set_finished(true);
563 num_active_streams_--;
564
565 bool can_recover_from_error = false;
566
567 if (is_sparse_file_) {
568 // If a neighboring stream request is available, check if it can help
569 // download all the data left by |source stream| or has already done so. We
570 // want to avoid the situation that a server always fail additional requests
571 // from the client thus causing the initial request and the download going
572 // nowhere.
573 // TODO(qinmin): make all streams half open so that they can recover
574 // failures from their neighbors.
575 SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream);
576 while (preceding_neighbor) {
577 int64_t upper_range = source_stream->offset() + source_stream->length();
578 if ((!preceding_neighbor->is_finished() &&
579 (preceding_neighbor->length() ==
580 DownloadSaveInfo::kLengthFullContent ||
581 preceding_neighbor->offset() + preceding_neighbor->length() >=
582 upper_range)) ||
583 (preceding_neighbor->offset() + preceding_neighbor->bytes_written() >=
584 upper_range)) {
585 can_recover_from_error = true;
586 break;
587 }
588 // If the neighbor cannot recover the error and it has already created
589 // a slice, just interrupt the download.
590 if (preceding_neighbor->bytes_written() > 0)
591 break;
592 preceding_neighbor = FindPrecedingNeighbor(preceding_neighbor);
593 }
594
595 if (can_recover_from_error) {
596 // Since the neighbor stream will download all data downloading from its
597 // offset to source_stream->offset(). Close all other streams in the
598 // middle.
599 for (auto& stream : source_streams_) {
600 if (stream.second->offset() < source_stream->offset() &&
601 stream.second->offset() > preceding_neighbor->offset()) {
602 DCHECK_EQ(stream.second->bytes_written(), 0);
603 stream.second->stream_reader()->RegisterCallback(base::Closure());
604 stream.second->set_finished(true);
605 num_active_streams_--;
606 }
607 }
608 }
609 }
610
611 SendUpdate(); // Make info up to date before error.
612
613 if (!can_recover_from_error) {
614 // Error case for both upstream source and file write.
615 // Shut down processing and signal an error to our observer.
616 // Our observer will clean us up.
617 weak_factory_.InvalidateWeakPtrs();
618 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
619 BrowserThread::PostTask(
620 BrowserThread::UI, FROM_HERE,
621 base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
622 reason, TotalBytesReceived(), base::Passed(&hash_state)));
623 }
624 }
625
626 DownloadFileImpl::SourceStream* DownloadFileImpl::FindPrecedingNeighbor(
627 SourceStream* source_stream) {
628 int64_t max_preceding_offset = 0;
629 SourceStream* ret = nullptr;
630 for (auto& stream : source_streams_) {
631 int64_t offset = stream.second->offset();
632 if (offset < source_stream->offset() && offset >= max_preceding_offset) {
633 ret = stream.second.get();
634 max_preceding_offset = offset;
635 }
636 }
637 return ret;
638 }
639
569 DownloadFileImpl::RenameParameters::RenameParameters( 640 DownloadFileImpl::RenameParameters::RenameParameters(
570 RenameOption option, 641 RenameOption option,
571 const base::FilePath& new_path, 642 const base::FilePath& new_path,
572 const RenameCompletionCallback& completion_callback) 643 const RenameCompletionCallback& completion_callback)
573 : option(option), 644 : option(option),
574 new_path(new_path), 645 new_path(new_path),
575 retries_left(kMaxRenameRetries), 646 retries_left(kMaxRenameRetries),
576 completion_callback(completion_callback) {} 647 completion_callback(completion_callback) {}
577 648
578 DownloadFileImpl::RenameParameters::~RenameParameters() {} 649 DownloadFileImpl::RenameParameters::~RenameParameters() {}
579 650
580 } // namespace content 651 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698