Index: trunk/src/content/browser/download/download_file_impl.cc |
=================================================================== |
--- trunk/src/content/browser/download/download_file_impl.cc (revision 278536) |
+++ trunk/src/content/browser/download/download_file_impl.cc (working copy) |
@@ -25,12 +25,6 @@ |
const int kUpdatePeriodMs = 500; |
const int kMaxTimeBlockingFileThreadMs = 1000; |
-// These constants control the default retry behavior for failing renames. Each |
-// retry is performed after a delay that is twice the previous delay. The |
-// initial delay is specified by kInitialRenameRetryDelayMs. |
-const int kMaxRenameRetries = 3; |
-const int kInitialRenameRetryDelayMs = 200; |
- |
int DownloadFile::number_active_objects_ = 0; |
DownloadFileImpl::DownloadFileImpl( |
@@ -42,20 +36,20 @@ |
scoped_ptr<ByteStreamReader> stream, |
const net::BoundNetLog& bound_net_log, |
base::WeakPtr<DownloadDestinationObserver> observer) |
- : file_(save_info->file_path, |
- url, |
- referrer_url, |
- save_info->offset, |
- calculate_hash, |
- save_info->hash_state, |
- save_info->file.Pass(), |
- bound_net_log), |
- default_download_directory_(default_download_directory), |
- stream_reader_(stream.Pass()), |
- bytes_seen_(0), |
- bound_net_log_(bound_net_log), |
- observer_(observer), |
- weak_factory_(this) { |
+ : file_(save_info->file_path, |
+ url, |
+ referrer_url, |
+ save_info->offset, |
+ calculate_hash, |
+ save_info->hash_state, |
+ save_info->file.Pass(), |
+ bound_net_log), |
+ default_download_directory_(default_download_directory), |
+ stream_reader_(stream.Pass()), |
+ bytes_seen_(0), |
+ bound_net_log_(bound_net_log), |
+ observer_(observer), |
+ weak_factory_(this) { |
} |
DownloadFileImpl::~DownloadFileImpl() { |
@@ -109,84 +103,47 @@ |
void DownloadFileImpl::RenameAndUniquify( |
const base::FilePath& full_path, |
const RenameCompletionCallback& callback) { |
- RenameWithRetryInternal( |
- full_path, UNIQUIFY, kMaxRenameRetries, base::TimeTicks(), callback); |
-} |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
-void DownloadFileImpl::RenameAndAnnotate( |
- const base::FilePath& full_path, |
- const RenameCompletionCallback& callback) { |
- RenameWithRetryInternal(full_path, |
- ANNOTATE_WITH_SOURCE_INFORMATION, |
- kMaxRenameRetries, |
- base::TimeTicks(), |
- callback); |
-} |
+ base::FilePath new_path(full_path); |
-base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename( |
- int attempt_number) { |
- DCHECK_GE(attempt_number, 0); |
- // |delay| starts at kInitialRenameRetryDelayMs and increases by a factor of |
- // 2 at each subsequent retry. Assumes that |retries_left| starts at |
- // kMaxRenameRetries. Also assumes that kMaxRenameRetries is less than the |
- // number of bits in an int. |
- return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) * |
- (1 << attempt_number); |
-} |
+ int uniquifier = base::GetUniquePathNumber( |
+ new_path, base::FilePath::StringType()); |
+ if (uniquifier > 0) { |
+ new_path = new_path.InsertBeforeExtensionASCII( |
+ base::StringPrintf(" (%d)", uniquifier)); |
+ } |
-bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { |
- return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; |
+ DownloadInterruptReason reason = file_.Rename(new_path); |
+ if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { |
+ // Make sure our information is updated, since we're about to |
+ // error out. |
+ SendUpdate(); |
+ |
+ // Null out callback so that we don't do any more stream processing. |
+ stream_reader_->RegisterCallback(base::Closure()); |
+ |
+ new_path.clear(); |
+ } |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(callback, reason, new_path)); |
} |
-void DownloadFileImpl::RenameWithRetryInternal( |
+void DownloadFileImpl::RenameAndAnnotate( |
const base::FilePath& full_path, |
- RenameOption option, |
- int retries_left, |
- base::TimeTicks time_of_first_failure, |
const RenameCompletionCallback& callback) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
base::FilePath new_path(full_path); |
- if ((option & UNIQUIFY) && full_path != file_.full_path()) { |
- int uniquifier = |
- base::GetUniquePathNumber(new_path, base::FilePath::StringType()); |
- if (uniquifier > 0) |
- new_path = new_path.InsertBeforeExtensionASCII( |
- base::StringPrintf(" (%d)", uniquifier)); |
- } |
+ DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; |
+ // Short circuit null rename. |
+ if (full_path != file_.full_path()) |
+ reason = file_.Rename(new_path); |
- DownloadInterruptReason reason = file_.Rename(new_path); |
- |
- // Attempt to retry the rename if possible. If the rename failed and the |
- // subsequent open also failed, then in_progress() would be false. We don't |
- // try to retry renames if the in_progress() was false to begin with since we |
- // have less assurance that the file at file_.full_path() was the one we were |
- // working with. |
- if (ShouldRetryFailedRename(reason) && file_.in_progress() && |
- retries_left > 0) { |
- int attempt_number = kMaxRenameRetries - retries_left; |
- BrowserThread::PostDelayedTask( |
- BrowserThread::FILE, |
- FROM_HERE, |
- base::Bind(&DownloadFileImpl::RenameWithRetryInternal, |
- weak_factory_.GetWeakPtr(), |
- full_path, |
- option, |
- --retries_left, |
- time_of_first_failure.is_null() ? base::TimeTicks::Now() |
- : time_of_first_failure, |
- callback), |
- GetRetryDelayForFailedRename(attempt_number)); |
- return; |
- } |
- |
- if (!time_of_first_failure.is_null()) |
- RecordDownloadFileRenameResultAfterRetry( |
- base::TimeTicks::Now() - time_of_first_failure, reason); |
- |
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE && |
- (option & ANNOTATE_WITH_SOURCE_INFORMATION)) { |
+ if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
// Doing the annotation after the rename rather than before leaves |
// a very small window during which the file has the final name but |
// hasn't been marked with the Mark Of The Web. However, it allows |