diff -p -up aria2c/src/AbstractCommand.cc.exit-status aria2c/src/AbstractCommand.cc --- aria2c/src/AbstractCommand.cc.exit-status 2008-10-24 11:44:31.000000000 +0200 +++ aria2c/src/AbstractCommand.cc 2008-10-27 11:30:49.000000000 +0100 @@ -148,13 +148,14 @@ bool AbstractCommand::execute() { req->getProtocol()); ss->setError(); - throw DlRetryEx(EX_TIME_OUT); + throw DlRetryEx(EX_TIME_OUT, DownloadResult::TIME_OUT); } e->commands.push_back(this); return false; } } catch(DlAbortEx& err) { logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str()); + _requestGroup->addResult(req->getUrl(), err.getCode()); onAbort(); req->resetUrl(); tryReserved(); @@ -173,6 +174,7 @@ bool AbstractCommand::execute() { if(isAbort) { logger->info(MSG_MAX_TRY, cuid, req->getTryCount()); logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str()); + _requestGroup->addResult(req->getUrl(), err.getCode()); tryReserved(); return true; } else { @@ -180,6 +182,7 @@ bool AbstractCommand::execute() { } } catch(DownloadFailureException& err) { logger->error(EX_EXCEPTION_CAUGHT, err); + _requestGroup->addResult(req->getUrl(), err.getCode()); _requestGroup->setHaltRequested(true); return true; } diff -p -up aria2c/src/DlAbortEx.h.exit-status aria2c/src/DlAbortEx.h --- aria2c/src/DlAbortEx.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/DlAbortEx.h 2008-10-24 11:44:31.000000000 +0200 @@ -50,6 +50,7 @@ public: DlAbortEx(const std::string& msg, const Exception& cause):RecoverableException(msg, cause) {} DlAbortEx(const RecoverableException& e):RecoverableException(e) {} + DlAbortEx(const std::string& msg, DownloadResult::RESULT code):RecoverableException(msg, code) {} }; } // namespace aria2 diff -p -up aria2c/src/DlRetryEx.h.exit-status aria2c/src/DlRetryEx.h --- aria2c/src/DlRetryEx.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/DlRetryEx.h 2008-10-24 11:44:31.000000000 +0200 @@ -50,6 +50,7 @@ public: DlRetryEx(const std::string& msg, const Exception& cause):RecoverableException(msg, cause) {} DlRetryEx(const DlRetryEx& e):RecoverableException(e) {} + DlRetryEx(const std::string& msg, DownloadResult::RESULT code):RecoverableException(msg, code) {} }; } // namespace aria2 diff -p -up aria2c/src/DownloadCommand.cc.exit-status aria2c/src/DownloadCommand.cc --- aria2c/src/DownloadCommand.cc.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/DownloadCommand.cc 2008-10-24 11:44:31.000000000 +0200 @@ -225,7 +225,7 @@ void DownloadCommand::checkLowestDownloa throw DlAbortEx(StringFormat(EX_TOO_SLOW_DOWNLOAD_SPEED, nowSpeed, lowestDownloadSpeedLimit, - req->getHost().c_str()).str()); + req->getHost().c_str()).str(), DownloadResult::TOO_SLOW_DOWNLOAD_SPEED); } } } diff -p -up aria2c/src/DownloadFailureException.h.exit-status aria2c/src/DownloadFailureException.h --- aria2c/src/DownloadFailureException.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/DownloadFailureException.h 2008-10-24 11:44:31.000000000 +0200 @@ -54,6 +54,7 @@ public: DownloadFailureException(const std::string& msg, const Exception& cause):RecoverableException(msg, cause) {} DownloadFailureException(const DownloadFailureException& e):RecoverableException(e) {} + DownloadFailureException(const std::string& msg, DownloadResult::RESULT code):RecoverableException(msg, code) {} }; } // namespace aria2 diff -p -up aria2c/src/DownloadResult.h.exit-status aria2c/src/DownloadResult.h --- aria2c/src/DownloadResult.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/DownloadResult.h 2008-10-24 15:03:09.000000000 +0200 @@ -47,7 +47,12 @@ class DownloadResult public: enum RESULT { FINISHED, - NOT_YET, + UNKNOWN_ERROR, + TIME_OUT, + RESOURCE_NOT_FOUND, + MAX_FILE_NOT_FOUND, + TOO_SLOW_DOWNLOAD_SPEED, + NETWORK_PROBLEM, }; int32_t gid; diff -p -up aria2c/src/FtpNegotiationCommand.cc.exit-status aria2c/src/FtpNegotiationCommand.cc --- aria2c/src/FtpNegotiationCommand.cc.exit-status 2008-10-24 11:44:31.000000000 +0200 +++ aria2c/src/FtpNegotiationCommand.cc 2008-10-24 17:59:26.000000000 +0200 @@ -225,7 +225,10 @@ bool FtpNegotiationCommand::recvCwd() { if(status != 250) { poolConnection(); _requestGroup->increaseAndValidateFileNotFoundCount(); - throw DlAbortEx(StringFormat(EX_BAD_STATUS, status).str()); + if (status == 550) + throw DlAbortEx(MSG_RESOURCE_NOT_FOUND, DownloadResult::RESOURCE_NOT_FOUND); + else + throw DlAbortEx(StringFormat(EX_BAD_STATUS, status).str()); } if(e->option->getAsBool(PREF_REMOTE_TIME)) { sequence = SEQ_SEND_MDTM; @@ -497,7 +500,10 @@ bool FtpNegotiationCommand::recvRetr() { } if(status != 150 && status != 125) { _requestGroup->increaseAndValidateFileNotFoundCount(); - throw DlAbortEx(StringFormat(EX_BAD_STATUS, status).str()); + if (status == 550) + throw DlAbortEx(MSG_RESOURCE_NOT_FOUND, DownloadResult::RESOURCE_NOT_FOUND); + else + throw DlAbortEx(StringFormat(EX_BAD_STATUS, status).str()); } if(e->option->getAsBool(PREF_FTP_PASV)) { sequence = SEQ_NEGOTIATION_COMPLETED; diff -p -up aria2c/src/HttpSkipResponseCommand.cc.exit-status aria2c/src/HttpSkipResponseCommand.cc --- aria2c/src/HttpSkipResponseCommand.cc.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/HttpSkipResponseCommand.cc 2008-10-24 11:44:31.000000000 +0200 @@ -142,7 +142,7 @@ bool HttpSkipResponseCommand::processRes if(_httpResponse->getResponseStatus() == HttpHeader::S401) { throw DlAbortEx(EX_AUTH_FAILED); }else if(_httpResponse->getResponseStatus() == HttpHeader::S404) { - throw DlAbortEx(MSG_RESOURCE_NOT_FOUND); + throw DlAbortEx(MSG_RESOURCE_NOT_FOUND, DownloadResult::RESOURCE_NOT_FOUND); } else { throw DlAbortEx(StringFormat(EX_BAD_STATUS, Util::parseUInt(_httpResponse->getResponseStatus())).str()); } diff -p -up aria2c/src/MultiUrlRequestInfo.cc.exit-status aria2c/src/MultiUrlRequestInfo.cc --- aria2c/src/MultiUrlRequestInfo.cc.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/MultiUrlRequestInfo.cc 2008-10-27 11:18:29.000000000 +0100 @@ -91,13 +91,13 @@ void MultiUrlRequestInfo::printMessageFo << "\n"; } -int MultiUrlRequestInfo::execute() +DownloadResult::RESULT MultiUrlRequestInfo::execute() { { DNSCacheHandle dnsCache(new SimpleDNSCache()); DNSCacheSingletonHolder::instance(dnsCache); } - int returnValue = 0; + DownloadResult::RESULT returnValue = DownloadResult::FINISHED; try { DownloadEngineHandle e = DownloadEngineFactory().newDownloadEngine(_option, _requestGroups); @@ -147,7 +147,7 @@ int MultiUrlRequestInfo::execute() RequestGroupMan::DownloadStat s = e->_requestGroupMan->getDownloadStat(); if(!s.allCompleted()) { printMessageForContinue(); - returnValue = 1; + returnValue = s.get_exit_status(); } } catch(RecoverableException *ex) { _logger->error(EX_EXCEPTION_CAUGHT, ex); diff -p -up aria2c/src/MultiUrlRequestInfo.h.exit-status aria2c/src/MultiUrlRequestInfo.h --- aria2c/src/MultiUrlRequestInfo.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/MultiUrlRequestInfo.h 2008-10-24 11:44:31.000000000 +0200 @@ -37,6 +37,7 @@ #include "common.h" #include "SharedHandle.h" +#include "DownloadResult.h" #include <deque> #include <iosfwd> @@ -71,9 +72,9 @@ public: virtual ~MultiUrlRequestInfo(); /** - * Returns 0 if all downloads have completed, otherwise returns 1. + * Returns FINISHED if all downloads have completed, otherwise returns the download result */ - int execute(); + DownloadResult::RESULT execute(); }; typedef SharedHandle<MultiUrlRequestInfo> MultiUrlRequestInfoHandle; diff -p -up aria2c/src/PeerAbstractCommand.cc.exit-status aria2c/src/PeerAbstractCommand.cc --- aria2c/src/PeerAbstractCommand.cc.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/PeerAbstractCommand.cc 2008-10-24 11:44:31.000000000 +0200 @@ -87,10 +87,10 @@ bool PeerAbstractCommand::execute() } else if(_errorEvent) { throw DlAbortEx (StringFormat(MSG_NETWORK_PROBLEM, - socket->getSocketError().c_str()).str()); + socket->getSocketError().c_str()).str(), DownloadResult::NETWORK_PROBLEM); } if(checkPoint.elapsed(timeout)) { - throw DlAbortEx(EX_TIME_OUT); + throw DlAbortEx(EX_TIME_OUT, DownloadResult::TIME_OUT); } return executeInternal(); } catch(DownloadFailureException& err) { diff -p -up aria2c/src/RecoverableException.h.exit-status aria2c/src/RecoverableException.h --- aria2c/src/RecoverableException.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/RecoverableException.h 2008-10-24 11:44:31.000000000 +0200 @@ -35,10 +35,14 @@ #ifndef _D_RECOVERABLE_EXCEPTION_H_ #define _D_RECOVERABLE_EXCEPTION_H_ #include "Exception.h" +#include "DownloadResult.h" namespace aria2 { class RecoverableException:public Exception { +private: + DownloadResult::RESULT _code; + protected: virtual SharedHandle<Exception> copy() const { @@ -46,10 +50,13 @@ protected: return e; } public: - RecoverableException(const std::string& msg):Exception(msg) {} + RecoverableException(const std::string& msg):Exception(msg), _code(DownloadResult::UNKNOWN_ERROR) {} RecoverableException(const std::string& msg, - const Exception& cause):Exception(msg, cause) {} - RecoverableException(const RecoverableException& e):Exception(e) {} + const Exception& cause):Exception(msg, cause), _code(DownloadResult::UNKNOWN_ERROR) {} + RecoverableException(const RecoverableException& e):Exception(e), _code(DownloadResult::UNKNOWN_ERROR) {} + RecoverableException(const std::string& msg, DownloadResult::RESULT code):Exception(msg), _code(code) {} + + DownloadResult::RESULT getCode() const { return _code; } }; } // namespace aria2 diff -p -up aria2c/src/RequestGroup.cc.exit-status aria2c/src/RequestGroup.cc --- aria2c/src/RequestGroup.cc.exit-status 2008-10-24 11:44:31.000000000 +0200 +++ aria2c/src/RequestGroup.cc 2008-10-27 11:19:55.000000000 +0100 @@ -170,6 +170,18 @@ bool RequestGroup::allDownloadFinished() } } +DownloadResult::RESULT RequestGroup::downloadResult() const +{ + if (downloadFinished()) + return DownloadResult::FINISHED; + else { + if (!_uri_results.empty()) + return _uri_results.front().second; + else + return DownloadResult::UNKNOWN_ERROR; + } +} + void RequestGroup::closeFile() { if(!_pieceStorage.isNull()) { @@ -887,9 +899,7 @@ DownloadResultHandle RequestGroup::creat getTotalLength(), uris.empty() ? A2STR::NIL:uris.front(), uris.size(), - downloadFinished()? - DownloadResult::FINISHED : - DownloadResult::NOT_YET)); + downloadResult())); } void RequestGroup::registerServerHost(const ServerHostHandle& serverHost) @@ -1057,7 +1067,7 @@ void RequestGroup::increaseAndValidateFi if(maxCount > 0 && _fileNotFoundCount >= maxCount && _segmentMan->calculateSessionDownloadLength() == 0) { throw DownloadFailureException - (StringFormat("Reached max-file-not-found count=%u", maxCount).str()); + (StringFormat("Reached max-file-not-found count=%u", maxCount).str(), DownloadResult::MAX_FILE_NOT_FOUND); } } diff -p -up aria2c/src/RequestGroup.h.exit-status aria2c/src/RequestGroup.h --- aria2c/src/RequestGroup.h.exit-status 2008-10-24 11:44:31.000000000 +0200 +++ aria2c/src/RequestGroup.h 2008-10-27 11:33:39.000000000 +0100 @@ -39,6 +39,7 @@ #include "SharedHandle.h" #include "TransferStat.h" #include "TimeA2.h" +#include "DownloadResult.h" #include <string> #include <deque> @@ -105,6 +107,8 @@ private: bool _forceHaltRequested; + std::deque<std::pair<std::string, DownloadResult::RESULT> > _uri_results; + bool _singleHostMultiConnectionEnabled; std::deque<SharedHandle<PreDownloadHandler> > _preDownloadHandlers; @@ -137,6 +141,8 @@ private: bool tryAutoFileRenaming(); + DownloadResult::RESULT downloadResult() const; + public: RequestGroup(const Option* option, const std::deque<std::string>& uris); @@ -284,6 +290,10 @@ public: return _forceHaltRequested; } + void addResult(std::string uri, DownloadResult::RESULT result) { _uri_results.push_front(std::pair<std::string, DownloadResult::RESULT>(uri, result)); } + + std::deque<std::pair<std::string, DownloadResult::RESULT> >& getResults() { return _uri_results; } + void dependsOn(const SharedHandle<Dependency>& dep); bool isDependencyResolved(); diff -p -up aria2c/src/RequestGroupMan.cc.exit-status aria2c/src/RequestGroupMan.cc --- aria2c/src/RequestGroupMan.cc.exit-status 2008-10-24 11:44:31.000000000 +0200 +++ aria2c/src/RequestGroupMan.cc 2008-10-24 11:44:31.000000000 +0200 @@ -355,14 +355,14 @@ RequestGroupMan::DownloadStat RequestGro { DownloadStat stat; size_t finished = 0; - size_t error = 0; + DownloadResult::RESULT exit_status = DownloadResult::FINISHED; size_t inprogress = 0; for(std::deque<SharedHandle<DownloadResult> >::const_iterator itr = _downloadResults.begin(); itr != _downloadResults.end(); ++itr) { if((*itr)->result == DownloadResult::FINISHED) { ++finished; } else { - ++error; + exit_status = (*itr)->result; } } for(RequestGroups::const_iterator itr = _requestGroups.begin(); @@ -374,8 +374,7 @@ RequestGroupMan::DownloadStat RequestGro ++inprogress; } } - stat.setCompleted(finished); - stat.setError(error); + stat.setExitStatus(exit_status); stat.setInProgress(inprogress); stat.setWaiting(_reservedGroups.size()); return stat; diff -p -up aria2c/src/RequestGroupMan.h.exit-status aria2c/src/RequestGroupMan.h --- aria2c/src/RequestGroupMan.h.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/RequestGroupMan.h 2008-10-24 11:44:31.000000000 +0200 @@ -37,6 +37,7 @@ #include "common.h" #include "SharedHandle.h" +#include "DownloadResult.h" #include "TransferStat.h" #include <string> #include <deque> @@ -114,20 +115,21 @@ public: class DownloadStat { private: size_t _completed; - size_t _error; + DownloadResult::RESULT _exit_status; size_t _inProgress; size_t _waiting; public: - DownloadStat():_completed(0), _error(0), _inProgress(0), _waiting(0) {} + DownloadStat(): _exit_status(DownloadResult::FINISHED), _inProgress(0), _waiting(0) {} - void setCompleted(size_t c) { _completed = c; } - void setError(size_t c) { _error = c; } + void setExitStatus(DownloadResult::RESULT s) { _exit_status = s; } void setInProgress(size_t c) { _inProgress = c; } void setWaiting(size_t c) { _waiting = c; } + DownloadResult::RESULT get_exit_status() const { return _exit_status; } + bool allCompleted() const { - return _error == 0 && _inProgress == 0 && _waiting == 0; + return _exit_status == DownloadResult::FINISHED && _inProgress == 0 && _waiting == 0; } }; diff -p -up aria2c/src/main.cc.exit-status aria2c/src/main.cc --- aria2c/src/main.cc.exit-status 2008-09-18 14:48:03.000000000 +0200 +++ aria2c/src/main.cc 2008-10-24 11:44:31.000000000 +0200 @@ -425,9 +425,7 @@ int main(int argc, char* argv[]) } else { returnValue = downloadUri(op, args); } - if(returnValue == 1) { - exitStatus = EXIT_FAILURE; - } + exitStatus = returnValue; } catch(Exception& ex) { std::cerr << EX_EXCEPTION_CAUGHT << "\n" << ex.stackTrace() << std::endl; exitStatus = EXIT_FAILURE;