ソースを参照

2009-05-22 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added the ability to execute command when download starts and
	stops. You can also specify command for particular cases such as
	complete/error download.  Added --on-download-start,
	--on-download-stop, --on-download-complete and --on-download-error
	option.
	* src/OptionHandlerFactory.cc
	* src/RequestGroupMan.cc
	* src/prefs.cc
	* src/prefs.h
	* src/usage_text.h
Tatsuhiro Tsujikawa 16 年 前
コミット
48a7e5868f
6 ファイル変更132 行追加0 行削除
  1. 18 0
      ChangeLog
  2. 36 0
      src/OptionHandlerFactory.cc
  3. 43 0
      src/RequestGroupMan.cc
  4. 5 0
      src/prefs.cc
  5. 5 0
      src/prefs.h
  6. 25 0
      src/usage_text.h

+ 18 - 0
ChangeLog

@@ -1,3 +1,21 @@
+2009-05-22  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added the ability to execute command when download starts and
+	stops. You can also specify command for particular cases such as
+	complete/error download.  Added --on-download-start,
+	--on-download-stop, --on-download-complete and --on-download-error
+	option.
+	* src/OptionHandlerFactory.cc
+	* src/RequestGroupMan.cc
+	* src/prefs.cc
+	* src/prefs.h
+	* src/usage_text.h
+
+2009-05-22  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed test error
+	* test/BencodeTest.cc
+
 2009-05-22  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Added unit tests.

+ 36 - 0
src/OptionHandlerFactory.cc

@@ -306,6 +306,42 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_ADVANCED);
     handlers.push_back(op);
   }
+  {
+    SharedHandle<OptionHandler> op(new DefaultOptionHandler
+				   (PREF_ON_DOWNLOAD_COMPLETE,
+				    TEXT_ON_DOWNLOAD_COMPLETE,
+				    NO_DEFAULT_VALUE,
+				    "/path/to/command"));
+    op->addTag(TAG_ADVANCED);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new DefaultOptionHandler
+				   (PREF_ON_DOWNLOAD_ERROR,
+				    TEXT_ON_DOWNLOAD_ERROR,
+				    NO_DEFAULT_VALUE,
+				    "/path/to/command"));
+    op->addTag(TAG_ADVANCED);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new DefaultOptionHandler
+				   (PREF_ON_DOWNLOAD_START,
+				    TEXT_ON_DOWNLOAD_START,
+				    NO_DEFAULT_VALUE,
+				    "/path/to/command"));
+    op->addTag(TAG_ADVANCED);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new DefaultOptionHandler
+				   (PREF_ON_DOWNLOAD_STOP,
+				    TEXT_ON_DOWNLOAD_STOP,
+				    NO_DEFAULT_VALUE,
+				    "/path/to/command"));
+    op->addTag(TAG_ADVANCED);
+    handlers.push_back(op);
+  }
   {
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
 				   (PREF_PARAMETERIZED_URI,

+ 43 - 0
src/RequestGroupMan.cc

@@ -34,6 +34,8 @@
 /* copyright --> */
 #include "RequestGroupMan.h"
 
+#include <unistd.h>
+#include <cstring>
 #include <iomanip>
 #include <sstream>
 #include <ostream>
@@ -188,6 +190,43 @@ bool RequestGroupMan::removeReservedGroup(int32_t gid)
   }
 }
 
+static void executeHook(const std::string& command, int gid)
+{
+  LogFactory::getInstance()->info("Executing user command: %s %d",
+				  command.c_str(), gid);
+  pid_t cpid = fork();
+  if(cpid == -1) {
+    LogFactory::getInstance()->error("fork() failed."
+				     " Cannot execute user command.");
+  } else if(cpid == 0) {
+    execl(command.c_str(), command.c_str(), Util::itos(gid).c_str(), (char*)0);
+    perror(("Could not execute user command: "+command).c_str());
+    _exit(1);
+  }
+}
+
+static void executeStartHook
+(const SharedHandle<RequestGroup>& group, const Option* option)
+{
+  if(!option->blank(PREF_ON_DOWNLOAD_START)) {
+    executeHook(option->get(PREF_ON_DOWNLOAD_START), group->getGID());
+  }
+}
+
+static void executeStopHook
+(const SharedHandle<DownloadResult>& result, const Option* option)
+{
+  if(result->result == DownloadResult::FINISHED &&
+     !option->blank(PREF_ON_DOWNLOAD_COMPLETE)) {
+    executeHook(option->get(PREF_ON_DOWNLOAD_COMPLETE), result->gid);
+  } else if(result->result != DownloadResult::IN_PROGRESS &&
+	    !option->blank(PREF_ON_DOWNLOAD_ERROR)) {
+    executeHook(option->get(PREF_ON_DOWNLOAD_ERROR), result->gid);
+  } else if(!option->blank(PREF_ON_DOWNLOAD_STOP)) {
+    executeHook(option->get(PREF_ON_DOWNLOAD_STOP), result->gid);
+  }
+}
+
 class ProcessStoppedRequestGroup {
 private:
   DownloadEngine* _e;
@@ -251,6 +290,8 @@ public:
       }
       group->releaseRuntimeResource(_e);
       _downloadResults.push_back(group->createDownloadResult());
+
+      executeStopHook(_downloadResults.back(), _e->option);
     }
   }
 };
@@ -381,6 +422,7 @@ void RequestGroupMan::fillRequestGroupFromReserver(DownloadEngine* e)
       _requestGroups.push_back(groupToAdd);
       ++count;
       e->addCommand(commands);
+      executeStartHook(groupToAdd, e->option);
     } catch(RecoverableException& ex) {
       _logger->error(EX_EXCEPTION_CAUGHT, ex);
       groupToAdd->releaseRuntimeResource(e);
@@ -404,6 +446,7 @@ void RequestGroupMan::getInitialCommands(std::deque<Command*>& commands,
 	configureRequestGroup(*itr);
 	createInitialCommand(*itr, commands, e,
 			     _option->getAsBool(PREF_USE_HEAD));
+	executeStartHook(*itr, e->option);
 	++itr;
       } else {
 	_reservedGroups.push_front((*itr));

+ 5 - 0
src/prefs.cc

@@ -167,6 +167,11 @@ const std::string PREF_REUSE_URI("reuse-uri");
 const std::string PREF_XML_RPC_USER("xml-rpc-user");
 // value: string
 const std::string PREF_XML_RPC_PASSWD("xml-rpc-passwd");
+// value: string
+const std::string PREF_ON_DOWNLOAD_START("on-download-start");
+const std::string PREF_ON_DOWNLOAD_STOP("on-download-stop");
+const std::string PREF_ON_DOWNLOAD_COMPLETE("on-download-complete");
+const std::string PREF_ON_DOWNLOAD_ERROR("on-download-error");
 
 /**
  * FTP related preferences

+ 5 - 0
src/prefs.h

@@ -171,6 +171,11 @@ extern const std::string PREF_REUSE_URI;
 extern const std::string PREF_XML_RPC_USER;
 // value: string
 extern const std::string PREF_XML_RPC_PASSWD;
+// value: string
+extern const std::string PREF_ON_DOWNLOAD_START;
+extern const std::string PREF_ON_DOWNLOAD_STOP;
+extern const std::string PREF_ON_DOWNLOAD_COMPLETE;
+extern const std::string PREF_ON_DOWNLOAD_ERROR;
 
 /**
  * FTP related preferences

+ 25 - 0
src/usage_text.h

@@ -523,3 +523,28 @@ _(" --bt-tracker-interval=SEC    Set the interval in seconds between tracker\n"\
   "                              tracker. If 0 is set, aria2 determines interval\n"\
   "                              based on the response of tracker and the download\n"\
   "                              progress.")
+#define TEXT_ON_DOWNLOAD_COMPLETE \
+_(" --on-download-complete=COMMAND Set the command to be executed when download\n"\
+  "                              completes.\n"\
+  "                              See --on-download-start option for the\n"\
+  "                              requirement of COMMAND.\n"\
+  "                              See also --on-download-stop option.")
+#define TEXT_ON_DOWNLOAD_START \
+_(" --on-download-start=COMMAND  Set the command to be executed when download\n"\
+  "                              starts up. COMMAND must take just one argument and\n"\
+  "                              GID is passed to COMMAND as a first argument.")
+#define TEXT_ON_DOWNLOAD_ERROR \
+_(" --on-download-error=COMMAND  Set the command to be executed when download\n"\
+  "                              aborts due to error.\n"\
+  "                              See --on-download-start option for the\n"\
+  "                              requirement of COMMAND.\n"\
+  "                              See also --on-download-stop option.")
+#define TEXT_ON_DOWNLOAD_STOP \
+_(" --on-download-stop=COMMAND   Set the command to be executed when download\n"\
+  "                              stops. You can override the command to be executed\n"\
+  "                              for particular download result using\n"\
+  "                              --on-download-complete and --on-download-error. If\n"\
+  "                              they are specified, command specified in this\n"\
+  "                              option is not executed.\n"\
+  "                              See --on-download-start option for the\n"\
+  "                              requirement of COMMAND.")