summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2013-04-25 21:46:31 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2013-04-25 21:46:31 +0900
commit90abec8a362d6224bfff76d12fc9365fac36ddaa (patch)
tree115a8248adda60f01004bdae167571c3f95d3806 /src
parentbbb978948d87790c6dfb78eaca1d47d45101443d (diff)
Move initialization code in aria2::main to struct Context
Diffstat (limited to 'src')
-rw-r--r--src/Context.cc298
-rw-r--r--src/Context.h53
-rw-r--r--src/DownloadEngine.cc18
-rw-r--r--src/DownloadEngine.h6
-rw-r--r--src/Makefile.am5
-rw-r--r--src/MultiUrlRequestInfo.cc169
-rw-r--r--src/MultiUrlRequestInfo.h19
-rw-r--r--src/RequestGroupMan.cc5
-rw-r--r--src/SingletonHolder.h15
-rw-r--r--src/main.cc249
10 files changed, 510 insertions, 327 deletions
diff --git a/src/Context.cc b/src/Context.cc
new file mode 100644
index 00000000..da23982d
--- /dev/null
+++ b/src/Context.cc
@@ -0,0 +1,298 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2013 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "Context.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include <numeric>
+#include <vector>
+#include <iostream>
+
+#include "SharedHandle.h"
+#include "LogFactory.h"
+#include "Logger.h"
+#include "util.h"
+#include "FeatureConfig.h"
+#include "MultiUrlRequestInfo.h"
+#include "SimpleRandomizer.h"
+#include "File.h"
+#include "message.h"
+#include "prefs.h"
+#include "Option.h"
+#include "a2algo.h"
+#include "a2io.h"
+#include "a2time.h"
+#include "Platform.h"
+#include "FileEntry.h"
+#include "RequestGroup.h"
+#include "ConsoleStatCalc.h"
+#include "NullStatCalc.h"
+#include "download_helper.h"
+#include "Exception.h"
+#include "ProtocolDetector.h"
+#include "RecoverableException.h"
+#include "SocketCore.h"
+#include "DownloadContext.h"
+#include "fmt.h"
+#include "NullOutputFile.h"
+#include "console.h"
+#include "UriListParser.h"
+#ifdef ENABLE_BITTORRENT
+# include "bittorrent_helper.h"
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+# include "metalink_helper.h"
+# include "MetalinkEntry.h"
+#endif // ENABLE_METALINK
+#ifdef ENABLE_MESSAGE_DIGEST
+# include "message_digest_helper.h"
+#endif // ENABLE_MESSAGE_DIGEST
+
+extern char* optarg;
+extern int optind, opterr, optopt;
+
+namespace aria2 {
+
+SharedHandle<StatCalc> getStatCalc(const SharedHandle<Option>& op)
+{
+ SharedHandle<StatCalc> statCalc;
+ if(op->getAsBool(PREF_QUIET)) {
+ statCalc.reset(new NullStatCalc());
+ } else {
+ SharedHandle<ConsoleStatCalc> impl
+ (new ConsoleStatCalc(op->getAsInt(PREF_SUMMARY_INTERVAL),
+ op->getAsBool(PREF_HUMAN_READABLE)));
+ impl->setReadoutVisibility(op->getAsBool(PREF_SHOW_CONSOLE_READOUT));
+ impl->setTruncate(op->getAsBool(PREF_TRUNCATE_CONSOLE_READOUT));
+ statCalc = impl;
+ }
+ return statCalc;
+}
+
+SharedHandle<OutputFile> getSummaryOut(const SharedHandle<Option>& op)
+{
+ if(op->getAsBool(PREF_QUIET)) {
+ return SharedHandle<OutputFile>(new NullOutputFile());
+ } else {
+ return global::cout();
+ }
+}
+
+#ifdef ENABLE_BITTORRENT
+namespace {
+void showTorrentFile(const std::string& uri)
+{
+ SharedHandle<Option> op(new Option());
+ SharedHandle<DownloadContext> dctx(new DownloadContext());
+ bittorrent::load(uri, dctx, op);
+ bittorrent::print(*global::cout(), dctx);
+}
+} // namespace
+#endif // ENABLE_BITTORRENT
+
+#ifdef ENABLE_METALINK
+namespace {
+void showMetalinkFile
+(const std::string& uri, const SharedHandle<Option>& op)
+{
+ std::vector<SharedHandle<MetalinkEntry> > metalinkEntries;
+ metalink::parseAndQuery(metalinkEntries, uri, op.get(),
+ op->get(PREF_METALINK_BASE_URI));
+ std::vector<SharedHandle<FileEntry> > fileEntries;
+ MetalinkEntry::toFileEntry(fileEntries, metalinkEntries);
+ util::toStream(fileEntries.begin(), fileEntries.end(), *global::cout());
+ global::cout()->write("\n");
+ global::cout()->flush();
+}
+} // namespace
+#endif // ENABLE_METALINK
+
+#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK
+namespace {
+void showFiles
+(const std::vector<std::string>& uris, const SharedHandle<Option>& op)
+{
+ ProtocolDetector dt;
+ for(std::vector<std::string>::const_iterator i = uris.begin(),
+ eoi = uris.end(); i != eoi; ++i) {
+ printf(">>> ");
+ printf(MSG_SHOW_FILES, (*i).c_str());
+ printf("\n");
+ try {
+#ifdef ENABLE_BITTORRENT
+ if(dt.guessTorrentFile(*i)) {
+ showTorrentFile(*i);
+ } else
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ if(dt.guessMetalinkFile(*i)) {
+ showMetalinkFile(*i, op);
+ } else
+#endif // ENABLE_METALINK
+ {
+ printf(MSG_NOT_TORRENT_METALINK);
+ printf("\n\n");
+ }
+ } catch(RecoverableException& e) {
+ global::cout()->printf("%s\n", e.stackTrace().c_str());
+ }
+ }
+}
+} // namespace
+#endif // ENABLE_BITTORRENT || ENABLE_METALINK
+
+extern void option_processing(Option& option, std::vector<std::string>& uris,
+ int argc, char* argv[]);
+
+Context::Context(int argc, char** argv)
+{
+ std::vector<std::string> args;
+ SharedHandle<Option> op(new Option());
+ option_processing(*op.get(), args, argc, argv);
+
+ SimpleRandomizer::init();
+#ifdef ENABLE_BITTORRENT
+ bittorrent::generateStaticPeerId(op->get(PREF_PEER_ID_PREFIX));
+#endif // ENABLE_BITTORRENT
+ LogFactory::setLogFile(op->get(PREF_LOG));
+ LogFactory::setLogLevel(op->get(PREF_LOG_LEVEL));
+ LogFactory::setConsoleLogLevel(op->get(PREF_CONSOLE_LOG_LEVEL));
+ if(op->getAsBool(PREF_QUIET)) {
+ LogFactory::setConsoleOutput(false);
+ }
+ LogFactory::reconfigure();
+ A2_LOG_INFO("<<--- --- --- ---");
+ A2_LOG_INFO(" --- --- --- ---");
+ A2_LOG_INFO(" --- --- --- --->>");
+ A2_LOG_INFO(fmt("%s %s %s", PACKAGE, PACKAGE_VERSION, TARGET));
+ A2_LOG_INFO(MSG_LOGGING_STARTED);
+
+ if(op->getAsBool(PREF_DISABLE_IPV6)) {
+ SocketCore::setProtocolFamily(AF_INET);
+ // Get rid of AI_ADDRCONFIG. It causes name resolution error
+ // when none of network interface has IPv4 address.
+ setDefaultAIFlags(0);
+ }
+ net::checkAddrconfig();
+ // Bind interface
+ if(!op->get(PREF_INTERFACE).empty()) {
+ std::string iface = op->get(PREF_INTERFACE);
+ SocketCore::bindAddress(iface);
+ }
+ sigset_t mask;
+#ifdef HAVE_SIGACTION
+ sigemptyset(&mask);
+#else // !HAVE_SIGACTION
+ mask = 0;
+#endif // !HAVE_SIGACTION
+#ifdef SIGPIPE
+ util::setGlobalSignalHandler(SIGPIPE, &mask, SIG_IGN, 0);
+#endif
+#ifdef SIGCHLD
+ // Avoid to create zombie process when forked child processes are
+ // died.
+ util::setGlobalSignalHandler(SIGCHLD, &mask, SIG_IGN, 0);
+#endif // SIGCHILD
+ std::vector<SharedHandle<RequestGroup> > requestGroups;
+ SharedHandle<UriListParser> uriListParser;
+#ifdef ENABLE_BITTORRENT
+ if(!op->blank(PREF_TORRENT_FILE)) {
+ if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
+ showTorrentFile(op->get(PREF_TORRENT_FILE));
+ return;
+ } else {
+ createRequestGroupForBitTorrent(requestGroups, op, args,
+ op->get(PREF_TORRENT_FILE));
+ }
+ }
+ else
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+ if(!op->blank(PREF_METALINK_FILE)) {
+ if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
+ showMetalinkFile(op->get(PREF_METALINK_FILE), op);
+ return;
+ } else {
+ createRequestGroupForMetalink(requestGroups, op);
+ }
+ }
+ else
+#endif // ENABLE_METALINK
+ if(!op->blank(PREF_INPUT_FILE)) {
+ if(op->getAsBool(PREF_DEFERRED_INPUT)) {
+ uriListParser = openUriListParser(op->get(PREF_INPUT_FILE));
+ } else {
+ createRequestGroupForUriList(requestGroups, op);
+ }
+#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK
+ } else if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
+ showFiles(args, op);
+ return;
+#endif // ENABLE_METALINK || ENABLE_METALINK
+ } else {
+ createRequestGroupForUri(requestGroups, op, args, false, false, true);
+ }
+
+ // Remove option values which is only valid for URIs specified in
+ // command-line. If they are left, because op is used as a template
+ // for new RequestGroup(such as created in RPC command), they causes
+ // unintentional effect.
+ for(SharedHandle<Option> i = op; i; i = i->getParent()) {
+ i->remove(PREF_OUT);
+ i->remove(PREF_FORCE_SEQUENTIAL);
+ i->remove(PREF_INPUT_FILE);
+ i->remove(PREF_INDEX_OUT);
+ i->remove(PREF_SELECT_FILE);
+ i->remove(PREF_PAUSE);
+ i->remove(PREF_CHECKSUM);
+ i->remove(PREF_GID);
+ }
+ if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty() &&
+ !uriListParser) {
+ global::cout()->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD);
+ } else {
+ reqinfo.reset(new MultiUrlRequestInfo(requestGroups, op, getStatCalc(op),
+ getSummaryOut(op),
+ uriListParser));
+ }
+}
+
+Context::~Context()
+{
+}
+
+} // namespace aria2
diff --git a/src/Context.h b/src/Context.h
new file mode 100644
index 00000000..7a873bdd
--- /dev/null
+++ b/src/Context.h
@@ -0,0 +1,53 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2013 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include "common.h"
+#include "SharedHandle.h"
+
+namespace aria2 {
+
+class MultiUrlRequestInfo;
+
+struct Context {
+ Context(int argc, char** argv);
+ ~Context();
+ SharedHandle<MultiUrlRequestInfo> reqinfo;
+};
+
+} // namespace aria2
+
+#endif // CONTEXT_H
diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc
index 05478fe8..0f266b58 100644
--- a/src/DownloadEngine.cc
+++ b/src/DownloadEngine.cc
@@ -86,7 +86,7 @@ volatile sig_atomic_t globalHaltRequested = 0;
DownloadEngine::DownloadEngine(const SharedHandle<EventPoll>& eventPoll)
: eventPoll_(eventPoll),
haltRequested_(0),
- noWait_(false),
+ noWait_(true),
refreshInterval_(DEFAULT_REFRESH_INTERVAL),
cookieStorage_(new CookieStorage()),
#ifdef ENABLE_BITTORRENT
@@ -139,11 +139,15 @@ void executeCommand(std::deque<Command*>& commands,
}
} // namespace
-void DownloadEngine::run()
+int DownloadEngine::run(bool oneshot)
{
Timer cp;
cp.reset(0);
while(!commands_.empty() || !routineCommands_.empty()) {
+ if(!commands_.empty()) {
+ waitData();
+ }
+ noWait_ = false;
global::wallclock().reset();
calculateStatistics();
if(cp.differenceInMillis(global::wallclock())+A2_DELTA_MILLIS >=
@@ -156,12 +160,14 @@ void DownloadEngine::run()
}
executeCommand(routineCommands_, Command::STATUS_ALL);
afterEachIteration();
- if(!commands_.empty()) {
- waitData();
+ if(oneshot) {
+ return 1;
}
- noWait_ = false;
}
- onEndOfRun();
+ if(!oneshot) {
+ onEndOfRun();
+ }
+ return 0;
}
void DownloadEngine::waitData()
diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h
index d949bff6..f382a6c1 100644
--- a/src/DownloadEngine.h
+++ b/src/DownloadEngine.h
@@ -167,7 +167,11 @@ public:
~DownloadEngine();
- void run();
+ // If oneshot is true, this function returns after one event polling
+ // and performing action for them. This function returns 1 when
+ // oneshot is true and there are still downloads to be
+ // processed. Otherwise, returns 0.
+ int run(bool oneshot=false);
void cleanQueue();
diff --git a/src/Makefile.am b/src/Makefile.am
index 5a52d4ac..ef4ff62b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,9 +1,10 @@
SUBDIRS = includes
bin_PROGRAMS = aria2c
aria2c_SOURCES = main.cc\
- option_processing.cc\
version_usage.cc
-SRCS = SocketCore.cc SocketCore.h\
+SRCS = option_processing.cc\
+ Context.cc Context.h\
+ SocketCore.cc SocketCore.h\
BinaryStream.h\
Command.cc Command.h\
AbstractCommand.cc AbstractCommand.h\
diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc
index b0156aca..3f2b3e9f 100644
--- a/src/MultiUrlRequestInfo.cc
+++ b/src/MultiUrlRequestInfo.cc
@@ -109,12 +109,14 @@ MultiUrlRequestInfo::MultiUrlRequestInfo
const SharedHandle<StatCalc>& statCalc,
const SharedHandle<OutputFile>& summaryOut,
const SharedHandle<UriListParser>& uriListParser)
- : requestGroups_(requestGroups),
- option_(op),
+ : option_(op),
statCalc_(statCalc),
summaryOut_(summaryOut),
uriListParser_(uriListParser)
-{}
+ // TODO init mask_
+{
+ requestGroups_.swap(requestGroups);
+}
MultiUrlRequestInfo::~MultiUrlRequestInfo() {}
@@ -126,17 +128,15 @@ void MultiUrlRequestInfo::printMessageForContinue()
_("If there are any errors, then see the log file. See '-l' option in help/man page for details."));
}
-error_code::Value MultiUrlRequestInfo::execute()
+error_code::Value MultiUrlRequestInfo::prepare()
{
- error_code::Value returnValue = error_code::FINISHED;
- sigset_t mask;
try {
SharedHandle<rpc::WebSocketSessionMan> wsSessionMan;
if(option_->getAsBool(PREF_ENABLE_RPC)) {
wsSessionMan.reset(new rpc::WebSocketSessionMan());
}
- Notifier notifier(wsSessionMan);
- SingletonHolder<Notifier>::instance(&notifier);
+ SharedHandle<Notifier> notifier(new Notifier(wsSessionMan));
+ SingletonHolder<Notifier>::instance(notifier);
#ifdef ENABLE_SSL
if(option_->getAsBool(PREF_ENABLE_RPC) &&
@@ -159,15 +159,16 @@ error_code::Value MultiUrlRequestInfo::execute()
}
#endif // ENABLE_SSL
- SharedHandle<DownloadEngine> e =
- DownloadEngineFactory().newDownloadEngine(option_.get(), requestGroups_);
+ e_ = DownloadEngineFactory().newDownloadEngine(option_.get(),
+ requestGroups_);
// Avoid keeping RequestGroups alive longer than necessary
requestGroups_.clear();
if(!option_->blank(PREF_LOAD_COOKIES)) {
File cookieFile(option_->get(PREF_LOAD_COOKIES));
if(cookieFile.isFile() &&
- e->getCookieStorage()->load(cookieFile.getPath(), Time().getTime())) {
+ e_->getCookieStorage()->load(cookieFile.getPath(),
+ Time().getTime())) {
A2_LOG_INFO(fmt("Loaded cookies from '%s'.",
cookieFile.getPath().c_str()));
} else {
@@ -194,7 +195,7 @@ error_code::Value MultiUrlRequestInfo::execute()
authConfigFactory->setNetrc(netrc);
}
}
- e->setAuthConfigFactory(authConfigFactory);
+ e_->setAuthConfigFactory(authConfigFactory);
#ifdef ENABLE_SSL
SharedHandle<TLSContext> clTlsContext(TLSContext::make(TLS_CLIENT));
@@ -220,7 +221,7 @@ error_code::Value MultiUrlRequestInfo::execute()
#ifdef HAVE_ARES_ADDR_NODE
ares_addr_node* asyncDNSServers =
parseAsyncDNSServers(option_->get(PREF_ASYNC_DNS_SERVER));
- e->setAsyncDNSServers(asyncDNSServers);
+ e_->setAsyncDNSServers(asyncDNSServers);
#endif // HAVE_ARES_ADDR_NODE
if(!Timer::monotonicClock()) {
A2_LOG_WARN("Don't change system time while aria2c is running."
@@ -229,86 +230,120 @@ error_code::Value MultiUrlRequestInfo::execute()
std::string serverStatIf = option_->get(PREF_SERVER_STAT_IF);
if(!serverStatIf.empty()) {
- e->getRequestGroupMan()->loadServerStat(serverStatIf);
- e->getRequestGroupMan()->removeStaleServerStat
+ e_->getRequestGroupMan()->loadServerStat(serverStatIf);
+ e_->getRequestGroupMan()->removeStaleServerStat
(option_->getAsInt(PREF_SERVER_STAT_TIMEOUT));
}
- e->setStatCalc(statCalc_);
+ e_->setStatCalc(statCalc_);
if(uriListParser_) {
- e->getRequestGroupMan()->setUriListParser(uriListParser_);
+ e_->getRequestGroupMan()->setUriListParser(uriListParser_);
}
#ifdef HAVE_SIGACTION
- sigemptyset(&mask);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGTERM);
+ sigemptyset(&mask_);
+ sigaddset(&mask_, SIGINT);
+ sigaddset(&mask_, SIGTERM);
#ifdef SIGHUP
- sigaddset(&mask, SIGHUP);
+ sigaddset(&mask_, SIGHUP);
#endif // SIGHUP
#else // !HAVE_SIGACTION
- mask = 0;
+ mask_ = 0;
#endif // !HAVE_SIGACTION
#ifdef SIGHUP
- util::setGlobalSignalHandler(SIGHUP, &mask, handler, 0);
+ util::setGlobalSignalHandler(SIGHUP, &mask_, handler, 0);
#endif // SIGHUP
- util::setGlobalSignalHandler(SIGINT, &mask, handler, 0);
- util::setGlobalSignalHandler(SIGTERM, &mask, handler, 0);
+ util::setGlobalSignalHandler(SIGINT, &mask_, handler, 0);
+ util::setGlobalSignalHandler(SIGTERM, &mask_, handler, 0);
- e->getRequestGroupMan()->getNetStat().downloadStart();
- e->run();
+ e_->getRequestGroupMan()->getNetStat().downloadStart();
+ } catch(RecoverableException& e) {
+ SingletonHolder<Notifier>::clear();
+ resetSignalHandlers();
+ return error_code::UNKNOWN_ERROR;
+ }
+ return error_code::FINISHED;
+}
- if(!option_->blank(PREF_SAVE_COOKIES)) {
- e->getCookieStorage()->saveNsFormat(option_->get(PREF_SAVE_COOKIES));
- }
+error_code::Value MultiUrlRequestInfo::getResult()
+{
+ error_code::Value returnValue = error_code::FINISHED;
+ if(!option_->blank(PREF_SAVE_COOKIES)) {
+ e_->getCookieStorage()->saveNsFormat(option_->get(PREF_SAVE_COOKIES));
+ }
- const std::string& serverStatOf = option_->get(PREF_SERVER_STAT_OF);
- if(!serverStatOf.empty()) {
- e->getRequestGroupMan()->saveServerStat(serverStatOf);
- }
- e->getRequestGroupMan()->showDownloadResults
- (*summaryOut_, option_->get(PREF_DOWNLOAD_RESULT) == A2_V_FULL);
- summaryOut_->flush();
+ const std::string& serverStatOf = option_->get(PREF_SERVER_STAT_OF);
+ if(!serverStatOf.empty()) {
+ e_->getRequestGroupMan()->saveServerStat(serverStatOf);
+ }
+ e_->getRequestGroupMan()->showDownloadResults
+ (*summaryOut_, option_->get(PREF_DOWNLOAD_RESULT) == A2_V_FULL);
+ summaryOut_->flush();
- RequestGroupMan::DownloadStat s =
- e->getRequestGroupMan()->getDownloadStat();
- if(!s.allCompleted()) {
- printMessageForContinue();
- if(s.getLastErrorResult() == error_code::FINISHED &&
- s.getInProgress() > 0) {
- returnValue = error_code::IN_PROGRESS;
- } else {
- returnValue = s.getLastErrorResult();
- }
+ RequestGroupMan::DownloadStat s =
+ e_->getRequestGroupMan()->getDownloadStat();
+ if(!s.allCompleted()) {
+ printMessageForContinue();
+ if(s.getLastErrorResult() == error_code::FINISHED &&
+ s.getInProgress() > 0) {
+ returnValue = error_code::IN_PROGRESS;
+ } else {
+ returnValue = s.getLastErrorResult();
}
- SessionSerializer sessionSerializer(e->getRequestGroupMan());
- // TODO Add option: --save-session-status=error,inprogress,waiting
- if(!option_->blank(PREF_SAVE_SESSION)) {
- const std::string& filename = option_->get(PREF_SAVE_SESSION);
- if(sessionSerializer.save(filename)) {
- A2_LOG_NOTICE(fmt(_("Serialized session to '%s' successfully."),
- filename.c_str()));
- } else {
- A2_LOG_NOTICE(fmt(_("Failed to serialize session to '%s'."),
- filename.c_str()));
- }
+ }
+ SessionSerializer sessionSerializer(e_->getRequestGroupMan());
+ // TODO Add option: --save-session-status=error,inprogress,waiting
+ if(!option_->blank(PREF_SAVE_SESSION)) {
+ const std::string& filename = option_->get(PREF_SAVE_SESSION);
+ if(sessionSerializer.save(filename)) {
+ A2_LOG_NOTICE(fmt(_("Serialized session to '%s' successfully."),
+ filename.c_str()));
+ } else {
+ A2_LOG_NOTICE(fmt(_("Failed to serialize session to '%s'."),
+ filename.c_str()));
}
+ }
+ SingletonHolder<Notifier>::clear();
+ return returnValue;
+}
+
+int MultiUrlRequestInfo::run()
+{
+ int rv;
+ try {
+ rv = e_->run(true);
+ } catch(RecoverableException& e) {
+ rv = -1;
+ }
+ return rv;
+}
+
+error_code::Value MultiUrlRequestInfo::execute()
+{
+ error_code::Value returnValue;
+ returnValue = prepare();
+ if(returnValue != error_code::FINISHED) {
+ return returnValue;
+ }
+ try {
+ e_->run();
} catch(RecoverableException& e) {
- if(returnValue == error_code::FINISHED) {
- returnValue = error_code::UNKNOWN_ERROR;
- }
A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e);
}
- SingletonHolder<Notifier>::instance(0);
+ returnValue = getResult();
+ resetSignalHandlers();
+ return returnValue;
+}
+void MultiUrlRequestInfo::resetSignalHandlers()
+{
#ifdef HAVE_SIGACTION
- sigemptyset(&mask);
+ sigemptyset(&mask_);
#endif // HAVE_SIGACTION
#ifdef SIGHUP
- util::setGlobalSignalHandler(SIGHUP, &mask, SIG_DFL, 0);
+ util::setGlobalSignalHandler(SIGHUP, &mask_, SIG_DFL, 0);
#endif // SIGHUP
- util::setGlobalSignalHandler(SIGINT, &mask, SIG_DFL, 0);
- util::setGlobalSignalHandler(SIGTERM, &mask, SIG_DFL, 0);
- return returnValue;
+ util::setGlobalSignalHandler(SIGINT, &mask_, SIG_DFL, 0);
+ util::setGlobalSignalHandler(SIGTERM, &mask_, SIG_DFL, 0);
}
} // namespace aria2
diff --git a/src/MultiUrlRequestInfo.h b/src/MultiUrlRequestInfo.h
index 45a627df..0d6b7377 100644
--- a/src/MultiUrlRequestInfo.h
+++ b/src/MultiUrlRequestInfo.h
@@ -37,10 +37,13 @@
#include "common.h"
+#include <signal.h>
+
#include <vector>
#include "SharedHandle.h"
#include "DownloadResult.h"
+#include "util.h"
namespace aria2 {
@@ -49,10 +52,11 @@ class Option;
class StatCalc;
class OutputFile;
class UriListParser;
+class DownloadEngine;
class MultiUrlRequestInfo {
private:
- std::vector<SharedHandle<RequestGroup> >& requestGroups_;
+ std::vector<SharedHandle<RequestGroup> > requestGroups_;
SharedHandle<Option> option_;
@@ -62,7 +66,12 @@ private:
SharedHandle<UriListParser> uriListParser_;
+ SharedHandle<DownloadEngine> e_;
+
+ sigset_t mask_;
+
void printMessageForContinue();
+ void resetSignalHandlers();
public:
/*
* MultiRequestInfo effectively takes ownership of the
@@ -82,6 +91,14 @@ public:
* last download result.
*/
error_code::Value execute();
+
+ error_code::Value prepare();
+ error_code::Value getResult();
+ // Returns 1 if the caller needs to call this function one or more
+ // time. Returns 0 if the function succeeds. Returns -1 on error.
+ // For return value 0 and -1, the caller must call tearDown() to get
+ // final error code.
+ int run();
};
} // namespace aria2
diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc
index d24e274f..fb8b4994 100644
--- a/src/RequestGroupMan.cc
+++ b/src/RequestGroupMan.cc
@@ -214,9 +214,8 @@ void notifyDownloadEvent
(const std::string& event, const SharedHandle<RequestGroup>& group)
{
// Check NULL to make unit test easier.
- Notifier* notifier = SingletonHolder<Notifier>::instance();
- if(notifier) {
- notifier->notifyDownloadEvent(event, group);
+ if(SingletonHolder<Notifier>::instance()) {
+ SingletonHolder<Notifier>::instance()->notifyDownloadEvent(event, group);
}
}
diff --git a/src/SingletonHolder.h b/src/SingletonHolder.h
index 7f8e2d69..dcfe9e33 100644
--- a/src/SingletonHolder.h
+++ b/src/SingletonHolder.h
@@ -35,30 +35,37 @@
#ifndef D_SINGLETON_HOLDER_H
#define D_SINGLETON_HOLDER_H
+#include "SharedHandle.h"
+
namespace aria2 {
template<typename T>
class SingletonHolder {
private:
- static T* instance_;
+ static SharedHandle<T> instance_;
SingletonHolder() {}
public:
~SingletonHolder() {}
- static T* instance()
+ static const SharedHandle<T>& instance()
{
return instance_;
}
- static void instance(T* instance)
+ static void instance(const SharedHandle<T>& instance)
{
instance_ = instance;
}
+
+ static void clear()
+ {
+ instance_.reset();
+ }
};
template<typename T>
-T* SingletonHolder<T>::instance_ = 0;
+SharedHandle<T> SingletonHolder<T>::instance_;
} // namespace aria2
diff --git a/src/main.cc b/src/main.cc
index c58300f3..47968f2e 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -34,268 +34,31 @@
/* copyright --> */
#include "common.h"
-#include <signal.h>
#include <unistd.h>
-#include <getopt.h>
-
-#include <numeric>
-#include <vector>
-#include <iostream>
#include "SharedHandle.h"
-#include "LogFactory.h"
-#include "Logger.h"
-#include "util.h"
-#include "FeatureConfig.h"
+#include "Context.h"
#include "MultiUrlRequestInfo.h"
-#include "SimpleRandomizer.h"
-#include "File.h"
#include "message.h"
-#include "prefs.h"
-#include "Option.h"
-#include "a2algo.h"
-#include "a2io.h"
-#include "a2time.h"
#include "Platform.h"
-#include "FileEntry.h"
-#include "RequestGroup.h"
-#include "ConsoleStatCalc.h"
-#include "NullStatCalc.h"
-#include "download_helper.h"
#include "Exception.h"
-#include "ProtocolDetector.h"
-#include "RecoverableException.h"
-#include "SocketCore.h"
-#include "DownloadContext.h"
-#include "fmt.h"
-#include "NullOutputFile.h"
#include "console.h"
-#include "UriListParser.h"
-#ifdef ENABLE_BITTORRENT
-# include "bittorrent_helper.h"
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
-# include "metalink_helper.h"
-# include "MetalinkEntry.h"
-#endif // ENABLE_METALINK
-#ifdef ENABLE_MESSAGE_DIGEST
-# include "message_digest_helper.h"
-#endif // ENABLE_MESSAGE_DIGEST
-
-extern char* optarg;
-extern int optind, opterr, optopt;
namespace aria2 {
-SharedHandle<StatCalc> getStatCalc(const SharedHandle<Option>& op)
-{
- SharedHandle<StatCalc> statCalc;
- if(op->getAsBool(PREF_QUIET)) {
- statCalc.reset(new NullStatCalc());
- } else {
- SharedHandle<ConsoleStatCalc> impl
- (new ConsoleStatCalc(op->getAsInt(PREF_SUMMARY_INTERVAL),
- op->getAsBool(PREF_HUMAN_READABLE)));
- impl->setReadoutVisibility(op->getAsBool(PREF_SHOW_CONSOLE_READOUT));
- impl->setTruncate(op->getAsBool(PREF_TRUNCATE_CONSOLE_READOUT));
- statCalc = impl;
- }
- return statCalc;
-}
-
-SharedHandle<OutputFile> getSummaryOut(const SharedHandle<Option>& op)
+error_code::Value main(int argc, char** argv)
{
- if(op->getAsBool(PREF_QUIET)) {
- return SharedHandle<OutputFile>(new NullOutputFile());
- } else {
- return global::cout();
- }
-}
-
-#ifdef ENABLE_BITTORRENT
-namespace {
-void showTorrentFile(const std::string& uri)
-{
- SharedHandle<Option> op(new Option());
- SharedHandle<DownloadContext> dctx(new DownloadContext());
- bittorrent::load(uri, dctx, op);
- bittorrent::print(*global::cout(), dctx);
-}
-} // namespace
-#endif // ENABLE_BITTORRENT
-
-#ifdef ENABLE_METALINK
-namespace {
-void showMetalinkFile
-(const std::string& uri, const SharedHandle<Option>& op)
-{
- std::vector<SharedHandle<MetalinkEntry> > metalinkEntries;
- metalink::parseAndQuery(metalinkEntries, uri, op.get(),
- op->get(PREF_METALINK_BASE_URI));
- std::vector<SharedHandle<FileEntry> > fileEntries;
- MetalinkEntry::toFileEntry(fileEntries, metalinkEntries);
- util::toStream(fileEntries.begin(), fileEntries.end(), *global::cout());
- global::cout()->write("\n");
- global::cout()->flush();
-}
-} // namespace
-#endif // ENABLE_METALINK
-
-#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK
-namespace {
-void showFiles
-(const std::vector<std::string>& uris, const SharedHandle<Option>& op)
-{
- ProtocolDetector dt;
- for(std::vector<std::string>::const_iterator i = uris.begin(),
- eoi = uris.end(); i != eoi; ++i) {
- printf(">>> ");
- printf(MSG_SHOW_FILES, (*i).c_str());
- printf("\n");
- try {
-#ifdef ENABLE_BITTORRENT
- if(dt.guessTorrentFile(*i)) {
- showTorrentFile(*i);
- } else
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- if(dt.guessMetalinkFile(*i)) {
- showMetalinkFile(*i, op);
- } else
-#endif // ENABLE_METALINK
- {
- printf(MSG_NOT_TORRENT_METALINK);
- printf("\n\n");
- }
- } catch(RecoverableException& e) {
- global::cout()->printf("%s\n", e.stackTrace().c_str());
- }
- }
-}
-} // namespace
-#endif // ENABLE_BITTORRENT || ENABLE_METALINK
-
-extern void option_processing(Option& option, std::vector<std::string>& uris,
- int argc, char* argv[]);
-
-error_code::Value main(int argc, char* argv[])
-{
- std::vector<std::string> args;
- SharedHandle<Option> op(new Option());
- option_processing(*op.get(), args, argc, argv);
-
- SimpleRandomizer::init();
-#ifdef ENABLE_BITTORRENT
- bittorrent::generateStaticPeerId(op->get(PREF_PEER_ID_PREFIX));
-#endif // ENABLE_BITTORRENT
- LogFactory::setLogFile(op->get(PREF_LOG));
- LogFactory::setLogLevel(op->get(PREF_LOG_LEVEL));
- LogFactory::setConsoleLogLevel(op->get(PREF_CONSOLE_LOG_LEVEL));
- if(op->getAsBool(PREF_QUIET)) {
- LogFactory::setConsoleOutput(false);
- }
- LogFactory::reconfigure();
+ Context context(argc, argv);
error_code::Value exitStatus = error_code::FINISHED;
- A2_LOG_INFO("<<--- --- --- ---");
- A2_LOG_INFO(" --- --- --- ---");
- A2_LOG_INFO(" --- --- --- --->>");
- A2_LOG_INFO(fmt("%s %s %s", PACKAGE, PACKAGE_VERSION, TARGET));
- A2_LOG_INFO(MSG_LOGGING_STARTED);
-
- if(op->getAsBool(PREF_DISABLE_IPV6)) {
- SocketCore::setProtocolFamily(AF_INET);
- // Get rid of AI_ADDRCONFIG. It causes name resolution error
- // when none of network interface has IPv4 address.
- setDefaultAIFlags(0);
- }
- net::checkAddrconfig();
- // Bind interface
- if(!op->get(PREF_INTERFACE).empty()) {
- std::string iface = op->get(PREF_INTERFACE);
- SocketCore::bindAddress(iface);
- }
- sigset_t mask;
-#ifdef HAVE_SIGACTION
- sigemptyset(&mask);
-#else // !HAVE_SIGACTION
- mask = 0;
-#endif // !HAVE_SIGACTION
-#ifdef SIGPIPE
- util::setGlobalSignalHandler(SIGPIPE, &mask, SIG_IGN, 0);
-#endif
-#ifdef SIGCHLD
- // Avoid to create zombie process when forked child processes are
- // died.
- util::setGlobalSignalHandler(SIGCHLD, &mask, SIG_IGN, 0);
-#endif // SIGCHILD
- std::vector<SharedHandle<RequestGroup> > requestGroups;
- SharedHandle<UriListParser> uriListParser;
-#ifdef ENABLE_BITTORRENT
- if(!op->blank(PREF_TORRENT_FILE)) {
- if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
- showTorrentFile(op->get(PREF_TORRENT_FILE));
- return exitStatus;
- } else {
- createRequestGroupForBitTorrent(requestGroups, op, args,
- op->get(PREF_TORRENT_FILE));
- }
- }
- else
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
- if(!op->blank(PREF_METALINK_FILE)) {
- if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
- showMetalinkFile(op->get(PREF_METALINK_FILE), op);
- return exitStatus;
- } else {
- createRequestGroupForMetalink(requestGroups, op);
- }
- }
- else
-#endif // ENABLE_METALINK
- if(!op->blank(PREF_INPUT_FILE)) {
- if(op->getAsBool(PREF_DEFERRED_INPUT)) {
- uriListParser = openUriListParser(op->get(PREF_INPUT_FILE));
- } else {
- createRequestGroupForUriList(requestGroups, op);
- }
-#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK
- } else if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
- showFiles(args, op);
- return exitStatus;
-#endif // ENABLE_METALINK || ENABLE_METALINK
- } else {
- createRequestGroupForUri(requestGroups, op, args, false, false, true);
- }
-
- // Remove option values which is only valid for URIs specified in
- // command-line. If they are left, because op is used as a template
- // for new RequestGroup(such as created in RPC command), they causes
- // unintentional effect.
- for(SharedHandle<Option> i = op; i; i = i->getParent()) {
- i->remove(PREF_OUT);
- i->remove(PREF_FORCE_SEQUENTIAL);
- i->remove(PREF_INPUT_FILE);
- i->remove(PREF_INDEX_OUT);
- i->remove(PREF_SELECT_FILE);
- i->remove(PREF_PAUSE);
- i->remove(PREF_CHECKSUM);
- i->remove(PREF_GID);
- }
- if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty() &&
- !uriListParser) {
- global::cout()->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD);
- } else {
- exitStatus = MultiUrlRequestInfo(requestGroups, op, getStatCalc(op),
- getSummaryOut(op),
- uriListParser).execute();
+ if(context.reqinfo) {
+ exitStatus = context.reqinfo->execute();
}
return exitStatus;
}
} // namespace aria2
-int main(int argc, char* argv[])
+int main(int argc, char** argv)
{
aria2::error_code::Value r;
try {