summaryrefslogtreecommitdiff
path: root/src/AbstractCommand.cc
diff options
context:
space:
mode:
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);
+ }
+ }
+ }
}
}