2010-04-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

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
pull/1/head
Tatsuhiro Tsujikawa 2010-04-11 14:46:07 +00:00
parent 2e6a517aaa
commit 15bb26cac8
8 changed files with 252 additions and 31 deletions

View File

@ -1,3 +1,13 @@
2010-04-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
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 <t-tujikawa@users.sourceforge.net>
Added aria2.forcePause XML-RPC command.

View File

@ -2,12 +2,12 @@
.\" Title: aria2c
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" 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

View File

@ -3102,16 +3102,30 @@ download without any action which takes time such as contacting
BitTorrent tracker.</p></div>
<div class="paragraph"><p><strong>aria2.pause</strong> <em>gid</em></p></div>
<div class="paragraph"><p>This method pauses the download denoted by <em>gid</em>. <em>gid</em> 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 <strong>aria2.unpause</strong> 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 <strong>aria2.unpause</strong> method.
This method returns GID of paused download.</p></div>
<div class="paragraph"><p><strong>aria2.pauseAll</strong></p></div>
<div class="paragraph"><p>This method is equal to calling <strong>aria2.pause</strong> for every active/waiting
download. This methods returns "OK" for success.</p></div>
<div class="paragraph"><p><strong>aria2.forcePause</strong> <em>pid</em></p></div>
<div class="paragraph"><p>This method pauses the download denoted by <em>gid</em>. This method
behaves just like <strong>aria2.pause</strong> except that this method pauses
download without any action which takes time such as contacting
BitTorrent tracker.</p></div>
<div class="paragraph"><p><strong>aria2.forcePauseAll</strong></p></div>
<div class="paragraph"><p>This method is equal to calling <strong>aria2.forcePause</strong> for every
active/waiting download. This methods returns "OK" for success.</p></div>
<div class="paragraph"><p><strong>aria2.unpause</strong> <em>gid</em></p></div>
<div class="paragraph"><p>This method changes the status of the download denoted by <em>gid</em> from
"paused" to "waiting". This makes the download eligible to restart.
<em>gid</em> is of type string. This method returns GID of unpaused
download.</p></div>
<div class="paragraph"><p><strong>aria2.unpauseAll</strong></p></div>
<div class="paragraph"><p>This method is equal to calling <strong>aria2.unpause</strong> for every active/waiting
download. This methods returns "OK" for success.</p></div>
<div class="paragraph"><p><strong>aria2.tellStatus</strong> <em>gid</em></p></div>
<div class="paragraph"><p>This method returns download progress of the download denoted by
<em>gid</em>. <em>gid</em> is of type string. The response is of type struct and it
@ -3794,7 +3808,7 @@ pprint(r)</tt></pre>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">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.</td>
<td class="content">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.</td>
</tr></table>
</div>
<h4 id="_download_a_file_from_2_different_http_servers">Download a file from 2 different HTTP servers</h4>
@ -3870,7 +3884,7 @@ variables. See <strong>ENVIRONMENT</strong> section.</td>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">To pause a download, press Ctrl-C.
<td class="content">To stop a download, press Ctrl-C.
You can resume the transfer by running aria2c with the same argument in the same
directory.</td>
</tr></table>
@ -3922,7 +3936,7 @@ directory.</td>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">To pause a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.</td>
<td class="content">To stop a download, press Ctrl-C. You can resume the transfer by running aria2c with the same argument in the same directory.</td>
</tr></table>
</div>
<h4 id="_download_using_bittorrent_magnet_uri">Download using BitTorrent Magnet URI</h4>
@ -4174,7 +4188,7 @@ files in the program, then also delete it here.</p></div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2010-04-09 00:32:31 JST
Last updated 2010-04-11 23:42:41 JST
</div>
</div>
</body>

View File

@ -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

View File

@ -62,8 +62,14 @@ XmlRpcMethodFactory::create(const std::string& methodName)
return SharedHandle<XmlRpcMethod>(new PauseXmlRpcMethod());
} else if(methodName == ForcePauseXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new ForcePauseXmlRpcMethod());
} else if(methodName == PauseAllXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new PauseAllXmlRpcMethod());
} else if(methodName == ForcePauseAllXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new ForcePauseAllXmlRpcMethod());
} else if(methodName == UnpauseXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new UnpauseXmlRpcMethod());
} else if(methodName == UnpauseAllXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new UnpauseAllXmlRpcMethod());
} else if(methodName == ForceRemoveXmlRpcMethod::getMethodName()) {
return SharedHandle<XmlRpcMethod>(new ForceRemoveXmlRpcMethod());
} else if(methodName == ChangePositionXmlRpcMethod::getMethodName()) {

View File

@ -348,17 +348,28 @@ BDE ForceRemoveXmlRpcMethod::process
return removeDownload(req, e, true);
}
static void pauseRequestGroup
(const SharedHandle<RequestGroup>& group, bool forcePause)
static bool pauseRequestGroup
(const SharedHandle<RequestGroup>& 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<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
if(group.isNull() || group->isHaltRequested()) {
bool reserved = false;
SharedHandle<RequestGroup> 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<typename InputIterator>
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<SharedHandle<RequestGroup> >& groups =
e->_requestGroupMan->getRequestGroups();
pauseRequestGroups(groups.begin(), groups.end(), false, forcePause);
const std::deque<SharedHandle<RequestGroup> >& 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<SharedHandle<RequestGroup> >& 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<FileEntry>& file)
{
{

View File

@ -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:

View File

@ -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<std::string> uris(vbegin(URIS), vend(URIS));
_option->put(PREF_FORCE_SEQUENTIAL, V_TRUE);
std::vector<SharedHandle<RequestGroup> > 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;