diff options
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); + } + } + } } } |
