diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-03-28 07:23:33 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-03-28 07:23:33 +0000 |
| commit | abe1e9843c1a357605013dae68b6b3bbb704cacb (patch) | |
| tree | 810774c5c0325c746d90c4a4dcae028f896a99bd /src/AbstractCommand.cc | |
| parent | 90bc2ccffc98a7be3af424932415e248e4385b22 (diff) | |
2010-03-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --always-resume and --max-resume-failure-tries option. If
--always-resume=false is given, when all given URIs does not
support resume or aria2 encounters N URIs which does not support
resume
(N is the value specified using --max-resume-failure-tries
option), aria2 download file from scratch. The default behavior
is --always-resume=true, which means if all URIs do not support
resume, download fails. I think this is OK because user normally
don't like to see that partially downloaded file is
overwritten(this is particularly true if file size is big). This
option is useful when aria2 is used as download backend and
graceful falling back to overwritten behavior is preferable.
Added exit status value 8, which means download failed because
server did not support resume.
* src/AbstractCommand.cc
* src/DefaultPieceStorage.cc
* src/DownloadCommand.cc
* src/DownloadResultCode.h
* src/FileEntry.h
* src/FtpNegotiationCommand.cc
* src/HttpResponse.cc
* src/HttpResponseCommand.cc
* src/OptionHandlerFactory.cc
* src/RequestGroup.cc
* src/RequestGroup.h
* src/SegmentMan.cc
* src/SegmentMan.h
* src/prefs.cc
* src/prefs.h
* src/usage_text.h
* test/DefaultPieceStorageTest.cc
* test/SegmentManTest.cc
Diffstat (limited to 'src/AbstractCommand.cc')
| -rw-r--r-- | src/AbstractCommand.cc | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 084b10c2..85b55475 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -148,6 +148,15 @@ bool AbstractCommand::execute() { if(!_requestGroup->getPieceStorage().isNull()) { _segments.clear(); _requestGroup->getSegmentMan()->getInFlightSegment(_segments, cuid); + if(!req.isNull() && _segments.empty()) { + // This command previously has assigned segments, but it is + // canceled. So discard current request chain. + if(logger->debug()) { + logger->debug("CUID#%s - It seems previously assigned segments are" + "canceled. Restart.", util::itos(cuid).c_str()); + } + return prepareForRetry(0); + } if(req.isNull() || req->getMaxPipelinedRequest() == 1 || _requestGroup->getDownloadContext()->getFileEntries().size() == 1) { if(_segments.empty()) { @@ -215,6 +224,9 @@ bool AbstractCommand::execute() { util::itos(cuid).c_str(), req->getUri().c_str()); _fileEntry->addURIResult(req->getUri(), err.getCode()); _requestGroup->setLastUriResult(req->getUri(), err.getCode()); + if(err.getCode() == downloadresultcode::CANNOT_RESUME) { + _requestGroup->increaseResumeFailureCount(); + } } onAbort(); tryReserved(); @@ -233,7 +245,6 @@ bool AbstractCommand::execute() { const unsigned int maxTries = getOption()->getAsInt(PREF_MAX_TRIES); bool isAbort = maxTries != 0 && req->getTryCount() >= maxTries; if(isAbort) { - onAbort(); if(logger->info()) { logger->info(MSG_MAX_TRY, util::itos(cuid).c_str(), req->getTryCount()); } @@ -241,6 +252,10 @@ bool AbstractCommand::execute() { req->getUri().c_str()); _fileEntry->addURIResult(req->getUri(), err.getCode()); _requestGroup->setLastUriResult(req->getUri(), err.getCode()); + if(err.getCode() == downloadresultcode::CANNOT_RESUME) { + _requestGroup->increaseResumeFailureCount(); + } + onAbort(); tryReserved(); return true; } else { @@ -323,7 +338,52 @@ void AbstractCommand::onAbort() { logger->debug("CUID#%s - Aborting download", util::itos(cuid).c_str()); } if(!_requestGroup->getPieceStorage().isNull()) { - _requestGroup->getSegmentMan()->cancelSegment(cuid); + SharedHandle<SegmentMan> segmentMan = _requestGroup->getSegmentMan(); + segmentMan->cancelSegment(cuid); + // Don't do following process if BitTorrent is involved or files + // in DownloadContext is more than 1. The latter condition is + // limitation of current implementation. + if(!getOption()->getAsBool(PREF_ALWAYS_RESUME) && + !_fileEntry.isNull() && + segmentMan->calculateSessionDownloadLength() == 0 && + !_requestGroup->p2pInvolved() && + _requestGroup->getDownloadContext()->getFileEntries().size() == 1) { + const int maxTries = getOption()->getAsInt(PREF_MAX_RESUME_FAILURE_TRIES); + if((maxTries > 0 && _requestGroup->getResumeFailureCount() >= maxTries)|| + _fileEntry->emptyRequestUri()) { + // Local file exists, but given servers(or at least contacted + // ones) doesn't support resume. Let's restart download from + // scratch. + logger->notice("CUID#%s - Failed to resume download." + " Download from scratch.", + util::itos(cuid).c_str()); + if(logger->debug()) { + logger->debug("CUID#%s - Gathering URIs that has CANNOT_RESUME error", + util::itos(cuid).c_str()); + } + // Set PREF_ALWAYS_RESUME to V_TRUE to avoid repeating this + // process. + getOption()->put(PREF_ALWAYS_RESUME, V_TRUE); + std::deque<URIResult> res; + _fileEntry->extractURIResult(res, downloadresultcode::CANNOT_RESUME); + if(!res.empty()) { + segmentMan->cancelAllSegments(); + segmentMan->eraseSegmentWrittenLengthMemo(); + _requestGroup->getPieceStorage()->markPiecesDone(0); + std::vector<std::string> uris; + uris.reserve(res.size()); + std::transform(res.begin(), res.end(), std::back_inserter(uris), + std::mem_fun_ref(&URIResult::getURI)); + if(logger->debug()) { + logger->debug("CUID#%s - %lu URIs found.", + util::itos(cuid).c_str(), + static_cast<unsigned long int>(uris.size())); + } + _fileEntry->addUris(uris.begin(), uris.end()); + segmentMan->recognizeSegmentFor(_fileEntry); + } + } + } } } |
