From f9c6c0ccd8bc3b262774f15071e9402c50c93ad4 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 17 Jan 2010 09:50:38 +0000 Subject: [PATCH] 2010-01-17 Tatsuhiro Tsujikawa 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 --- ChangeLog | 12 ++++++ doc/aria2c.1 | 18 ++++++-- doc/aria2c.1.html | 41 +++++++++++------- doc/aria2c.1.txt | 45 +++++++++++++------- src/XmlRpcMethodImpl.cc | 80 +++++++++++----------------------- src/XmlRpcMethodImpl.h | 92 ++++++++++++++++++++++++++++++++++++++-- test/XmlRpcMethodTest.cc | 33 ++++++++++++++ 7 files changed, 228 insertions(+), 93 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11477d50..6997e74c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-01-17 Tatsuhiro Tsujikawa + + 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 Added --human-readable option. This option, when true is given, diff --git a/doc/aria2c.1 b/doc/aria2c.1 index 41054f20..e7402fbb 100644 --- a/doc/aria2c.1 +++ b/doc/aria2c.1 @@ -2376,15 +2376,27 @@ seeder .sp \fBaria2\&.tellActive\fR .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 \fBaria2\&.tellWaiting\fR \fIoffset, num\fR .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 \fBaria2\&.tellStopped\fR \fIoffset, num\fR .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 \fBaria2\&.changePosition\fR \fIgid, pos, how\fR .sp diff --git a/doc/aria2c.1.html b/doc/aria2c.1.html index 3785fd4f..83db2a77 100644 --- a/doc/aria2c.1.html +++ b/doc/aria2c.1.html @@ -3031,25 +3031,34 @@ seeder

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 aria2.tellStatus method.

aria2.tellWaiting offset, num

-

This method returns the list of waiting download in the range of -[offset, offset+num). offset is of type integer and specifies -the offset from the download waiting at the front. num 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 aria2.tellStatus method.

+

This method returns the list of waiting download. offset is of type +integer and specifies the offset from the download waiting at the +front. num is of type integer and specifies the number of downloads +to be returned.

+

If offset is a positive integer, this method returns downloads in the +range of [offset, offset+num).

+

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

-

This method returns the list of stopped download in the range of -[offset, offset+num). offset is of type integer and specifies -the offset from the oldest download. num 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 -aria2.tellStatus method.

+

This method returns the list of stopped download. offset is of type +integer and specifies the offset from the oldest download. num is of +type integer and specifies the number of downloads to be returned.

+

offset and num have the same semantics as aria2.tellWaiting +method.

+

The response is of type array and its element is the same struct +returned by aria2.tellStatus method.

aria2.changePosition gid, pos, how

This method changes the position of the download denoted by gid. pos is of type integer. how is of type string. If how is @@ -3587,7 +3596,7 @@ files in the program, then also delete it here.


diff --git a/doc/aria2c.1.txt b/doc/aria2c.1.txt index 8c992b87..212310cd 100644 --- a/doc/aria2c.1.txt +++ b/doc/aria2c.1.txt @@ -1352,29 +1352,44 @@ seeder:: *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 *aria2.tellStatus* method. *aria2.tellWaiting* 'offset, num' -This method returns the list of waiting download in the range of -['offset', 'offset'+'num'). 'offset' is of type integer and specifies -the offset from the download waiting at the front. 'num' 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 *aria2.tellStatus* method. +This method returns the list of waiting download. 'offset' is of type +integer and specifies the offset from the download waiting at the +front. 'num' is of type integer and specifies the number of downloads +to be returned. + +If offset is a positive integer, this method returns downloads in the +range of ['offset', 'offset'+'num'). + +'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' -This method returns the list of stopped download in the range of -['offset', 'offset'+'num'). 'offset' is of type integer and specifies -the offset from the oldest download. 'num' 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 -*aria2.tellStatus* method. +This method returns the list of stopped download. 'offset' is of type +integer and specifies the offset from the oldest download. 'num' is of +type integer and specifies the number of downloads to be returned. + +'offset' and 'num' have the same semantics as *aria2.tellWaiting* +method. + +The response is of type array and its element is the same struct +returned by *aria2.tellStatus* method. *aria2.changePosition* 'gid, pos, how' diff --git a/src/XmlRpcMethodImpl.cc b/src/XmlRpcMethodImpl.cc index a9be47c8..92f03328 100644 --- a/src/XmlRpcMethodImpl.cc +++ b/src/XmlRpcMethodImpl.cc @@ -586,73 +586,43 @@ BDE TellActiveXmlRpcMethod::process return list; } -template -static std::pair -getPaginationRange -(const XmlRpcRequest& req, InputIterator first, InputIterator last) +template +void AbstractPaginationXmlRpcMethod::checkPaginationParams +(const BDE& params) const { - const BDE& params = req._params; assert(params.isList()); - if(params.size() != 2 || !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."); } - - 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 XmlRpcRequest& req, DownloadEngine* e) +const std::deque >& +TellWaitingXmlRpcMethod::getItems(DownloadEngine* e) const { - const std::deque >& waitings = - e->_requestGroupMan->getReservedGroups(); - std::pair >::const_iterator, - std::deque >::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; + return e->_requestGroupMan->getReservedGroups(); } -BDE TellStoppedXmlRpcMethod::process -(const XmlRpcRequest& req, DownloadEngine* e) +void TellWaitingXmlRpcMethod::createEntry +(BDE& entryDict, const SharedHandle& item, + DownloadEngine* e) const { - const std::deque >& stopped = - e->_requestGroupMan->getDownloadResults(); - std::pair >::const_iterator, - std::deque >::const_iterator> range = - getPaginationRange(req, stopped.begin(), stopped.end()); - BDE list = BDE::list(); - for(; range.first != range.second; ++range.first) { - BDE entryDict = BDE::dict(); - gatherStoppedDownload(entryDict, *range.first); - list << entryDict; - } - return list; + entryDict[KEY_STATUS] = BDE_WAITING; + gatherProgress(entryDict, item, e); +} + +const std::deque >& +TellStoppedXmlRpcMethod::getItems(DownloadEngine* e) const +{ + return e->_requestGroupMan->getDownloadResults(); +} + +void TellStoppedXmlRpcMethod::createEntry +(BDE& entryDict, const SharedHandle& item, + DownloadEngine* e) const +{ + gatherStoppedDownload(entryDict, item); } BDE PurgeDownloadResultXmlRpcMethod::process diff --git a/src/XmlRpcMethodImpl.h b/src/XmlRpcMethodImpl.h index 108378ab..5eb576f1 100644 --- a/src/XmlRpcMethodImpl.h +++ b/src/XmlRpcMethodImpl.h @@ -37,6 +37,12 @@ #include "XmlRpcMethod.h" +#include +#include + +#include "BDE.h" +#include "XmlRpcRequest.h" + namespace aria2 { class DownloadResult; @@ -160,9 +166,81 @@ public: } }; -class TellWaitingXmlRpcMethod:public XmlRpcMethod { +template +class AbstractPaginationXmlRpcMethod:public XmlRpcMethod { +private: + template + std::pair + 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: - 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 >& items = getItems(e); + std::pair >::const_iterator, + typename std::deque >::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 >& + getItems(DownloadEngine* e) const = 0; + + virtual void createEntry + (BDE& entryDict, const SharedHandle& item, DownloadEngine* e) const = 0; +}; + +class TellWaitingXmlRpcMethod: + public AbstractPaginationXmlRpcMethod { +protected: + virtual const std::deque >& + getItems(DownloadEngine* e) const; + + virtual void createEntry + (BDE& entryDict, const SharedHandle& item, + DownloadEngine* e) const; public: static const std::string& getMethodName() { @@ -171,9 +249,15 @@ public: } }; -class TellStoppedXmlRpcMethod:public XmlRpcMethod { +class TellStoppedXmlRpcMethod: + public AbstractPaginationXmlRpcMethod { protected: - virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); + virtual const std::deque >& + getItems(DownloadEngine* e) const; + + virtual void createEntry + (BDE& entryDict, const SharedHandle& item, + DownloadEngine* e) const; public: static const std::string& getMethodName() { diff --git a/test/XmlRpcMethodTest.cc b/test/XmlRpcMethodTest.cc index 3d3b2e31..d610a811 100644 --- a/test/XmlRpcMethodTest.cc +++ b/test/XmlRpcMethodTest.cc @@ -608,6 +608,39 @@ void XmlRpcMethodTest::testTellWaiting() #else //!ENABLE_BITTORRENT CPPUNIT_ASSERT_EQUAL((size_t)2, res._param.size()); #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()