Add changePosition API

pull/89/head
Tatsuhiro Tsujikawa 2013-05-15 00:50:55 +09:00
parent 4f5d26a0c7
commit cef6db17ba
8 changed files with 113 additions and 55 deletions

View File

@ -42,13 +42,9 @@
#include <vector>
#include <algorithm>
namespace aria2 {
#include <aria2/aria2.h>
enum A2_HOW {
A2_POS_SET,
A2_POS_CUR,
A2_POS_END
};
namespace aria2 {
template<typename SeqType, typename ValueType, typename ReferenceType,
typename PointerType, typename SeqIteratorType>
@ -539,15 +535,15 @@ public:
}
// Moves element with |key| to the specified position. If |how| is
// A2_POS_CUR, the element is moved to the position |offset|
// relative to the current position. If |how| is A2_POS_SET, the
// element is moved to the position |offset|. If |how| is
// A2_POS_END, the element is moved to the position |offset|
// OFFSET_MODE_CUR, the element is moved to the position |offset|
// relative to the current position. If |how| is OFFSET_MODE_SET,
// the element is moved to the position |offset|. If |how| is
// OFFSET_MODE_END, the element is moved to the position |offset|
// relative to the end of the list. This function returns the
// position the elment is moved to if it succeeds, or -1 if no
// element with |key| is found or |how| is invalid. Complexity:
// O(N)
ssize_t move(KeyType key, ssize_t offset, A2_HOW how)
ssize_t move(KeyType key, ssize_t offset, OffsetMode how)
{
typename IndexType::iterator idxent = index_.find(key);
if(idxent == index_.end()) {
@ -562,16 +558,16 @@ public:
ssize_t xp = std::distance(seq_.begin(), x);
ssize_t size = index_.size();
ssize_t dest;
if(how == A2_POS_CUR) {
if(how == OFFSET_MODE_CUR) {
if(offset > 0) {
dest = std::min(xp+offset, static_cast<ssize_t>(size-1));
} else {
dest = std::max(xp+offset, static_cast<ssize_t>(0));
}
} else {
if(how == A2_POS_END) {
if(how == OFFSET_MODE_END) {
dest = std::min(size-1+offset, size-1);
} else if(how == A2_POS_SET) {
} else if(how == OFFSET_MODE_SET) {
dest = std::min(offset, size-1);
} else {
return -1;

View File

@ -192,7 +192,7 @@ SharedHandle<RequestGroup> RequestGroupMan::findGroup(a2_gid_t gid) const
}
size_t RequestGroupMan::changeReservedGroupPosition
(a2_gid_t gid, int pos, A2_HOW how)
(a2_gid_t gid, int pos, OffsetMode how)
{
ssize_t dest = reservedGroups_.move(gid, pos, how);
if(dest == -1) {

View File

@ -180,7 +180,7 @@ public:
// beginning or the end of the queue respectively. Returns the
// destination position.
size_t changeReservedGroupPosition(a2_gid_t gid, int pos,
A2_HOW how);
OffsetMode how);
bool removeReservedGroup(a2_gid_t gid);

View File

@ -1301,13 +1301,13 @@ SharedHandle<ValueBase> ChangePositionRpcMethod::process
a2_gid_t gid = str2Gid(gidParam);
int pos = posParam->i();
const std::string& howStr = howParam->s();
A2_HOW how;
OffsetMode how;
if(howStr == "POS_SET") {
how = A2_POS_SET;
how = OFFSET_MODE_SET;
} else if(howStr == "POS_CUR") {
how = A2_POS_CUR;
how = OFFSET_MODE_CUR;
} else if(howStr == "POS_END") {
how = A2_POS_END;
how = OFFSET_MODE_END;
} else {
throw DL_ABORT_EX("Illegal argument.");
}

View File

@ -367,6 +367,18 @@ int unpauseDownload(Session* session, const A2Gid& gid)
return 0;
}
int changePosition(Session* session, const A2Gid& gid, int pos, OffsetMode how)
{
const SharedHandle<DownloadEngine>& e =
session->context->reqinfo->getDownloadEngine();
try {
return e->getRequestGroupMan()->changeReservedGroupPosition(gid, pos, how);
} catch(RecoverableException& e) {
A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
return -1;
}
}
std::vector<A2Gid> getActiveDownload(Session* session)
{
const SharedHandle<DownloadEngine>& e =

View File

@ -361,6 +361,56 @@ int pauseDownload(Session* session, const A2Gid& gid, bool force = false);
*/
int unpauseDownload(Session* session, const A2Gid& gid);
/**
* @enum
*
* Constants how to re-position a download.
*/
enum OffsetMode {
/**
* Moves the download to a position relative to the beginning of the
* queue.
*/
OFFSET_MODE_SET,
/**
* Moves the download to a position relative to the current
* position.
*/
OFFSET_MODE_CUR,
/**
* Moves the download to a position relative to the end of the
* queue.
*/
OFFSET_MODE_END
};
/**
* @function
*
* Changes the position of the download denoted by the |gid|. if it is
* in :c:macro:`DOWNLOAD_WAITING` or :c:macro:`DOWNLOAD_PAUSED` state.
* If the |how| is :c:macro:`OFFSET_MODE_SET`, it moves the download
* to a position |pos| relative to the beginning of the queue. If the
* |how| is :c:macro:`OFFSET_MODE_CUR`, it moves the download to a
* position |pos| relative to the current position. If the |how| is
* :c:macro:`OFFSET_MODE_END`, it moves the download to a position
* |pos| relative to the end of the queue. If the destination position
* is less than 0 or beyond the end of the queue, it moves the
* download to the beginning or the end of the queue respectively. The
* response is the destination position on success.
*
* For example, if the download having GID gid is placed in position
* 3, ``changePosition(gid, -1, OFFSET_MODE_CUR)`` will change its
* position to 2. Additional call ``changePosition(gid, 0,
* OFFSET_MODE_SET)`` will change its position to 0 (the beginning of
* the queue).
*
* This function returns the final destination position of this
* download, or negative error code.
*/
int changePosition(Session* session, const A2Gid& gid, int pos,
OffsetMode how);
/**
* @function
*

View File

@ -148,77 +148,77 @@ void IndexedListTest::testMove()
for(int i = 0; i < 5; ++i) {
list.push_back(i, &a[i]);
}
CPPUNIT_ASSERT_EQUAL((ssize_t)-1, list.move(100, 0, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)-1, list.move(100, 0, OFFSET_MODE_SET));
int a0[] = {0,1,2,3,4};
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(0, 0, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(0, 0, OFFSET_MODE_SET));
LIST_CHECK(a0, list);
int a1[] = {0,2,3,4,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(1, 4, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(1, 4, OFFSET_MODE_SET));
LIST_CHECK(a1, list);
int a2[] = {0,3,4,2,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(2, 3, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(2, 3, OFFSET_MODE_SET));
LIST_CHECK(a2, list);
int a3[] = {0,2,3,4,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)1, list.move(2, 1, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)1, list.move(2, 1, OFFSET_MODE_SET));
LIST_CHECK(a3, list);
int a4[] = {1,0,2,3,4};
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(1, 0, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(1, 0, OFFSET_MODE_SET));
LIST_CHECK(a4, list);
int a5[] = {1,0,3,2,4};
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(3, 2, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(3, 2, OFFSET_MODE_SET));
LIST_CHECK(a5, list);
int a6[] = {1,3,2,4,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(0, 5, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(0, 5, OFFSET_MODE_SET));
LIST_CHECK(a6, list);
int a7[] = {3,1,2,4,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)1, list.move(1, 1, A2_POS_CUR));
CPPUNIT_ASSERT_EQUAL((ssize_t)1, list.move(1, 1, OFFSET_MODE_CUR));
LIST_CHECK(a7, list);
int a8[] = {3,2,4,1,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(1, 2, A2_POS_CUR));
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(1, 2, OFFSET_MODE_CUR));
LIST_CHECK(a8, list);
int a9[] = {3,2,1,4,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(1, -1, A2_POS_CUR));
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(1, -1, OFFSET_MODE_CUR));
LIST_CHECK(a9, list);
int a10[] = {1,3,2,4,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(1, -1233, A2_POS_CUR));
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(1, -1233, OFFSET_MODE_CUR));
LIST_CHECK(a10, list);
int a11[] = {3,2,4,0,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(1, 8733, A2_POS_CUR));
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(1, 8733, OFFSET_MODE_CUR));
LIST_CHECK(a11, list);
int a12[] = {3,2,4,0,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(0, -1, A2_POS_END));
CPPUNIT_ASSERT_EQUAL((ssize_t)3, list.move(0, -1, OFFSET_MODE_END));
LIST_CHECK(a12, list);
int a13[] = {3,2,0,4,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(0, -2, A2_POS_END));
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(0, -2, OFFSET_MODE_END));
LIST_CHECK(a13, list);
int a14[] = {0,3,2,4,1};
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(0, -8733, A2_POS_END));
CPPUNIT_ASSERT_EQUAL((ssize_t)0, list.move(0, -8733, OFFSET_MODE_END));
LIST_CHECK(a14, list);
int a15[] = {0,2,4,1,3};
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(3, 0, A2_POS_END));
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(3, 0, OFFSET_MODE_END));
LIST_CHECK(a15, list);
int a16[] = {2,4,1,3,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(0, 1000, A2_POS_END));
CPPUNIT_ASSERT_EQUAL((ssize_t)4, list.move(0, 1000, OFFSET_MODE_END));
LIST_CHECK(a16, list);
int a17[] = {2,1,4,3,0};
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(4, 2, A2_POS_SET));
CPPUNIT_ASSERT_EQUAL((ssize_t)2, list.move(4, 2, OFFSET_MODE_SET));
LIST_CHECK(a17, list);
}

View File

@ -158,57 +158,57 @@ void RequestGroupManTest::testChangeReservedGroupPosition()
CPPUNIT_ASSERT_EQUAL
((size_t)0, rm.changeReservedGroupPosition(gs[0]->getGID(),
0, A2_POS_SET));
0, OFFSET_MODE_SET));
CPPUNIT_ASSERT_EQUAL
((size_t)1, rm.changeReservedGroupPosition(gs[0]->getGID(),
1, A2_POS_SET));
1, OFFSET_MODE_SET));
CPPUNIT_ASSERT_EQUAL
((size_t)3, rm.changeReservedGroupPosition(gs[0]->getGID(),
10,A2_POS_SET));
10,OFFSET_MODE_SET));
CPPUNIT_ASSERT_EQUAL
((size_t)0, rm.changeReservedGroupPosition(gs[0]->getGID(),
-10, A2_POS_SET));
-10, OFFSET_MODE_SET));
CPPUNIT_ASSERT_EQUAL
((size_t)1, rm.changeReservedGroupPosition(gs[1]->getGID(),
0, A2_POS_CUR));
0, OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)2, rm.changeReservedGroupPosition(gs[1]->getGID(),
1, A2_POS_CUR));
1, OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)1, rm.changeReservedGroupPosition(gs[1]->getGID(),
-1,A2_POS_CUR));
-1,OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)0, rm.changeReservedGroupPosition(gs[1]->getGID(),
-10, A2_POS_CUR));
-10, OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)1, rm.changeReservedGroupPosition(gs[1]->getGID(),
1, A2_POS_CUR));
1, OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)3, rm.changeReservedGroupPosition(gs[1]->getGID(),
10, A2_POS_CUR));
10, OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)1, rm.changeReservedGroupPosition(gs[1]->getGID(),
-2,A2_POS_CUR));
-2,OFFSET_MODE_CUR));
CPPUNIT_ASSERT_EQUAL
((size_t)3, rm.changeReservedGroupPosition(gs[3]->getGID(),
0, A2_POS_END));
0, OFFSET_MODE_END));
CPPUNIT_ASSERT_EQUAL
((size_t)2, rm.changeReservedGroupPosition(gs[3]->getGID(),
-1,A2_POS_END));
-1,OFFSET_MODE_END));
CPPUNIT_ASSERT_EQUAL
((size_t)0, rm.changeReservedGroupPosition(gs[3]->getGID(),
-10, A2_POS_END));
-10, OFFSET_MODE_END));
CPPUNIT_ASSERT_EQUAL
((size_t)3, rm.changeReservedGroupPosition(gs[3]->getGID(),
10, A2_POS_END));
10, OFFSET_MODE_END));
CPPUNIT_ASSERT_EQUAL((size_t)4, rm.getReservedGroups().size());
try {
rm.changeReservedGroupPosition(GroupId::create()->getNumericId(),
0, A2_POS_CUR);
0, OFFSET_MODE_CUR);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success