From 15bb26cac82a27aeca37c377679c2821d9ff8a8f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 11 Apr 2010 14:46:07 +0000 Subject: [PATCH] 2010-04-11 Tatsuhiro Tsujikawa Added aria2.pauseAll, aria2.forcePauseAll and aria2.unpauseAll XML-RPC method. * doc/aria2c.1.txt * src/XmlRpcMethodFactory.cc * src/XmlRpcMethodImpl.cc * src/XmlRpcMethodImpl.h * test/XmlRpcMethodTest.cc --- ChangeLog | 10 +++++ doc/aria2c.1 | 28 ++++++++++--- doc/aria2c.1.html | 30 ++++++++++---- doc/aria2c.1.txt | 30 ++++++++++++-- src/XmlRpcMethodFactory.cc | 6 +++ src/XmlRpcMethodImpl.cc | 85 ++++++++++++++++++++++++++++++++------ src/XmlRpcMethodImpl.h | 33 +++++++++++++++ test/XmlRpcMethodTest.cc | 61 +++++++++++++++++++++++++++ 8 files changed, 252 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0242e6a..65f705e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-04-11 Tatsuhiro Tsujikawa + + Added aria2.pauseAll, aria2.forcePauseAll and aria2.unpauseAll + XML-RPC method. + * doc/aria2c.1.txt + * src/XmlRpcMethodFactory.cc + * src/XmlRpcMethodImpl.cc + * src/XmlRpcMethodImpl.h + * test/XmlRpcMethodTest.cc + 2010-04-11 Tatsuhiro Tsujikawa Added aria2.forcePause XML-RPC command. diff --git a/doc/aria2c.1 b/doc/aria2c.1 index f7f5dbaf..f91fd6b5 100644 --- a/doc/aria2c.1 +++ b/doc/aria2c.1 @@ -2,12 +2,12 @@ .\" Title: aria2c .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.75.2 -.\" Date: 04/09/2010 +.\" Date: 04/11/2010 .\" Manual: Aria2 Manual .\" Source: Aria2 1.9.1a .\" Language: English .\" -.TH "ARIA2C" "1" "04/09/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual" +.TH "ARIA2C" "1" "04/11/2010" "Aria2 1\&.9\&.1a" "Aria2 Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2631,12 +2631,28 @@ This method removes the download denoted by \fIgid\fR\&. This method behaves jus .sp \fBaria2\&.pause\fR \fIgid\fR .sp -This method pauses the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The status of paused download becomes "paused" and the download is placed on the first position of waiting queue\&. As long as the status is "paused", the download is not started\&. To change status to "waiting", use \fBaria2\&.unpause\fR method\&. This method returns GID of paused download\&. +This method pauses the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The status of paused download becomes "paused"\&. If the download is active, the download is placed on the first position of waiting queue\&. As long as the status is "paused", the download is not started\&. To change status to "waiting", use \fBaria2\&.unpause\fR method\&. This method returns GID of paused download\&. +.sp +\fBaria2\&.pauseAll\fR +.sp +This method is equal to calling \fBaria2\&.pause\fR for every active/waiting download\&. This methods returns "OK" for success\&. +.sp +\fBaria2\&.forcePause\fR \fIpid\fR +.sp +This method pauses the download denoted by \fIgid\fR\&. This method behaves just like \fBaria2\&.pause\fR except that this method pauses download without any action which takes time such as contacting BitTorrent tracker\&. +.sp +\fBaria2\&.forcePauseAll\fR +.sp +This method is equal to calling \fBaria2\&.forcePause\fR for every active/waiting download\&. This methods returns "OK" for success\&. .sp \fBaria2\&.unpause\fR \fIgid\fR .sp This method changes the status of the download denoted by \fIgid\fR from "paused" to "waiting"\&. This makes the download eligible to restart\&. \fIgid\fR is of type string\&. This method returns GID of unpaused download\&. .sp +\fBaria2\&.unpauseAll\fR +.sp +This method is equal to calling \fBaria2\&.unpause\fR for every active/waiting download\&. This methods returns "OK" for success\&. +.sp \fBaria2\&.tellStatus\fR \fIgid\fR .sp This method returns download progress of the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The response is of type struct and it contains following keys\&. The value type is string\&. @@ -3167,7 +3183,7 @@ aria2 uses 5 connections to download 1 file by default\&. \-s1 limits the number .ps -1 .br .sp -To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. You can change URIs as long as they are pointing to the same file\&. +To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. You can change URIs as long as they are pointing to the same file\&. .sp .5v .RE .RE @@ -3383,7 +3399,7 @@ aria2c \-p \-\-lowest\-speed\-limit=4000 file\&.metalink .ps -1 .br .sp -To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. +To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. .sp .5v .RE .RE @@ -3527,7 +3543,7 @@ aria2c \-\-max\-upload\-limit=40K file\&.torrent .ps -1 .br .sp -To pause a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. +To stop a download, press Ctrl\-C\&. You can resume the transfer by running aria2c with the same argument in the same directory\&. .sp .5v .RE .RE diff --git a/doc/aria2c.1.html b/doc/aria2c.1.html index 7e297cd8..793002b2 100644 --- a/doc/aria2c.1.html +++ b/doc/aria2c.1.html @@ -3102,16 +3102,30 @@ download without any action which takes time such as contacting BitTorrent tracker.

aria2.pause gid

This method pauses the download denoted by gid. gid is of type -string. The status of paused download becomes "paused" and the -download is placed on the first position of waiting queue. As long as -the status is "paused", the download is not started. To change status -to "waiting", use aria2.unpause method. +string. The status of paused download becomes "paused". If the +download is active, the download is placed on the first position of +waiting queue. As long as the status is "paused", the download is not +started. To change status to "waiting", use aria2.unpause method. This method returns GID of paused download.

+

aria2.pauseAll

+

This method is equal to calling aria2.pause for every active/waiting +download. This methods returns "OK" for success.

+

aria2.forcePause pid

+

This method pauses the download denoted by gid. This method +behaves just like aria2.pause except that this method pauses +download without any action which takes time such as contacting +BitTorrent tracker.

+

aria2.forcePauseAll

+

This method is equal to calling aria2.forcePause for every +active/waiting download. This methods returns "OK" for success.

aria2.unpause gid

This method changes the status of the download denoted by gid from "paused" to "waiting". This makes the download eligible to restart. gid is of type string. This method returns GID of unpaused download.

+

aria2.unpauseAll

+

This method is equal to calling aria2.unpause for every active/waiting +download. This methods returns "OK" for success.

aria2.tellStatus gid

This method returns download progress of the download denoted by gid. gid is of type string. The response is of type struct and it @@ -3794,7 +3808,7 @@ pprint(r)

Note
-To pause a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. You can change URIs as long as they are pointing to the same file. +To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. You can change URIs as long as they are pointing to the same file.

Download a file from 2 different HTTP servers

@@ -3870,7 +3884,7 @@ variables. See ENVIRONMENT section.
Note
-To pause a download, press Ctrl-C. +To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. @@ -3922,7 +3936,7 @@ directory.
Note
-To pause a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory. +To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.

Download using BitTorrent Magnet URI

@@ -4174,7 +4188,7 @@ files in the program, then also delete it here.


diff --git a/doc/aria2c.1.txt b/doc/aria2c.1.txt index b111793e..0d13c8b4 100644 --- a/doc/aria2c.1.txt +++ b/doc/aria2c.1.txt @@ -1371,12 +1371,29 @@ BitTorrent tracker. *aria2.pause* 'gid' This method pauses the download denoted by 'gid'. 'gid' is of type -string. The status of paused download becomes "paused" and the -download is placed on the first position of waiting queue. As long as -the status is "paused", the download is not started. To change status -to "waiting", use *aria2.unpause* method. +string. The status of paused download becomes "paused". If the +download is active, the download is placed on the first position of +waiting queue. As long as the status is "paused", the download is not +started. To change status to "waiting", use *aria2.unpause* method. This method returns GID of paused download. +*aria2.pauseAll* + +This method is equal to calling *aria2.pause* for every active/waiting +download. This methods returns "OK" for success. + +*aria2.forcePause* 'pid' + +This method pauses the download denoted by 'gid'. This method +behaves just like *aria2.pause* except that this method pauses +download without any action which takes time such as contacting +BitTorrent tracker. + +*aria2.forcePauseAll* + +This method is equal to calling *aria2.forcePause* for every +active/waiting download. This methods returns "OK" for success. + *aria2.unpause* 'gid' This method changes the status of the download denoted by 'gid' from @@ -1384,6 +1401,11 @@ This method changes the status of the download denoted by 'gid' from 'gid' is of type string. This method returns GID of unpaused download. +*aria2.unpauseAll* + +This method is equal to calling *aria2.unpause* for every active/waiting +download. This methods returns "OK" for success. + *aria2.tellStatus* 'gid' This method returns download progress of the download denoted by diff --git a/src/XmlRpcMethodFactory.cc b/src/XmlRpcMethodFactory.cc index 53fc8507..dbb0e13a 100644 --- a/src/XmlRpcMethodFactory.cc +++ b/src/XmlRpcMethodFactory.cc @@ -62,8 +62,14 @@ XmlRpcMethodFactory::create(const std::string& methodName) return SharedHandle(new PauseXmlRpcMethod()); } else if(methodName == ForcePauseXmlRpcMethod::getMethodName()) { return SharedHandle(new ForcePauseXmlRpcMethod()); + } else if(methodName == PauseAllXmlRpcMethod::getMethodName()) { + return SharedHandle(new PauseAllXmlRpcMethod()); + } else if(methodName == ForcePauseAllXmlRpcMethod::getMethodName()) { + return SharedHandle(new ForcePauseAllXmlRpcMethod()); } else if(methodName == UnpauseXmlRpcMethod::getMethodName()) { return SharedHandle(new UnpauseXmlRpcMethod()); + } else if(methodName == UnpauseAllXmlRpcMethod::getMethodName()) { + return SharedHandle(new UnpauseAllXmlRpcMethod()); } else if(methodName == ForceRemoveXmlRpcMethod::getMethodName()) { return SharedHandle(new ForceRemoveXmlRpcMethod()); } else if(methodName == ChangePositionXmlRpcMethod::getMethodName()) { diff --git a/src/XmlRpcMethodImpl.cc b/src/XmlRpcMethodImpl.cc index 88b71fdc..db03840b 100644 --- a/src/XmlRpcMethodImpl.cc +++ b/src/XmlRpcMethodImpl.cc @@ -348,17 +348,28 @@ BDE ForceRemoveXmlRpcMethod::process return removeDownload(req, e, true); } -static void pauseRequestGroup -(const SharedHandle& group, bool forcePause) +static bool pauseRequestGroup +(const SharedHandle& group, bool reserved, bool forcePause) { - // Call setHaltRequested before setPauseRequested because - // setHaltRequested calls setPauseRequested(false) internally. - if(forcePause) { - group->setForceHaltRequested(true, RequestGroup::USER_REQUEST); + if((reserved && !group->isPauseRequested()) || + (!reserved && + !group->isForceHaltRequested() && + ((forcePause && group->isHaltRequested() && group->isPauseRequested()) || + (!group->isHaltRequested() && !group->isPauseRequested())))) { + if(!reserved) { + // Call setHaltRequested before setPauseRequested because + // setHaltRequested calls setPauseRequested(false) internally. + if(forcePause) { + group->setForceHaltRequested(true, RequestGroup::USER_REQUEST); + } else { + group->setHaltRequested(true, RequestGroup::USER_REQUEST); + } + } + group->setPauseRequested(true); + return true; } else { - group->setHaltRequested(true, RequestGroup::USER_REQUEST); + return false; } - group->setPauseRequested(true); } static BDE pauseDownload @@ -370,15 +381,19 @@ static BDE pauseDownload throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED); } gid_t gid = util::parseLLInt(params[0].s()); - SharedHandle group = findRequestGroup(e->_requestGroupMan, gid); - if(group.isNull() || group->isHaltRequested()) { + bool reserved = false; + SharedHandle group = e->_requestGroupMan->findRequestGroup(gid); + if(group.isNull()) { + reserved = true; + group = e->_requestGroupMan->findReservedGroup(gid); + } + if(!group.isNull() && pauseRequestGroup(group, reserved, forcePause)) { + return createGIDResponse(gid); + } else { throw DL_ABORT_EX (StringFormat("GID#%s cannot be paused now", util::itos(gid).c_str()).str()); - } else { - pauseRequestGroup(group, forcePause); } - return createGIDResponse(gid); } BDE PauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) @@ -391,6 +406,39 @@ BDE ForcePauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) return pauseDownload(req, e, true); } +template +static void pauseRequestGroups +(InputIterator first, InputIterator last, bool reserved, bool forcePause) +{ + for(; first != last; ++first) { + pauseRequestGroup(*first, reserved, forcePause); + } +} + +static BDE pauseAllDownloads +(const XmlRpcRequest& req, DownloadEngine* e, bool forcePause) +{ + const std::deque >& groups = + e->_requestGroupMan->getRequestGroups(); + pauseRequestGroups(groups.begin(), groups.end(), false, forcePause); + const std::deque >& reservedGroups = + e->_requestGroupMan->getReservedGroups(); + pauseRequestGroups(reservedGroups.begin(), reservedGroups.end(), + true, forcePause); + return BDE_OK; +} + +BDE PauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) +{ + return pauseAllDownloads(req, e, false); +} + +BDE ForcePauseAllXmlRpcMethod::process +(const XmlRpcRequest& req, DownloadEngine* e) +{ + return pauseAllDownloads(req, e, true); +} + BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) { const BDE& params = req._params; @@ -411,6 +459,17 @@ BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) return createGIDResponse(gid); } +BDE UnpauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) +{ + const std::deque >& groups = + e->_requestGroupMan->getReservedGroups(); + std::for_each(groups.begin(), groups.end(), + std::bind2nd(mem_fun_sh(&RequestGroup::setPauseRequested), + false)); + e->_requestGroupMan->requestQueueCheck(); + return BDE_OK; +} + static void createUriEntry(BDE& uriList, const SharedHandle& file) { { diff --git a/src/XmlRpcMethodImpl.h b/src/XmlRpcMethodImpl.h index ba9de2bc..159b65fc 100644 --- a/src/XmlRpcMethodImpl.h +++ b/src/XmlRpcMethodImpl.h @@ -106,6 +106,28 @@ public: } }; +class PauseAllXmlRpcMethod:public XmlRpcMethod { +protected: + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); +public: + static const std::string& getMethodName() + { + static std::string methodName = "aria2.pauseAll"; + return methodName; + } +}; + +class ForcePauseAllXmlRpcMethod:public XmlRpcMethod { +protected: + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); +public: + static const std::string& getMethodName() + { + static std::string methodName = "aria2.forcePauseAll"; + return methodName; + } +}; + class UnpauseXmlRpcMethod:public XmlRpcMethod { protected: virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); @@ -117,6 +139,17 @@ public: } }; +class UnpauseAllXmlRpcMethod:public XmlRpcMethod { +protected: + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); +public: + static const std::string& getMethodName() + { + static std::string methodName = "aria2.unpauseAll"; + return methodName; + } +}; + #ifdef ENABLE_BITTORRENT class AddTorrentXmlRpcMethod:public XmlRpcMethod { protected: diff --git a/test/XmlRpcMethodTest.cc b/test/XmlRpcMethodTest.cc index 74aa128e..77f88f06 100644 --- a/test/XmlRpcMethodTest.cc +++ b/test/XmlRpcMethodTest.cc @@ -20,6 +20,7 @@ #include "FeatureConfig.h" #include "util.h" #include "array_fun.h" +#include "download_helper.h" #ifdef ENABLE_BITTORRENT # include "BtRegistry.h" # include "BtRuntime.h" @@ -77,6 +78,7 @@ class XmlRpcMethodTest:public CppUnit::TestFixture { CPPUNIT_TEST(testGetSessionInfo); CPPUNIT_TEST(testChangeUri); CPPUNIT_TEST(testChangeUri_fail); + CPPUNIT_TEST(testPause); CPPUNIT_TEST(testSystemMulticall); CPPUNIT_TEST(testSystemMulticall_fail); CPPUNIT_TEST_SUITE_END(); @@ -139,6 +141,7 @@ public: void testGetSessionInfo(); void testChangeUri(); void testChangeUri_fail(); + void testPause(); void testSystemMulticall(); void testSystemMulticall_fail(); }; @@ -920,6 +923,64 @@ void XmlRpcMethodTest::testGetSessionInfo() res._param["sessionId"].s()); } +void XmlRpcMethodTest::testPause() +{ + const std::string URIS[] = { + "http://url1", + "http://url2", + "http://url3", + }; + std::vector uris(vbegin(URIS), vend(URIS)); + _option->put(PREF_FORCE_SEQUENTIAL, V_TRUE); + std::vector > groups; + createRequestGroupForUri(groups, _option, uris); + CPPUNIT_ASSERT_EQUAL((size_t)3, groups.size()); + _e->_requestGroupMan->addReservedGroup(groups); + { + PauseXmlRpcMethod m; + XmlRpcRequest req(PauseXmlRpcMethod::getMethodName(), BDE::list()); + req._params << std::string("1"); + XmlRpcResponse res = m.execute(req, _e.get()); + CPPUNIT_ASSERT_EQUAL(0, res._code); + } + CPPUNIT_ASSERT(groups[0]->isPauseRequested()); + { + UnpauseXmlRpcMethod m; + XmlRpcRequest req(UnpauseXmlRpcMethod::getMethodName(), BDE::list()); + req._params << std::string("1"); + XmlRpcResponse res = m.execute(req, _e.get()); + CPPUNIT_ASSERT_EQUAL(0, res._code); + } + CPPUNIT_ASSERT(!groups[0]->isPauseRequested()); + { + PauseAllXmlRpcMethod m; + XmlRpcRequest req(PauseAllXmlRpcMethod::getMethodName(), BDE::list()); + XmlRpcResponse res = m.execute(req, _e.get()); + CPPUNIT_ASSERT_EQUAL(0, res._code); + } + for(size_t i = 0; i < groups.size(); ++i) { + CPPUNIT_ASSERT(groups[i]->isPauseRequested()); + } + { + UnpauseAllXmlRpcMethod m; + XmlRpcRequest req(UnpauseAllXmlRpcMethod::getMethodName(), BDE::list()); + XmlRpcResponse res = m.execute(req, _e.get()); + CPPUNIT_ASSERT_EQUAL(0, res._code); + } + for(size_t i = 0; i < groups.size(); ++i) { + CPPUNIT_ASSERT(!groups[i]->isPauseRequested()); + } + { + ForcePauseAllXmlRpcMethod m; + XmlRpcRequest req(ForcePauseAllXmlRpcMethod::getMethodName(), BDE::list()); + XmlRpcResponse res = m.execute(req, _e.get()); + CPPUNIT_ASSERT_EQUAL(0, res._code); + } + for(size_t i = 0; i < groups.size(); ++i) { + CPPUNIT_ASSERT(groups[i]->isPauseRequested()); + } +} + void XmlRpcMethodTest::testSystemMulticall() { SystemMulticallXmlRpcMethod m;