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

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: 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 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 source_stream)); 367 source_stream));
368 } 368 }
369 369
370 if (total_incoming_data_size) 370 if (total_incoming_data_size)
371 RecordFileThreadReceiveBuffers(num_buffers); 371 RecordFileThreadReceiveBuffers(num_buffers);
372 372
373 RecordContiguousWriteTime(now - start); 373 RecordContiguousWriteTime(now - start);
374 374
375 // Take care of communication with our observer. 375 // Take care of communication with our observer.
376 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 376 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
377 // Error case for both upstream source and file write. 377 HandleStreamError(source_stream, reason);
378 // Shut down processing and signal an error to our observer.
379 // Our observer will clean us up.
380 source_stream->stream_reader()->RegisterCallback(base::Closure());
381 weak_factory_.InvalidateWeakPtrs();
382 SendUpdate(); // Make info up to date before error.
383 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
384 BrowserThread::PostTask(
385 BrowserThread::UI, FROM_HERE,
386 base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
387 reason, TotalBytesReceived(), base::Passed(&hash_state)));
388 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) { 378 } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) {
389 // Signal successful completion or termination of the current stream. 379 // Signal successful completion or termination of the current stream.
390 source_stream->stream_reader()->RegisterCallback(base::Closure()); 380 source_stream->stream_reader()->RegisterCallback(base::Closure());
391 source_stream->set_finished(true); 381 source_stream->set_finished(true);
392 382
393 // Inform observers. 383 // Inform observers.
394 SendUpdate(); 384 SendUpdate();
395 385
396 // All the stream reader are completed, shut down file IO processing. 386 // All the stream reader are completed, shut down file IO processing.
397 if (IsDownloadCompleted()) { 387 if (IsDownloadCompleted()) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 return false; 498 return false;
509 } 499 }
510 DCHECK_EQ(slices_to_download[0].offset, 500 DCHECK_EQ(slices_to_download[0].offset,
511 stream_for_last_slice->offset() + 501 stream_for_last_slice->offset() +
512 stream_for_last_slice->bytes_written()); 502 stream_for_last_slice->bytes_written());
513 } 503 }
514 504
515 return true; 505 return true;
516 } 506 }
517 507
508 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
509 DownloadInterruptReason reason) {
510 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
511 source_stream->stream_reader()->RegisterCallback(base::Closure());
512 source_stream->set_finished(true);
513
514 bool can_recover_from_error = false;
515
516 if (is_sparse_file_) {
517 auto initial_source_stream = source_streams_.find(save_info_->offset);
xingliu 2017/03/18 22:27:34 What if the error is triggered by the initial stre
qinmin 2017/03/20 20:59:21 If the error is trigger by initial stream, set_fin
xingliu 2017/03/20 22:33:33 I see.
David Trainor- moved to gerrit 2017/03/21 17:00:16 Should we just call this stream_iterator or someth
qinmin 2017/03/21 19:29:17 Done.
518 DCHECK(initial_source_stream != source_streams_.end());
519 SourceStream* initial_stream = initial_source_stream->second.get();
520 // If the initial request is alive, check if it can help download all the
David Trainor- moved to gerrit 2017/03/21 17:00:16 Can we add a TODO to figure out allowing adjacent
qinmin 2017/03/21 19:29:17 Done.
521 // data left by this source stream. We want to avoid the situation that
522 // a server always fail additional requests from the client thus causing the
523 // initial request and the download going nowhere.
524 if (!initial_stream->is_finished() &&
525 (initial_stream->length() == DownloadSaveInfo::kLengthFullContent ||
526 initial_stream->offset() + initial_stream->length() >
527 source_stream->offset() + source_stream->length())) {
528 // The initial stream will download all data downloading from its offset
xingliu 2017/03/18 22:27:34 If there is a new slice added, does the initial sl
qinmin 2017/03/20 20:59:21 No. For example, there are stream A, B, C ordered
xingliu 2017/03/20 22:33:33 sgtm.
David Trainor- moved to gerrit 2017/03/21 17:00:16 Hmm that seems like it might be a really common oc
qinmin 2017/03/21 19:29:17 This will add more complexity to the current logic
David Trainor- moved to gerrit 2017/03/22 03:10:55 Okay I guess it's fine to postpone this for now.
529 // to source_stream->offset(). Close all other streams in the middle.
530 for (auto& stream : source_streams_) {
531 if (stream.second->offset() < source_stream->offset() &&
532 stream.second.get() != initial_stream) {
533 DCHECK_EQ(stream.second->bytes_written(), 0);
xingliu 2017/03/18 22:27:34 Is it safe to assume streams in the middle never w
qinmin 2017/03/20 20:59:21 Yes, if a stream in the middle writes something, i
xingliu 2017/03/20 22:33:33 I see.
David Trainor- moved to gerrit 2017/03/21 17:00:16 Who kills the outstanding request if the middle st
xingliu 2017/03/21 17:48:04 DownloadFileImpl and all objects under it will get
David Trainor- moved to gerrit 2017/03/22 03:10:55 Thanks!
534 stream.second->stream_reader()->RegisterCallback(base::Closure());
535 stream.second->set_finished(true);
536 }
537 }
538 can_recover_from_error = true;
539 }
540 }
541
542 SendUpdate(); // Make info up to date before error.
543
544 if (!can_recover_from_error) {
545 // Error case for both upstream source and file write.
546 // Shut down processing and signal an error to our observer.
547 // Our observer will clean us up.
548 weak_factory_.InvalidateWeakPtrs();
David Trainor- moved to gerrit 2017/03/21 17:00:16 Should we pull out the shutdown code to a common h
qinmin 2017/03/21 19:29:17 No, we don't have the lines duplicated. It is simi
David Trainor- moved to gerrit 2017/03/22 03:10:55 Yeah makes sense. Thanks
549 std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
550 BrowserThread::PostTask(
551 BrowserThread::UI, FROM_HERE,
552 base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
553 reason, TotalBytesReceived(), base::Passed(&hash_state)));
xingliu 2017/03/20 22:33:33 nit%: Not in this CL, since we allow duplicate IO
xingliu 2017/03/20 22:35:10 make sure it's ok for user to see larger bytes num
qinmin 2017/03/21 19:29:17 This won't happen. TotalBytesReceived is calculate
554 }
555 }
556
518 DownloadFileImpl::RenameParameters::RenameParameters( 557 DownloadFileImpl::RenameParameters::RenameParameters(
519 RenameOption option, 558 RenameOption option,
520 const base::FilePath& new_path, 559 const base::FilePath& new_path,
521 const RenameCompletionCallback& completion_callback) 560 const RenameCompletionCallback& completion_callback)
522 : option(option), 561 : option(option),
523 new_path(new_path), 562 new_path(new_path),
524 retries_left(kMaxRenameRetries), 563 retries_left(kMaxRenameRetries),
525 completion_callback(completion_callback) {} 564 completion_callback(completion_callback) {}
526 565
527 DownloadFileImpl::RenameParameters::~RenameParameters() {} 566 DownloadFileImpl::RenameParameters::~RenameParameters() {}
528 567
529 } // namespace content 568 } // 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