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

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

Issue 2770303002: Add a helper method to truncate SourceStream's length (Closed)
Patch Set: nit 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
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 13 matching lines...) Expand all
24 #include "crypto/secure_hash.h" 24 #include "crypto/secure_hash.h"
25 #include "crypto/sha2.h" 25 #include "crypto/sha2.h"
26 #include "net/base/io_buffer.h" 26 #include "net/base/io_buffer.h"
27 #include "net/log/net_log.h" 27 #include "net/log/net_log.h"
28 #include "net/log/net_log_event_type.h" 28 #include "net/log/net_log_event_type.h"
29 #include "net/log/net_log_source.h" 29 #include "net/log/net_log_source.h"
30 #include "net/log/net_log_source_type.h" 30 #include "net/log/net_log_source_type.h"
31 31
32 namespace content { 32 namespace content {
33 33
34 namespace {
35
34 const int kUpdatePeriodMs = 500; 36 const int kUpdatePeriodMs = 500;
35 const int kMaxTimeBlockingFileThreadMs = 1000; 37 const int kMaxTimeBlockingFileThreadMs = 1000;
36 38
37 // These constants control the default retry behavior for failing renames. Each 39 // These constants control the default retry behavior for failing renames. Each
38 // retry is performed after a delay that is twice the previous delay. The 40 // retry is performed after a delay that is twice the previous delay. The
39 // initial delay is specified by kInitialRenameRetryDelayMs. 41 // initial delay is specified by kInitialRenameRetryDelayMs.
40 const int kInitialRenameRetryDelayMs = 200; 42 const int kInitialRenameRetryDelayMs = 200;
41 43
42 // Number of times a failing rename is retried before giving up. 44 // Number of times a failing rename is retried before giving up.
43 const int kMaxRenameRetries = 3; 45 const int kMaxRenameRetries = 3;
44 46
47 // Because DownloadSaveInfo::kLengthFullContent is 0, we should avoid using
48 // 0 for length if we found that a stream can no longer write any data.
49 const int kNoBytesToWrite = -1;
50
51 } // namespace
52
45 DownloadFileImpl::SourceStream::SourceStream( 53 DownloadFileImpl::SourceStream::SourceStream(
46 int64_t offset, 54 int64_t offset,
47 int64_t length, 55 int64_t length,
48 std::unique_ptr<ByteStreamReader> stream_reader) 56 std::unique_ptr<ByteStreamReader> stream_reader)
49 : offset_(offset), 57 : offset_(offset),
50 length_(length), 58 length_(length),
51 bytes_written_(0), 59 bytes_written_(0),
52 finished_(false), 60 finished_(false),
53 index_(0u), 61 index_(0u),
54 stream_reader_(std::move(stream_reader)) {} 62 stream_reader_(std::move(stream_reader)) {}
55 63
56 DownloadFileImpl::SourceStream::~SourceStream() = default; 64 DownloadFileImpl::SourceStream::~SourceStream() = default;
57 65
58 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { 66 void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) {
59 bytes_written_ += bytes_write; 67 bytes_written_ += bytes_write;
60 } 68 }
61 69
70 void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
71 int64_t offset,
72 int64_t bytes_written) {
73 DCHECK_GT(bytes_written, 0);
74 if (length_ == kNoBytesToWrite)
75 return;
76
77 if (offset <= offset_) {
78 if (offset + bytes_written > offset_)
79 length_ = kNoBytesToWrite;
80 return;
81 }
82
83 if (length_ == DownloadSaveInfo::kLengthFullContent ||
84 length_ > offset - offset_) {
85 length_ = offset - offset_;
86 }
87 }
88
62 DownloadFileImpl::DownloadFileImpl( 89 DownloadFileImpl::DownloadFileImpl(
63 std::unique_ptr<DownloadSaveInfo> save_info, 90 std::unique_ptr<DownloadSaveInfo> save_info,
64 const base::FilePath& default_download_directory, 91 const base::FilePath& default_download_directory,
65 std::unique_ptr<ByteStreamReader> stream_reader, 92 std::unique_ptr<ByteStreamReader> stream_reader,
66 const std::vector<DownloadItem::ReceivedSlice>& received_slices, 93 const std::vector<DownloadItem::ReceivedSlice>& received_slices,
67 const net::NetLogWithSource& download_item_net_log, 94 const net::NetLogWithSource& download_item_net_log,
68 bool is_sparse_file, 95 bool is_sparse_file,
69 base::WeakPtr<DownloadDestinationObserver> observer) 96 base::WeakPtr<DownloadDestinationObserver> observer)
70 : net_log_( 97 : net_log_(
71 net::NetLogWithSource::Make(download_item_net_log.net_log(), 98 net::NetLogWithSource::Make(download_item_net_log.net_log(),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 const char* data, 181 const char* data,
155 size_t data_len) { 182 size_t data_len) {
156 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 183 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
157 WillWriteToDisk(data_len); 184 WillWriteToDisk(data_len);
158 return file_.WriteDataToFile(offset, data, data_len); 185 return file_.WriteDataToFile(offset, data, data_len);
159 } 186 }
160 187
161 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, 188 bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream,
162 size_t bytes_available_to_write, 189 size_t bytes_available_to_write,
163 size_t* bytes_to_write) { 190 size_t* bytes_to_write) {
191 if (source_stream->length() == kNoBytesToWrite) {
192 *bytes_to_write = 0;
193 return true;
194 }
195
164 // If a new slice finds that its target position has already been written, 196 // If a new slice finds that its target position has already been written,
165 // terminate the stream. 197 // terminate the stream.
166 if (source_stream->bytes_written() == 0) { 198 if (source_stream->bytes_written() == 0) {
167 for (const auto& received_slice : received_slices_) { 199 for (const auto& received_slice : received_slices_) {
168 if (received_slice.offset <= source_stream->offset() && 200 if (received_slice.offset <= source_stream->offset() &&
169 received_slice.offset + received_slice.received_bytes > 201 received_slice.offset + received_slice.received_bytes >
170 source_stream->offset()) { 202 source_stream->offset()) {
171 *bytes_to_write = 0; 203 *bytes_to_write = 0;
172 return true; 204 return true;
173 } 205 }
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 } 473 }
442 } 474 }
443 475
444 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { 476 void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) {
445 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 477 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
446 ByteStreamReader* stream_reader = source_stream->stream_reader(); 478 ByteStreamReader* stream_reader = source_stream->stream_reader();
447 if (stream_reader) { 479 if (stream_reader) {
448 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive, 480 stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive,
449 weak_factory_.GetWeakPtr(), 481 weak_factory_.GetWeakPtr(),
450 source_stream)); 482 source_stream));
483 // Truncate |source_stream|'s length if necessary.
484 for (const auto& received_slice : received_slices_) {
485 source_stream->TruncateLengthWithWrittenDataBlock(
486 received_slice.offset, received_slice.received_bytes);
487 }
451 StreamActive(source_stream); 488 StreamActive(source_stream);
452 num_active_streams_++; 489 num_active_streams_++;
453 } 490 }
454 } 491 }
455 492
456 int64_t DownloadFileImpl::TotalBytesReceived() const { 493 int64_t DownloadFileImpl::TotalBytesReceived() const {
457 return file_.bytes_so_far(); 494 return file_.bytes_so_far();
458 } 495 }
459 496
460 void DownloadFileImpl::SendUpdate() { 497 void DownloadFileImpl::SendUpdate() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 // Check if the slice is added as a new slice, or merged with an existing one. 533 // Check if the slice is added as a new slice, or merged with an existing one.
497 bool slice_added = (offset == received_slices_[index].offset); 534 bool slice_added = (offset == received_slices_[index].offset);
498 // Update the index of exising SourceStreams. 535 // Update the index of exising SourceStreams.
499 for (auto& stream : source_streams_) { 536 for (auto& stream : source_streams_) {
500 SourceStream* source_stream = stream.second.get(); 537 SourceStream* source_stream = stream.second.get();
501 if (source_stream->offset() > offset) { 538 if (source_stream->offset() > offset) {
502 if (slice_added && source_stream->bytes_written() > 0) 539 if (slice_added && source_stream->bytes_written() > 0)
503 source_stream->set_index(source_stream->index() + 1); 540 source_stream->set_index(source_stream->index() + 1);
504 } else if (source_stream->offset() == offset) { 541 } else if (source_stream->offset() == offset) {
505 source_stream->set_index(index); 542 source_stream->set_index(index);
506 } else if (source_stream->length() == 543 } else {
507 DownloadSaveInfo::kLengthFullContent || 544 source_stream->TruncateLengthWithWrittenDataBlock(offset, length);
508 source_stream->length() > offset - source_stream->offset()) {
509 // The newly introduced slice will impact the length of the SourceStreams
510 // preceding it.
511 source_stream->set_length(offset - source_stream->offset());
512 } 545 }
513 } 546 }
514 } 547 }
515 548
516 bool DownloadFileImpl::IsDownloadCompleted() { 549 bool DownloadFileImpl::IsDownloadCompleted() {
517 SourceStream* stream_for_last_slice = nullptr; 550 SourceStream* stream_for_last_slice = nullptr;
518 int64_t last_slice_offset = 0; 551 int64_t last_slice_offset = 0;
519 for (auto& stream : source_streams_) { 552 for (auto& stream : source_streams_) {
520 SourceStream* source_stream = stream.second.get(); 553 SourceStream* source_stream = stream.second.get();
521 if (source_stream->offset() >= last_slice_offset && 554 if (source_stream->offset() >= last_slice_offset &&
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 590
558 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, 591 void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
559 DownloadInterruptReason reason) { 592 DownloadInterruptReason reason) {
560 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 593 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
561 source_stream->stream_reader()->RegisterCallback(base::Closure()); 594 source_stream->stream_reader()->RegisterCallback(base::Closure());
562 source_stream->set_finished(true); 595 source_stream->set_finished(true);
563 num_active_streams_--; 596 num_active_streams_--;
564 597
565 bool can_recover_from_error = false; 598 bool can_recover_from_error = false;
566 599
567 if (is_sparse_file_) { 600 if (is_sparse_file_ && source_stream->length() != kNoBytesToWrite) {
568 // If a neighboring stream request is available, check if it can help 601 // 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 602 // 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 603 // 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 604 // from the client thus causing the initial request and the download going
572 // nowhere. 605 // nowhere.
573 // TODO(qinmin): make all streams half open so that they can recover 606 // TODO(qinmin): make all streams half open so that they can recover
574 // failures from their neighbors. 607 // failures from their neighbors.
575 SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream); 608 SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream);
576 while (preceding_neighbor) { 609 while (preceding_neighbor) {
577 int64_t upper_range = source_stream->offset() + source_stream->length(); 610 int64_t upper_range = source_stream->offset() + source_stream->length();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 const base::FilePath& new_path, 675 const base::FilePath& new_path,
643 const RenameCompletionCallback& completion_callback) 676 const RenameCompletionCallback& completion_callback)
644 : option(option), 677 : option(option),
645 new_path(new_path), 678 new_path(new_path),
646 retries_left(kMaxRenameRetries), 679 retries_left(kMaxRenameRetries),
647 completion_callback(completion_callback) {} 680 completion_callback(completion_callback) {}
648 681
649 DownloadFileImpl::RenameParameters::~RenameParameters() {} 682 DownloadFileImpl::RenameParameters::~RenameParameters() {}
650 683
651 } // namespace content 684 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | content/browser/download/download_item_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698