summaryrefslogtreecommitdiff
path: root/src/AbstractCommand.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-03-28 07:23:33 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-03-28 07:23:33 +0000
commitabe1e9843c1a357605013dae68b6b3bbb704cacb (patch)
tree810774c5c0325c746d90c4a4dcae028f896a99bd /src/AbstractCommand.cc
parent90bc2ccffc98a7be3af424932415e248e4385b22 (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.cc64
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);
+ }
+ }
+ }
}
}