mirror of https://github.com/aria2/aria2
2010-03-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added changeUri XML-RPC method. This method removes/adds URIs dynamically. * doc/aria2c.1.txt * src/AbstractCommand.cc * src/DownloadContext.cc * src/DownloadContext.h * src/FileEntry.cc * src/FileEntry.h * src/Request.cc * src/Request.h * src/RequestGroup.cc * src/RequestGroupMan.cc * src/XmlRpcMethodFactory.cc * src/XmlRpcMethodImpl.cc * src/XmlRpcMethodImpl.h * test/FileEntryTest.cc * test/XmlRpcMethodTest.ccpull/1/head
parent
61b2b88c29
commit
b1713e6373
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
||||||
|
2010-03-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
|
Added changeUri XML-RPC method. This method removes/adds URIs
|
||||||
|
dynamically.
|
||||||
|
* doc/aria2c.1.txt
|
||||||
|
* src/AbstractCommand.cc
|
||||||
|
* src/DownloadContext.cc
|
||||||
|
* src/DownloadContext.h
|
||||||
|
* src/FileEntry.cc
|
||||||
|
* src/FileEntry.h
|
||||||
|
* src/Request.cc
|
||||||
|
* src/Request.h
|
||||||
|
* src/RequestGroup.cc
|
||||||
|
* src/RequestGroupMan.cc
|
||||||
|
* src/XmlRpcMethodFactory.cc
|
||||||
|
* src/XmlRpcMethodImpl.cc
|
||||||
|
* src/XmlRpcMethodImpl.h
|
||||||
|
* test/FileEntryTest.cc
|
||||||
|
* test/XmlRpcMethodTest.cc
|
||||||
|
|
||||||
2010-03-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
2010-03-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||||
|
|
||||||
Rewritten copy ctor of RequestSlot to use initialization list.
|
Rewritten copy ctor of RequestSlot to use initialization list.
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
.\" Title: aria2c
|
.\" Title: aria2c
|
||||||
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||||
.\" Date: 02/25/2010
|
.\" Date: 03/06/2010
|
||||||
.\" Manual: Aria2 Manual
|
.\" Manual: Aria2 Manual
|
||||||
.\" Source: Aria2 1.9.0a
|
.\" Source: Aria2 1.9.0a
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "ARIA2C" "1" "02/25/2010" "Aria2 1\&.9\&.0a" "Aria2 Manual"
|
.TH "ARIA2C" "1" "03/06/2010" "Aria2 1\&.9\&.0a" "Aria2 Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
|
@ -2467,6 +2467,10 @@ This method changes the position of the download denoted by \fIgid\fR\&. \fIpos\
|
||||||
.sp
|
.sp
|
||||||
For example, if GID#1 is placed in position 3, aria2\&.changePosition(1, \-1, POS_CUR) will change its position to 2\&. Additional aria2\&.changePosition(1, 0, POS_SET) will change its position to 0(the beginning of the queue)\&.
|
For example, if GID#1 is placed in position 3, aria2\&.changePosition(1, \-1, POS_CUR) will change its position to 2\&. Additional aria2\&.changePosition(1, 0, POS_SET) will change its position to 0(the beginning of the queue)\&.
|
||||||
.sp
|
.sp
|
||||||
|
\fBaria2\&.changeUri\fR \fIgid, fileIndex, delUris, addUris[, position]\fR
|
||||||
|
.sp
|
||||||
|
This method removes URIs in \fIdelUris\fR from and appends URIs in \fIaddUris\fR to download denoted by \fIgid\fR\&. \fIdelUris\fR and \fIaddUris\fR are list of string\&. A download can contain multiple files and URIs are attached to each file\&. \fIfileIndex\fR is used to select which file to remove/attach given URIs\&. \fIposition\fR is used to specify where URIs are inserted in the existing waiting URI list\&. \fIposition\fR is 0\-based\&. When \fIposition\fR is omitted, URIs are appended to the back of the list\&. This method first execute removal and then addition\&. \fIposition\fR is the position after URIs are removed, not the position when this method is called\&. When removing URI, if same URIs exist in download, only one of them is removed for each URI in \fIdelUris\fR\&. In other words, there are three URIs "http://example\&.org/aria2" and you want remove them all, you have to specify (at least) 3 "http://example\&.org/aria2" in \fIdelUris\fR\&. This method returns a list which contains 2 integers\&. The first integer is the number of URIs deleted\&. The second integer is the number of URIs added\&.
|
||||||
|
.sp
|
||||||
\fBaria2\&.getOption\fR \fIgid\fR
|
\fBaria2\&.getOption\fR \fIgid\fR
|
||||||
.sp
|
.sp
|
||||||
This method returns options of the download denoted by \fIgid\fR\&. The response is of type struct\&. Its key is the name of option\&. The value type is string\&.
|
This method returns options of the download denoted by \fIgid\fR\&. The response is of type struct\&. Its key is the name of option\&. The value type is string\&.
|
||||||
|
|
|
@ -3176,6 +3176,24 @@ destination position.</p></div>
|
||||||
-1, POS_CUR) will change its position to 2. Additional
|
-1, POS_CUR) will change its position to 2. Additional
|
||||||
aria2.changePosition(1, 0, POS_SET) will change its position to 0(the
|
aria2.changePosition(1, 0, POS_SET) will change its position to 0(the
|
||||||
beginning of the queue).</p></div>
|
beginning of the queue).</p></div>
|
||||||
|
<div class="paragraph"><p><strong>aria2.changeUri</strong> <em>gid, fileIndex, delUris, addUris[, position]</em></p></div>
|
||||||
|
<div class="paragraph"><p>This method removes URIs in <em>delUris</em> from and appends URIs in
|
||||||
|
<em>addUris</em> to download denoted by <em>gid</em>. <em>delUris</em> and <em>addUris</em> are
|
||||||
|
list of string. A download can contain multiple files and URIs are
|
||||||
|
attached to each file. <em>fileIndex</em> is used to select which file to
|
||||||
|
remove/attach given URIs. <em>position</em> is used to specify where URIs
|
||||||
|
are inserted in the existing waiting URI list. <em>position</em> is
|
||||||
|
0-based. When <em>position</em> is omitted, URIs are appended to the back of
|
||||||
|
the list. This method first execute removal and then
|
||||||
|
addition. <em>position</em> is the position after URIs are removed, not the
|
||||||
|
position when this method is called. When removing URI, if same URIs
|
||||||
|
exist in download, only one of them is removed for each URI in
|
||||||
|
<em>delUris</em>. In other words, there are three URIs
|
||||||
|
"http://example.org/aria2" and you want remove them all, you have to
|
||||||
|
specify (at least) 3 "http://example.org/aria2" in <em>delUris</em>. This
|
||||||
|
method returns a list which contains 2 integers. The first integer is
|
||||||
|
the number of URIs deleted. The second integer is the number of URIs
|
||||||
|
added.</p></div>
|
||||||
<div class="paragraph"><p><strong>aria2.getOption</strong> <em>gid</em></p></div>
|
<div class="paragraph"><p><strong>aria2.getOption</strong> <em>gid</em></p></div>
|
||||||
<div class="paragraph"><p>This method returns options of the download denoted by <em>gid</em>. The
|
<div class="paragraph"><p>This method returns options of the download denoted by <em>gid</em>. The
|
||||||
response is of type struct. Its key is the name of option. The value type
|
response is of type struct. Its key is the name of option. The value type
|
||||||
|
@ -3722,7 +3740,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-02-23 23:01:01 JST
|
Last updated 2010-03-06 23:18:27 JST
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1465,6 +1465,26 @@ For example, if GID#1 is placed in position 3, aria2.changePosition(1,
|
||||||
aria2.changePosition(1, 0, POS_SET) will change its position to 0(the
|
aria2.changePosition(1, 0, POS_SET) will change its position to 0(the
|
||||||
beginning of the queue).
|
beginning of the queue).
|
||||||
|
|
||||||
|
*aria2.changeUri* 'gid, fileIndex, delUris, addUris[, position]'
|
||||||
|
|
||||||
|
This method removes URIs in 'delUris' from and appends URIs in
|
||||||
|
'addUris' to download denoted by 'gid'. 'delUris' and 'addUris' are
|
||||||
|
list of string. A download can contain multiple files and URIs are
|
||||||
|
attached to each file. 'fileIndex' is used to select which file to
|
||||||
|
remove/attach given URIs. 'position' is used to specify where URIs
|
||||||
|
are inserted in the existing waiting URI list. 'position' is
|
||||||
|
0-based. When 'position' is omitted, URIs are appended to the back of
|
||||||
|
the list. This method first execute removal and then
|
||||||
|
addition. 'position' is the position after URIs are removed, not the
|
||||||
|
position when this method is called. When removing URI, if same URIs
|
||||||
|
exist in download, only one of them is removed for each URI in
|
||||||
|
'delUris'. In other words, there are three URIs
|
||||||
|
"http://example.org/aria2" and you want remove them all, you have to
|
||||||
|
specify (at least) 3 "http://example.org/aria2" in 'delUris'. This
|
||||||
|
method returns a list which contains 2 integers. The first integer is
|
||||||
|
the number of URIs deleted. The second integer is the number of URIs
|
||||||
|
added.
|
||||||
|
|
||||||
*aria2.getOption* 'gid'
|
*aria2.getOption* 'gid'
|
||||||
|
|
||||||
This method returns options of the download denoted by 'gid'. The
|
This method returns options of the download denoted by 'gid'. The
|
||||||
|
|
|
@ -107,6 +107,14 @@ bool AbstractCommand::execute() {
|
||||||
//logger->debug("CUID#%d - finished.", cuid);
|
//logger->debug("CUID#%d - finished.", cuid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if(!req.isNull() && req->removalRequested()) {
|
||||||
|
if(logger->debug()) {
|
||||||
|
logger->debug
|
||||||
|
("CUID#%d - Discard original URI=%s because it is requested.",
|
||||||
|
cuid, req->getUrl().c_str());
|
||||||
|
}
|
||||||
|
return prepareForRetry(0);
|
||||||
|
}
|
||||||
// TODO it is not needed to check other PeerStats every time.
|
// TODO it is not needed to check other PeerStats every time.
|
||||||
// Find faster Request when no segment is available.
|
// Find faster Request when no segment is available.
|
||||||
if(!req.isNull() && _fileEntry->countPooledRequest() > 0 &&
|
if(!req.isNull() && _fileEntry->countPooledRequest() > 0 &&
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "FileEntry.h"
|
#include "FileEntry.h"
|
||||||
#include "StringFormat.h"
|
#include "StringFormat.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "wallclock.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ DownloadContext::DownloadContext(size_t pieceLength,
|
||||||
_knowsTotalLength(true),
|
_knowsTotalLength(true),
|
||||||
_ownerRequestGroup(0),
|
_ownerRequestGroup(0),
|
||||||
_downloadStartTime(0),
|
_downloadStartTime(0),
|
||||||
_downloadStopTime(_downloadStartTime)
|
_downloadStopTime(0)
|
||||||
{
|
{
|
||||||
SharedHandle<FileEntry> fileEntry
|
SharedHandle<FileEntry> fileEntry
|
||||||
(new FileEntry(util::escapePath(path), totalLength, 0));
|
(new FileEntry(util::escapePath(path), totalLength, 0));
|
||||||
|
@ -67,12 +68,12 @@ DownloadContext::DownloadContext(size_t pieceLength,
|
||||||
|
|
||||||
void DownloadContext::resetDownloadStartTime()
|
void DownloadContext::resetDownloadStartTime()
|
||||||
{
|
{
|
||||||
_downloadStartTime.reset();
|
_downloadStartTime = global::wallclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadContext::resetDownloadStopTime()
|
void DownloadContext::resetDownloadStopTime()
|
||||||
{
|
{
|
||||||
_downloadStopTime.reset();
|
_downloadStopTime = global::wallclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t DownloadContext::calculateSessionTime() const
|
int64_t DownloadContext::calculateSessionTime() const
|
||||||
|
|
|
@ -233,6 +233,11 @@ public:
|
||||||
|
|
||||||
void resetDownloadStopTime();
|
void resetDownloadStopTime();
|
||||||
|
|
||||||
|
const Time& getDownloadStopTime() const
|
||||||
|
{
|
||||||
|
return _downloadStopTime;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t calculateSessionTime() const;
|
int64_t calculateSessionTime() const;
|
||||||
|
|
||||||
// Returns FileEntry at given offset. SharedHandle<FileEntry>() is
|
// Returns FileEntry at given offset. SharedHandle<FileEntry>() is
|
||||||
|
|
|
@ -218,7 +218,9 @@ void FileEntry::storePool(const SharedHandle<Request>& request)
|
||||||
void FileEntry::poolRequest(const SharedHandle<Request>& request)
|
void FileEntry::poolRequest(const SharedHandle<Request>& request)
|
||||||
{
|
{
|
||||||
removeRequest(request);
|
removeRequest(request);
|
||||||
storePool(request);
|
if(!request->removalRequested()) {
|
||||||
|
storePool(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileEntry::removeRequest(const SharedHandle<Request>& request)
|
bool FileEntry::removeRequest(const SharedHandle<Request>& request)
|
||||||
|
@ -330,4 +332,49 @@ void FileEntry::releaseRuntimeResource()
|
||||||
_uriResults.clear();
|
_uriResults.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename InputIterator, typename T>
|
||||||
|
static InputIterator findRequestByUri
|
||||||
|
(InputIterator first, InputIterator last, const T& uri)
|
||||||
|
{
|
||||||
|
for(; first != last; ++first) {
|
||||||
|
if(!(*first)->removalRequested() && (*first)->getUrl() == uri) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileEntry::removeUri(const std::string& uri)
|
||||||
|
{
|
||||||
|
std::deque<std::string>::iterator itr =
|
||||||
|
std::find(_spentUris.begin(), _spentUris.end(), uri);
|
||||||
|
if(itr == _spentUris.end()) {
|
||||||
|
itr = std::find(_uris.begin(), _uris.end(), uri);
|
||||||
|
if(itr == _uris.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
_uris.erase(itr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_spentUris.erase(itr);
|
||||||
|
SharedHandle<Request> req;
|
||||||
|
std::deque<SharedHandle<Request> >::iterator riter =
|
||||||
|
findRequestByUri(_inFlightRequests.begin(), _inFlightRequests.end(), uri);
|
||||||
|
if(riter == _inFlightRequests.end()) {
|
||||||
|
riter = findRequestByUri(_requestPool.begin(), _requestPool.end(), uri);
|
||||||
|
if(riter == _requestPool.end()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
req = *riter;
|
||||||
|
_requestPool.erase(riter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req = *riter;
|
||||||
|
}
|
||||||
|
req->requestRemoval();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -129,15 +129,43 @@ public:
|
||||||
return _spentUris;
|
return _spentUris;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUris(const std::vector<std::string>& uris)
|
size_t setUris(const std::vector<std::string>& uris)
|
||||||
{
|
{
|
||||||
_uris = std::deque<std::string>(uris.begin(), uris.end());
|
_uris.clear();
|
||||||
|
return addUris(uris.begin(), uris.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
void addUris(InputIterator first, InputIterator last)
|
size_t addUris(InputIterator first, InputIterator last)
|
||||||
{
|
{
|
||||||
_uris.insert(_uris.end(), first, last);
|
size_t count = 0;
|
||||||
|
for(; first != last; ++first) {
|
||||||
|
if(addUri(*first)) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addUri(const std::string& uri)
|
||||||
|
{
|
||||||
|
if(Request().setUrl(uri)) {
|
||||||
|
_uris.push_back(uri);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insertUri(const std::string& uri, size_t pos)
|
||||||
|
{
|
||||||
|
if(Request().setUrl(uri)) {
|
||||||
|
pos = std::min(pos, _uris.size());
|
||||||
|
_uris.insert(_uris.begin()+pos, uri);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts _uris and _spentUris into uris.
|
// Inserts _uris and _spentUris into uris.
|
||||||
|
@ -234,6 +262,8 @@ public:
|
||||||
{
|
{
|
||||||
return _originalName;
|
return _originalName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool removeUri(const std::string& uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the first FileEntry which isRequested() method returns
|
// Returns the first FileEntry which isRequested() method returns
|
||||||
|
|
|
@ -63,7 +63,8 @@ Request::Request():
|
||||||
_maxPipelinedRequest(1),
|
_maxPipelinedRequest(1),
|
||||||
_method(METHOD_GET),
|
_method(METHOD_GET),
|
||||||
_hasPassword(false),
|
_hasPassword(false),
|
||||||
_ipv6LiteralAddress(false)
|
_ipv6LiteralAddress(false),
|
||||||
|
_removalRequested(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static std::string removeFragment(const std::string& url)
|
static std::string removeFragment(const std::string& url)
|
||||||
|
|
|
@ -88,6 +88,8 @@ private:
|
||||||
|
|
||||||
SharedHandle<PeerStat> _peerStat;
|
SharedHandle<PeerStat> _peerStat;
|
||||||
|
|
||||||
|
bool _removalRequested;
|
||||||
|
|
||||||
bool parseUrl(const std::string& url);
|
bool parseUrl(const std::string& url);
|
||||||
public:
|
public:
|
||||||
Request();
|
Request();
|
||||||
|
@ -204,6 +206,16 @@ public:
|
||||||
|
|
||||||
const SharedHandle<PeerStat>& initPeerStat();
|
const SharedHandle<PeerStat>& initPeerStat();
|
||||||
|
|
||||||
|
void requestRemoval()
|
||||||
|
{
|
||||||
|
_removalRequested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool removalRequested() const
|
||||||
|
{
|
||||||
|
return _removalRequested;
|
||||||
|
}
|
||||||
|
|
||||||
static const std::string METHOD_GET;
|
static const std::string METHOD_GET;
|
||||||
static const std::string METHOD_HEAD;
|
static const std::string METHOD_HEAD;
|
||||||
|
|
||||||
|
|
|
@ -991,6 +991,9 @@ bool RequestGroup::needsFileAllocation() const
|
||||||
|
|
||||||
DownloadResultHandle RequestGroup::createDownloadResult() const
|
DownloadResultHandle RequestGroup::createDownloadResult() const
|
||||||
{
|
{
|
||||||
|
if(_logger->debug()) {
|
||||||
|
_logger->debug("GID#%d - Creating DownloadResult.", _gid);
|
||||||
|
}
|
||||||
uint64_t sessionDownloadLength = 0;
|
uint64_t sessionDownloadLength = 0;
|
||||||
|
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
|
|
|
@ -336,6 +336,16 @@ public:
|
||||||
void operator()(const SharedHandle<RequestGroup>& group)
|
void operator()(const SharedHandle<RequestGroup>& group)
|
||||||
{
|
{
|
||||||
if(group->getNumCommand() == 0) {
|
if(group->getNumCommand() == 0) {
|
||||||
|
SharedHandle<DownloadContext> dctx = group->getDownloadContext();
|
||||||
|
// DownloadContext::resetDownloadStopTime() is only called when
|
||||||
|
// download completed. If
|
||||||
|
// DownloadContext::getDownloadStopTime().isZero() is true, then
|
||||||
|
// there is a possibility that the download is error or
|
||||||
|
// in-progress and resetDownloadStopTime() is not called. So
|
||||||
|
// call it here.
|
||||||
|
if(dctx->getDownloadStopTime().isZero()) {
|
||||||
|
dctx->resetDownloadStopTime();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
group->closeFile();
|
group->closeFile();
|
||||||
if(group->downloadFinished()) {
|
if(group->downloadFinished()) {
|
||||||
|
|
|
@ -79,6 +79,8 @@ XmlRpcMethodFactory::create(const std::string& methodName)
|
||||||
return SharedHandle<XmlRpcMethod>(new TellStoppedXmlRpcMethod());
|
return SharedHandle<XmlRpcMethod>(new TellStoppedXmlRpcMethod());
|
||||||
} else if(methodName == GetOptionXmlRpcMethod::getMethodName()) {
|
} else if(methodName == GetOptionXmlRpcMethod::getMethodName()) {
|
||||||
return SharedHandle<XmlRpcMethod>(new GetOptionXmlRpcMethod());
|
return SharedHandle<XmlRpcMethod>(new GetOptionXmlRpcMethod());
|
||||||
|
} else if(methodName == ChangeUriXmlRpcMethod::getMethodName()) {
|
||||||
|
return SharedHandle<XmlRpcMethod>(new ChangeUriXmlRpcMethod());
|
||||||
} else if(methodName == ChangeOptionXmlRpcMethod::getMethodName()) {
|
} else if(methodName == ChangeOptionXmlRpcMethod::getMethodName()) {
|
||||||
return SharedHandle<XmlRpcMethod>(new ChangeOptionXmlRpcMethod());
|
return SharedHandle<XmlRpcMethod>(new ChangeOptionXmlRpcMethod());
|
||||||
} else if(methodName == GetGlobalOptionXmlRpcMethod::getMethodName()) {
|
} else if(methodName == GetGlobalOptionXmlRpcMethod::getMethodName()) {
|
||||||
|
|
|
@ -851,6 +851,67 @@ BDE GetSessionInfoXmlRpcMethod::process
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BDE ChangeUriXmlRpcMethod::process
|
||||||
|
(const XmlRpcRequest& req, DownloadEngine* e)
|
||||||
|
{
|
||||||
|
const BDE& params = req._params;
|
||||||
|
assert(params.isList());
|
||||||
|
|
||||||
|
if(params.size() < 4 ||
|
||||||
|
!params[0].isString() || !params[1].isInteger() ||
|
||||||
|
!params[2].isList() || !params[3].isList() ||
|
||||||
|
params[1].i() < 0) {
|
||||||
|
throw DL_ABORT_EX("Bad request");
|
||||||
|
}
|
||||||
|
size_t pos = 0;
|
||||||
|
bool posGiven = false;
|
||||||
|
getPosParam(params, 4, posGiven, pos);
|
||||||
|
|
||||||
|
int32_t gid = util::parseInt(params[0].s());
|
||||||
|
size_t index = params[1].i();
|
||||||
|
const BDE& deluris = params[2];
|
||||||
|
const BDE& adduris = params[3];
|
||||||
|
SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
|
||||||
|
if(group.isNull()) {
|
||||||
|
throw DL_ABORT_EX
|
||||||
|
(StringFormat("Cannot remove URIs from GID#%d", gid).str());
|
||||||
|
}
|
||||||
|
SharedHandle<DownloadContext> dctx = group->getDownloadContext();
|
||||||
|
const std::vector<SharedHandle<FileEntry> >& files = dctx->getFileEntries();
|
||||||
|
if(files.size() <= index) {
|
||||||
|
throw DL_ABORT_EX(StringFormat("fileIndex is out of range").str());
|
||||||
|
}
|
||||||
|
SharedHandle<FileEntry> s = files[index];
|
||||||
|
size_t delcount = 0;
|
||||||
|
for(BDE::List::const_iterator i = deluris.listBegin(),
|
||||||
|
eoi = deluris.listEnd(); i != eoi; ++i) {
|
||||||
|
if(s->removeUri((*i).s())) {
|
||||||
|
++delcount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t addcount = 0;
|
||||||
|
if(posGiven) {
|
||||||
|
for(BDE::List::const_iterator i = adduris.listBegin(),
|
||||||
|
eoi = adduris.listEnd(); i != eoi; ++i) {
|
||||||
|
if(s->insertUri((*i).s(), pos)) {
|
||||||
|
++addcount;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(BDE::List::const_iterator i = adduris.listBegin(),
|
||||||
|
eoi = adduris.listEnd(); i != eoi; ++i) {
|
||||||
|
if(s->addUri((*i).s())) {
|
||||||
|
++addcount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BDE res = BDE::list();
|
||||||
|
res << delcount;
|
||||||
|
res << addcount;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
BDE SystemMulticallXmlRpcMethod::process
|
BDE SystemMulticallXmlRpcMethod::process
|
||||||
(const XmlRpcRequest& req, DownloadEngine* e)
|
(const XmlRpcRequest& req, DownloadEngine* e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -341,6 +341,17 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ChangeUriXmlRpcMethod:public XmlRpcMethod {
|
||||||
|
protected:
|
||||||
|
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
|
||||||
|
public:
|
||||||
|
static const std::string& getMethodName()
|
||||||
|
{
|
||||||
|
static std::string methodName = "aria2.changeUri";
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GetSessionInfoXmlRpcMethod:public XmlRpcMethod {
|
class GetSessionInfoXmlRpcMethod:public XmlRpcMethod {
|
||||||
protected:
|
protected:
|
||||||
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
|
virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e);
|
||||||
|
|
|
@ -15,6 +15,10 @@ class FileEntryTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testGetRequest);
|
CPPUNIT_TEST(testGetRequest);
|
||||||
CPPUNIT_TEST(testGetRequest_disableSingleHostMultiConnection);
|
CPPUNIT_TEST(testGetRequest_disableSingleHostMultiConnection);
|
||||||
CPPUNIT_TEST(testReuseUri);
|
CPPUNIT_TEST(testReuseUri);
|
||||||
|
CPPUNIT_TEST(testAddUri);
|
||||||
|
CPPUNIT_TEST(testAddUris);
|
||||||
|
CPPUNIT_TEST(testInsertUri);
|
||||||
|
CPPUNIT_TEST(testRemoveUri);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
public:
|
public:
|
||||||
void setUp() {}
|
void setUp() {}
|
||||||
|
@ -25,6 +29,10 @@ public:
|
||||||
void testGetRequest();
|
void testGetRequest();
|
||||||
void testGetRequest_disableSingleHostMultiConnection();
|
void testGetRequest_disableSingleHostMultiConnection();
|
||||||
void testReuseUri();
|
void testReuseUri();
|
||||||
|
void testAddUri();
|
||||||
|
void testAddUris();
|
||||||
|
void testInsertUri();
|
||||||
|
void testRemoveUri();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,4 +157,63 @@ void FileEntryTest::testReuseUri()
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[2]);
|
CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileEntryTest::testAddUri()
|
||||||
|
{
|
||||||
|
FileEntry file;
|
||||||
|
CPPUNIT_ASSERT(file.addUri("http://good"));
|
||||||
|
CPPUNIT_ASSERT(!file.addUri("bad"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileEntryTest::testAddUris()
|
||||||
|
{
|
||||||
|
FileEntry file;
|
||||||
|
std::string uris[] = {"bad", "http://good"};
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, file.addUris(&uris[0], &uris[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileEntryTest::testInsertUri()
|
||||||
|
{
|
||||||
|
FileEntry file;
|
||||||
|
CPPUNIT_ASSERT(file.insertUri("http://example.org/1", 0));
|
||||||
|
CPPUNIT_ASSERT(file.insertUri("http://example.org/2", 0));
|
||||||
|
CPPUNIT_ASSERT(file.insertUri("http://example.org/3", 1));
|
||||||
|
CPPUNIT_ASSERT(file.insertUri("http://example.org/4", 5));
|
||||||
|
std::deque<std::string> uris = file.getRemainingUris();
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/2"), uris[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/3"), uris[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/1"), uris[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/4"), uris[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileEntryTest::testRemoveUri()
|
||||||
|
{
|
||||||
|
SharedHandle<InOrderURISelector> selector(new InOrderURISelector());
|
||||||
|
FileEntry file;
|
||||||
|
file.addUri("http://example.org/");
|
||||||
|
CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
|
||||||
|
CPPUNIT_ASSERT(file.getRemainingUris().empty());
|
||||||
|
CPPUNIT_ASSERT(!file.removeUri("http://example.org/"));
|
||||||
|
|
||||||
|
file.addUri("http://example.org/");
|
||||||
|
SharedHandle<Request> exampleOrgReq = file.getRequest(selector);
|
||||||
|
CPPUNIT_ASSERT(!exampleOrgReq->removalRequested());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, file.getSpentUris().size());
|
||||||
|
CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
|
||||||
|
CPPUNIT_ASSERT(file.getSpentUris().empty());
|
||||||
|
CPPUNIT_ASSERT(exampleOrgReq->removalRequested());
|
||||||
|
file.poolRequest(exampleOrgReq);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, file.countPooledRequest());
|
||||||
|
|
||||||
|
file.addUri("http://example.org/");
|
||||||
|
exampleOrgReq = file.getRequest(selector);
|
||||||
|
file.poolRequest(exampleOrgReq);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)1, file.countPooledRequest());
|
||||||
|
CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, file.countPooledRequest());
|
||||||
|
CPPUNIT_ASSERT(file.getSpentUris().empty());
|
||||||
|
|
||||||
|
file.addUri("http://example.org/");
|
||||||
|
CPPUNIT_ASSERT(!file.removeUri("http://example.net"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -75,6 +75,8 @@ class XmlRpcMethodTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testChangePosition);
|
CPPUNIT_TEST(testChangePosition);
|
||||||
CPPUNIT_TEST(testChangePosition_fail);
|
CPPUNIT_TEST(testChangePosition_fail);
|
||||||
CPPUNIT_TEST(testGetSessionInfo);
|
CPPUNIT_TEST(testGetSessionInfo);
|
||||||
|
CPPUNIT_TEST(testChangeUri);
|
||||||
|
CPPUNIT_TEST(testChangeUri_fail);
|
||||||
CPPUNIT_TEST(testSystemMulticall);
|
CPPUNIT_TEST(testSystemMulticall);
|
||||||
CPPUNIT_TEST(testSystemMulticall_fail);
|
CPPUNIT_TEST(testSystemMulticall_fail);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
@ -135,6 +137,8 @@ public:
|
||||||
void testChangePosition();
|
void testChangePosition();
|
||||||
void testChangePosition_fail();
|
void testChangePosition_fail();
|
||||||
void testGetSessionInfo();
|
void testGetSessionInfo();
|
||||||
|
void testChangeUri();
|
||||||
|
void testChangeUri_fail();
|
||||||
void testSystemMulticall();
|
void testSystemMulticall();
|
||||||
void testSystemMulticall_fail();
|
void testSystemMulticall_fail();
|
||||||
};
|
};
|
||||||
|
@ -779,6 +783,131 @@ void XmlRpcMethodTest::testChangePosition_fail()
|
||||||
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlRpcMethodTest::testChangeUri()
|
||||||
|
{
|
||||||
|
SharedHandle<FileEntry> files[3];
|
||||||
|
for(int i = 0; i < 3; ++i) {
|
||||||
|
files[i].reset(new FileEntry());
|
||||||
|
}
|
||||||
|
files[1]->addUri("http://example.org/aria2.tar.bz2");
|
||||||
|
files[1]->addUri("http://example.org/mustremove1");
|
||||||
|
files[1]->addUri("http://example.org/mustremove2");
|
||||||
|
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
||||||
|
dctx->setFileEntries(&files[0], &files[3]);
|
||||||
|
SharedHandle<RequestGroup> group(new RequestGroup(_option));
|
||||||
|
group->setDownloadContext(dctx);
|
||||||
|
_e->_requestGroupMan->addReservedGroup(group);
|
||||||
|
|
||||||
|
ChangeUriXmlRpcMethod m;
|
||||||
|
XmlRpcRequest req(ChangeUriXmlRpcMethod::getMethodName(), BDE::list());
|
||||||
|
req._params << std::string("1"); // GID
|
||||||
|
req._params << 1; // index of FileEntry
|
||||||
|
BDE removeuris = BDE::list();
|
||||||
|
removeuris << std::string("http://example.org/mustremove1");
|
||||||
|
removeuris << std::string("http://example.org/mustremove2");
|
||||||
|
removeuris << std::string("http://example.org/notexist");
|
||||||
|
req._params << removeuris;
|
||||||
|
BDE adduris = BDE::list();
|
||||||
|
adduris << std::string("http://example.org/added1");
|
||||||
|
adduris << std::string("http://example.org/added2");
|
||||||
|
adduris << std::string("baduri");
|
||||||
|
adduris << std::string("http://example.org/added3");
|
||||||
|
req._params << adduris;
|
||||||
|
XmlRpcResponse res = m.execute(req, _e.get());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, res._code);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)2, res._param[0].i());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)3, res._param[1].i());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, files[0]->getRemainingUris().size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, files[2]->getRemainingUris().size());
|
||||||
|
std::deque<std::string> uris = files[1]->getRemainingUris();
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, uris.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/aria2.tar.bz2"),uris[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1"), uris[1]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added2"), uris[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added3"), uris[3]);
|
||||||
|
|
||||||
|
// Change adduris
|
||||||
|
adduris = BDE::list();
|
||||||
|
adduris << std::string("http://example.org/added1-1");
|
||||||
|
adduris << std::string("http://example.org/added1-2");
|
||||||
|
req._params[3] = adduris;
|
||||||
|
// Set position parameter
|
||||||
|
req._params << 2;
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, res._code);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)0, res._param[0].i());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)2, res._param[1].i());
|
||||||
|
uris = files[1]->getRemainingUris();
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)6, uris.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-1"), uris[2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-2"), uris[3]);
|
||||||
|
|
||||||
|
// Change index of FileEntry
|
||||||
|
req._params[1] = 0;
|
||||||
|
// Set position far beyond the size of uris in FileEntry.
|
||||||
|
req._params[4] = 1000;
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, res._code);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)0, res._param[0].i());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)2, res._param[1].i());
|
||||||
|
uris = files[0]->getRemainingUris();
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)2, uris.size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-1"), uris[0]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-2"), uris[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmlRpcMethodTest::testChangeUri_fail()
|
||||||
|
{
|
||||||
|
SharedHandle<FileEntry> files[3];
|
||||||
|
for(int i = 0; i < 3; ++i) {
|
||||||
|
files[i].reset(new FileEntry());
|
||||||
|
}
|
||||||
|
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
||||||
|
dctx->setFileEntries(&files[0], &files[3]);
|
||||||
|
SharedHandle<RequestGroup> group(new RequestGroup(_option));
|
||||||
|
group->setDownloadContext(dctx);
|
||||||
|
_e->_requestGroupMan->addReservedGroup(group);
|
||||||
|
|
||||||
|
ChangeUriXmlRpcMethod m;
|
||||||
|
XmlRpcRequest req(ChangeUriXmlRpcMethod::getMethodName(), BDE::list());
|
||||||
|
req._params << std::string("1"); // GID
|
||||||
|
req._params << 0; // index of FileEntry
|
||||||
|
BDE removeuris = BDE::list();
|
||||||
|
req._params << removeuris;
|
||||||
|
BDE adduris = BDE::list();
|
||||||
|
req._params << adduris;
|
||||||
|
XmlRpcResponse res = m.execute(req, _e.get());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, res._code);
|
||||||
|
|
||||||
|
req._params[0] = std::string("2");
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
// RPC request fails because GID#2 does not exist.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
|
|
||||||
|
req._params[0] = std::string("1");
|
||||||
|
req._params[1] = 3;
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
// RPC request fails because FileEntry#3 does not exist.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
|
|
||||||
|
req._params[1] = std::string("0");
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
// RPC request fails because index of FileEntry is string.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
|
|
||||||
|
req._params[1] = 0;
|
||||||
|
req._params[2] = std::string("http://url");
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
// RPC request fails because 3rd param is not list.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
|
|
||||||
|
req._params[2] = BDE::list();
|
||||||
|
req._params[3] = std::string("http://url");
|
||||||
|
res = m.execute(req, _e.get());
|
||||||
|
// RPC request fails because 4th param is not list.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(1, res._code);
|
||||||
|
}
|
||||||
|
|
||||||
void XmlRpcMethodTest::testGetSessionInfo()
|
void XmlRpcMethodTest::testGetSessionInfo()
|
||||||
{
|
{
|
||||||
GetSessionInfoXmlRpcMethod m;
|
GetSessionInfoXmlRpcMethod m;
|
||||||
|
|
Loading…
Reference in New Issue