2010-01-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Now offset argument in aria2.tellWaiting and aria2.tellStopped
	accepts a negative integer.  'offset' == -1 points last download
	in the waiting queue and 'offset' == -2 points the download before
	the last download, and so on. The downloads in the response are in
	reversed order.
	* doc/aria2c.1.txt
	* src/XmlRpcMethodImpl.cc
	* src/XmlRpcMethodImpl.h
	* test/XmlRpcMethodTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-01-17 09:50:38 +00:00
parent c0308e1ea4
commit f9c6c0ccd8
7 changed files with 228 additions and 93 deletions

View File

@ -1,3 +1,15 @@
2010-01-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Now offset argument in aria2.tellWaiting and aria2.tellStopped
accepts a negative integer. 'offset' == -1 points last download
in the waiting queue and 'offset' == -2 points the download before
the last download, and so on. The downloads in the response are in
reversed order.
* doc/aria2c.1.txt
* src/XmlRpcMethodImpl.cc
* src/XmlRpcMethodImpl.h
* test/XmlRpcMethodTest.cc
2010-01-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2010-01-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --human-readable option. This option, when true is given, Added --human-readable option. This option, when true is given,

View File

@ -2376,15 +2376,27 @@ seeder
.sp .sp
\fBaria2\&.tellActive\fR \fBaria2\&.tellActive\fR
.sp .sp
This method returns the list of active downloads\&. The respose is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&. This method returns the list of active downloads\&. The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
.sp .sp
\fBaria2\&.tellWaiting\fR \fIoffset, num\fR \fBaria2\&.tellWaiting\fR \fIoffset, num\fR
.sp .sp
This method returns the list of waiting download in the range of [\fIoffset\fR, \fIoffset\fR+\fInum\fR)\&. \fIoffset\fR is of type integer and specifies the offset from the download waiting at the front\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&. For example, imagine that three downloads "A","B" and "C" are waiting in this order\&. aria2\&.tellWaiting(0, 1) returns "A"\&. aria2\&.tellWaiting(1, 2) returns "B" and "C"\&. The respose is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&. This method returns the list of waiting download\&. \fIoffset\fR is of type integer and specifies the offset from the download waiting at the front\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&.
.sp
If offset is a positive integer, this method returns downloads in the range of [\fIoffset\fR, \fIoffset\fR+\fInum\fR)\&.
.sp
\fIoffset\fR can be a negative integer\&. \fIoffset\fR == \-1 points last download in the waiting queue and \fIoffset\fR == \-2 points the download before the last download, and so on\&. The downloads in the response are in reversed order\&.
.sp
For example, imagine that three downloads "A","B" and "C" are waiting in this order\&. aria2\&.tellWaiting(0, 1) returns ["A"]\&. aria2\&.tellWaiting(1, 2) returns ["B", "C"]\&. aria2\&.tellWaiting(\-1, 2) returns ["C", "B"]\&.
.sp
The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
.sp .sp
\fBaria2\&.tellStopped\fR \fIoffset, num\fR \fBaria2\&.tellStopped\fR \fIoffset, num\fR
.sp .sp
This method returns the list of stopped download in the range of [\fIoffset\fR, \fIoffset\fR+\fInum\fR)\&. \fIoffset\fR is of type integer and specifies the offset from the oldest download\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&. The respose is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&. This method returns the list of stopped download\&. \fIoffset\fR is of type integer and specifies the offset from the oldest download\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&.
.sp
\fIoffset\fR and \fInum\fR have the same semantics as \fBaria2\&.tellWaiting\fR method\&.
.sp
The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
.sp .sp
\fBaria2\&.changePosition\fR \fIgid, pos, how\fR \fBaria2\&.changePosition\fR \fIgid, pos, how\fR
.sp .sp

View File

@ -3031,25 +3031,34 @@ seeder
</dd> </dd>
</dl></div> </dl></div>
<div class="paragraph"><p><strong>aria2.tellActive</strong></p></div> <div class="paragraph"><p><strong>aria2.tellActive</strong></p></div>
<div class="paragraph"><p>This method returns the list of active downloads. The respose is of <div class="paragraph"><p>This method returns the list of active downloads. The response is of
type array and its element is the same struct returned by type array and its element is the same struct returned by
<strong>aria2.tellStatus</strong> method.</p></div> <strong>aria2.tellStatus</strong> method.</p></div>
<div class="paragraph"><p><strong>aria2.tellWaiting</strong> <em>offset, num</em></p></div> <div class="paragraph"><p><strong>aria2.tellWaiting</strong> <em>offset, num</em></p></div>
<div class="paragraph"><p>This method returns the list of waiting download in the range of <div class="paragraph"><p>This method returns the list of waiting download. <em>offset</em> is of type
[<em>offset</em>, <em>offset</em>+<em>num</em>). <em>offset</em> is of type integer and specifies integer and specifies the offset from the download waiting at the
the offset from the download waiting at the front. <em>num</em> is of type front. <em>num</em> is of type integer and specifies the number of downloads
integer and specifies the number of downloads to be returned. For to be returned.</p></div>
example, imagine that three downloads "A","B" and "C" are waiting in <div class="paragraph"><p>If offset is a positive integer, this method returns downloads in the
this order. aria2.tellWaiting(0, 1) returns "A". aria2.tellWaiting(1, range of [<em>offset</em>, <em>offset</em>+<em>num</em>).</p></div>
2) returns "B" and "C". The respose is of type array and its element <div class="paragraph"><p><em>offset</em> can be a negative integer. <em>offset</em> == -1 points last
is the same struct returned by <strong>aria2.tellStatus</strong> method.</p></div> download in the waiting queue and <em>offset</em> == -2 points the download
before the last download, and so on. The downloads in the response are
in reversed order.</p></div>
<div class="paragraph"><p>For example, imagine that three downloads "A","B" and "C" are waiting
in this order. aria2.tellWaiting(0, 1) returns
["A"]. aria2.tellWaiting(1, 2) returns ["B", "C"].
aria2.tellWaiting(-1, 2) returns ["C", "B"].</p></div>
<div class="paragraph"><p>The response is of type array and its element is the same struct
returned by <strong>aria2.tellStatus</strong> method.</p></div>
<div class="paragraph"><p><strong>aria2.tellStopped</strong> <em>offset, num</em></p></div> <div class="paragraph"><p><strong>aria2.tellStopped</strong> <em>offset, num</em></p></div>
<div class="paragraph"><p>This method returns the list of stopped download in the range of <div class="paragraph"><p>This method returns the list of stopped download. <em>offset</em> is of type
[<em>offset</em>, <em>offset</em>+<em>num</em>). <em>offset</em> is of type integer and specifies integer and specifies the offset from the oldest download. <em>num</em> is of
the offset from the oldest download. <em>num</em> is of type integer and type integer and specifies the number of downloads to be returned.</p></div>
specifies the number of downloads to be returned. The respose is of <div class="paragraph"><p><em>offset</em> and <em>num</em> have the same semantics as <strong>aria2.tellWaiting</strong>
type array and its element is the same struct returned by method.</p></div>
<strong>aria2.tellStatus</strong> method.</p></div> <div class="paragraph"><p>The response is of type array and its element is the same struct
returned by <strong>aria2.tellStatus</strong> method.</p></div>
<div class="paragraph"><p><strong>aria2.changePosition</strong> <em>gid, pos, how</em></p></div> <div class="paragraph"><p><strong>aria2.changePosition</strong> <em>gid, pos, how</em></p></div>
<div class="paragraph"><p>This method changes the position of the download denoted by <div class="paragraph"><p>This method changes the position of the download denoted by
<em>gid</em>. <em>pos</em> is of type integer. <em>how</em> is of type string. If <em>how</em> is <em>gid</em>. <em>pos</em> is of type integer. <em>how</em> is of type string. If <em>how</em> is
@ -3587,7 +3596,7 @@ files in the program, then also delete it here.</p></div>
<div id="footnotes"><hr /></div> <div id="footnotes"><hr /></div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2010-01-17 16:21:53 JST Last updated 2010-01-17 18:47:03 JST
</div> </div>
</div> </div>
</body> </body>

View File

@ -1352,29 +1352,44 @@ seeder::
*aria2.tellActive* *aria2.tellActive*
This method returns the list of active downloads. The respose is of This method returns the list of active downloads. The response is of
type array and its element is the same struct returned by type array and its element is the same struct returned by
*aria2.tellStatus* method. *aria2.tellStatus* method.
*aria2.tellWaiting* 'offset, num' *aria2.tellWaiting* 'offset, num'
This method returns the list of waiting download in the range of This method returns the list of waiting download. 'offset' is of type
['offset', 'offset'+'num'). 'offset' is of type integer and specifies integer and specifies the offset from the download waiting at the
the offset from the download waiting at the front. 'num' is of type front. 'num' is of type integer and specifies the number of downloads
integer and specifies the number of downloads to be returned. For to be returned.
example, imagine that three downloads "A","B" and "C" are waiting in
this order. aria2.tellWaiting(0, 1) returns "A". aria2.tellWaiting(1, If offset is a positive integer, this method returns downloads in the
2) returns "B" and "C". The respose is of type array and its element range of ['offset', 'offset'+'num').
is the same struct returned by *aria2.tellStatus* method.
'offset' can be a negative integer. 'offset' == -1 points last
download in the waiting queue and 'offset' == -2 points the download
before the last download, and so on. The downloads in the response are
in reversed order.
For example, imagine that three downloads "A","B" and "C" are waiting
in this order. aria2.tellWaiting(0, 1) returns
["A"]. aria2.tellWaiting(1, 2) returns ["B", "C"].
aria2.tellWaiting(-1, 2) returns ["C", "B"].
The response is of type array and its element is the same struct
returned by *aria2.tellStatus* method.
*aria2.tellStopped* 'offset, num' *aria2.tellStopped* 'offset, num'
This method returns the list of stopped download in the range of This method returns the list of stopped download. 'offset' is of type
['offset', 'offset'+'num'). 'offset' is of type integer and specifies integer and specifies the offset from the oldest download. 'num' is of
the offset from the oldest download. 'num' is of type integer and type integer and specifies the number of downloads to be returned.
specifies the number of downloads to be returned. The respose is of
type array and its element is the same struct returned by 'offset' and 'num' have the same semantics as *aria2.tellWaiting*
*aria2.tellStatus* method. method.
The response is of type array and its element is the same struct
returned by *aria2.tellStatus* method.
*aria2.changePosition* 'gid, pos, how' *aria2.changePosition* 'gid, pos, how'

View File

@ -586,73 +586,43 @@ BDE TellActiveXmlRpcMethod::process
return list; return list;
} }
template<typename InputIterator> template<typename T>
static std::pair<InputIterator, InputIterator> void AbstractPaginationXmlRpcMethod<T>::checkPaginationParams
getPaginationRange (const BDE& params) const
(const XmlRpcRequest& req, InputIterator first, InputIterator last)
{ {
const BDE& params = req._params;
assert(params.isList()); assert(params.isList());
if(params.size() != 2 || if(params.size() != 2 ||
!params[0].isInteger() || !params[1].isInteger() || !params[0].isInteger() || !params[1].isInteger() ||
params[0].i() < 0 || params[1].i() < 0) { params[1].i() < 0) {
throw DL_ABORT_EX("Invalid argument. Specify offset and num in integer."); throw DL_ABORT_EX("Invalid argument. Specify offset and num in integer.");
} }
size_t offset = params[0].i();
size_t num = params[1].i();
BDE list = BDE::list();
size_t size = std::distance(first, last);
if(size <= offset) {
return std::make_pair(last, last);
}
size_t lastDistance;
if(size < offset+num) {
lastDistance = size;
} else {
lastDistance = offset+num;
}
last = first;
std::advance(first, offset);
std::advance(last, lastDistance);
return std::make_pair(first, last);
} }
BDE TellWaitingXmlRpcMethod::process const std::deque<SharedHandle<RequestGroup> >&
(const XmlRpcRequest& req, DownloadEngine* e) TellWaitingXmlRpcMethod::getItems(DownloadEngine* e) const
{ {
const std::deque<SharedHandle<RequestGroup> >& waitings = return e->_requestGroupMan->getReservedGroups();
e->_requestGroupMan->getReservedGroups();
std::pair<std::deque<SharedHandle<RequestGroup> >::const_iterator,
std::deque<SharedHandle<RequestGroup> >::const_iterator> range =
getPaginationRange(req, waitings.begin(), waitings.end());
BDE list = BDE::list();
for(; range.first != range.second; ++range.first) {
BDE entryDict = BDE::dict();
entryDict[KEY_STATUS] = BDE_WAITING;
gatherProgress(entryDict, *range.first, e);
list << entryDict;
}
return list;
} }
BDE TellStoppedXmlRpcMethod::process void TellWaitingXmlRpcMethod::createEntry
(const XmlRpcRequest& req, DownloadEngine* e) (BDE& entryDict, const SharedHandle<RequestGroup>& item,
DownloadEngine* e) const
{ {
const std::deque<SharedHandle<DownloadResult> >& stopped = entryDict[KEY_STATUS] = BDE_WAITING;
e->_requestGroupMan->getDownloadResults(); gatherProgress(entryDict, item, e);
std::pair<std::deque<SharedHandle<DownloadResult> >::const_iterator, }
std::deque<SharedHandle<DownloadResult> >::const_iterator> range =
getPaginationRange(req, stopped.begin(), stopped.end()); const std::deque<SharedHandle<DownloadResult> >&
BDE list = BDE::list(); TellStoppedXmlRpcMethod::getItems(DownloadEngine* e) const
for(; range.first != range.second; ++range.first) { {
BDE entryDict = BDE::dict(); return e->_requestGroupMan->getDownloadResults();
gatherStoppedDownload(entryDict, *range.first); }
list << entryDict;
} void TellStoppedXmlRpcMethod::createEntry
return list; (BDE& entryDict, const SharedHandle<DownloadResult>& item,
DownloadEngine* e) const
{
gatherStoppedDownload(entryDict, item);
} }
BDE PurgeDownloadResultXmlRpcMethod::process BDE PurgeDownloadResultXmlRpcMethod::process

View File

@ -37,6 +37,12 @@
#include "XmlRpcMethod.h" #include "XmlRpcMethod.h"
#include <deque>
#include <algorithm>
#include "BDE.h"
#include "XmlRpcRequest.h"
namespace aria2 { namespace aria2 {
class DownloadResult; class DownloadResult;
@ -160,9 +166,81 @@ public:
} }
}; };
class TellWaitingXmlRpcMethod:public XmlRpcMethod { template<typename T>
class AbstractPaginationXmlRpcMethod:public XmlRpcMethod {
private:
template<typename InputIterator>
std::pair<InputIterator, InputIterator>
getPaginationRange
(ssize_t offset, size_t num, InputIterator first, InputIterator last)
{
size_t size = std::distance(first, last);
if(offset < 0) {
ssize_t tempoffset = offset+size;
if(tempoffset < 0) {
return std::make_pair(last, last);
}
offset = tempoffset-(num-1);
if(offset < 0) {
offset = 0;
num = tempoffset+1;
}
} else if(size <= (size_t)offset) {
return std::make_pair(last, last);
}
BDE list = BDE::list();
size_t lastDistance;
if(size < offset+num) {
lastDistance = size;
} else {
lastDistance = offset+num;
}
last = first;
std::advance(first, offset);
std::advance(last, lastDistance);
return std::make_pair(first, last);
}
void checkPaginationParams(const BDE& params) const;
protected: protected:
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e)
{
const BDE& params = req._params;
checkPaginationParams(params);
ssize_t offset = params[0].i();
size_t num = params[1].i();
const std::deque<SharedHandle<T> >& items = getItems(e);
std::pair<typename std::deque<SharedHandle<T> >::const_iterator,
typename std::deque<SharedHandle<T> >::const_iterator> range =
getPaginationRange(offset, num, items.begin(), items.end());
BDE list = BDE::list();
for(; range.first != range.second; ++range.first) {
BDE entryDict = BDE::dict();
createEntry(entryDict, *range.first, e);
list << entryDict;
}
if(offset < 0) {
std::reverse(list.listBegin(), list.listEnd());
}
return list;
}
virtual const std::deque<SharedHandle<T> >&
getItems(DownloadEngine* e) const = 0;
virtual void createEntry
(BDE& entryDict, const SharedHandle<T>& item, DownloadEngine* e) const = 0;
};
class TellWaitingXmlRpcMethod:
public AbstractPaginationXmlRpcMethod<RequestGroup> {
protected:
virtual const std::deque<SharedHandle<RequestGroup> >&
getItems(DownloadEngine* e) const;
virtual void createEntry
(BDE& entryDict, const SharedHandle<RequestGroup>& item,
DownloadEngine* e) const;
public: public:
static const std::string& getMethodName() static const std::string& getMethodName()
{ {
@ -171,9 +249,15 @@ public:
} }
}; };
class TellStoppedXmlRpcMethod:public XmlRpcMethod { class TellStoppedXmlRpcMethod:
public AbstractPaginationXmlRpcMethod<DownloadResult> {
protected: protected:
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); virtual const std::deque<SharedHandle<DownloadResult> >&
getItems(DownloadEngine* e) const;
virtual void createEntry
(BDE& entryDict, const SharedHandle<DownloadResult>& item,
DownloadEngine* e) const;
public: public:
static const std::string& getMethodName() static const std::string& getMethodName()
{ {

View File

@ -608,6 +608,39 @@ void XmlRpcMethodTest::testTellWaiting()
#else //!ENABLE_BITTORRENT #else //!ENABLE_BITTORRENT
CPPUNIT_ASSERT_EQUAL((size_t)2, res._param.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, res._param.size());
#endif // !ENABLE_BITTORRENT #endif // !ENABLE_BITTORRENT
// negative offset
req = XmlRpcRequest(TellWaitingXmlRpcMethod::getMethodName(), BDE::list());
req._params << BDE((int64_t)-1);
req._params << BDE((int64_t)2);
res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(0, res._code);
CPPUNIT_ASSERT_EQUAL((size_t)2, res._param.size());
#ifdef ENABLE_BITTORRENT
CPPUNIT_ASSERT_EQUAL(std::string("4"), res._param[0]["gid"].s());
CPPUNIT_ASSERT_EQUAL(std::string("3"), res._param[1]["gid"].s());
#else // !ENABLE_BITTORRENT
CPPUNIT_ASSERT_EQUAL(std::string("3"), res._param[0]["gid"].s());
CPPUNIT_ASSERT_EQUAL(std::string("2"), res._param[1]["gid"].s());
#endif // !ENABLE_BITTORRENT
// negative offset and size < num
req._params[1] = BDE((int64_t)100);
res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(0, res._code);
#ifdef ENABLE_BITTORRENT
CPPUNIT_ASSERT_EQUAL((size_t)4, res._param.size());
#else // !ENABLE_BITTORRENT
CPPUNIT_ASSERT_EQUAL((size_t)3, res._param.size());
#endif // !ENABLE_BITTORRENT
// nagative offset and normalized offset < 0
req._params[0] = BDE((int64_t)-5);
res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(0, res._code);
CPPUNIT_ASSERT_EQUAL((size_t)0, res._param.size());
// nagative offset and normalized offset == 0
req._params[0] = BDE((int64_t)-4);
res = m.execute(req, _e.get());
CPPUNIT_ASSERT_EQUAL(0, res._code);
CPPUNIT_ASSERT_EQUAL((size_t)1, res._param.size());
} }
void XmlRpcMethodTest::testTellWaiting_fail() void XmlRpcMethodTest::testTellWaiting_fail()