mirror of https://github.com/aria2/aria2
Add changeOption and DownloadHandle::getOption API
In aria2c.rst, define section label for "Input File" section so that it can be referenced from other document.pull/89/head
parent
be4c9aa95e
commit
c7c4d46672
|
@ -1733,6 +1733,8 @@ if you have a torrent or metalink with chunk checksums for the file,
|
|||
you can resume the download without a control file by giving -V option
|
||||
to aria2c in command-line.
|
||||
|
||||
.. _input-file:
|
||||
|
||||
Input File
|
||||
~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -1082,85 +1082,6 @@ SharedHandle<ValueBase> RemoveDownloadResultRpcMethod::process
|
|||
return VLB_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void changeOption
|
||||
(const SharedHandle<RequestGroup>& group,
|
||||
const Option& option,
|
||||
DownloadEngine* e)
|
||||
{
|
||||
const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
|
||||
const SharedHandle<Option>& grOption = group->getOption();
|
||||
grOption->merge(option);
|
||||
if(option.defined(PREF_CHECKSUM)) {
|
||||
const std::string& checksum = grOption->get(PREF_CHECKSUM);
|
||||
std::pair<Scip, Scip> p;
|
||||
util::divide(p, checksum.begin(), checksum.end(), '=');
|
||||
std::string hashType(p.first.first, p.first.second);
|
||||
util::lowercase(hashType);
|
||||
dctx->setDigest(hashType, util::fromHex(p.second.first, p.second.second));
|
||||
}
|
||||
if(option.defined(PREF_SELECT_FILE)) {
|
||||
SegList<int> sgl;
|
||||
util::parseIntSegments(sgl, grOption->get(PREF_SELECT_FILE));
|
||||
sgl.normalize();
|
||||
dctx->setFileFilter(sgl);
|
||||
}
|
||||
if(option.defined(PREF_SPLIT)) {
|
||||
group->setNumConcurrentCommand(grOption->getAsInt(PREF_SPLIT));
|
||||
}
|
||||
if(option.defined(PREF_MAX_CONNECTION_PER_SERVER)) {
|
||||
int maxConn = grOption->getAsInt(PREF_MAX_CONNECTION_PER_SERVER);
|
||||
const std::vector<SharedHandle<FileEntry> >& files = dctx->getFileEntries();
|
||||
for(std::vector<SharedHandle<FileEntry> >::const_iterator i = files.begin(),
|
||||
eoi = files.end(); i != eoi; ++i) {
|
||||
(*i)->setMaxConnectionPerServer(maxConn);
|
||||
}
|
||||
}
|
||||
if(option.defined(PREF_DIR) || option.defined(PREF_OUT)) {
|
||||
if(dctx->getFileEntries().size() == 1
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
&& !dctx->hasAttribute(CTX_ATTR_BT)
|
||||
#endif // ENABLE_BITTORRENT
|
||||
) {
|
||||
dctx->getFirstFileEntry()->setPath
|
||||
(grOption->blank(PREF_OUT) ? A2STR::NIL :
|
||||
util::applyDir(grOption->get(PREF_DIR), grOption->get(PREF_OUT)));
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
if(option.defined(PREF_DIR) || option.defined(PREF_INDEX_OUT)) {
|
||||
if(dctx->hasAttribute(CTX_ATTR_BT)) {
|
||||
std::istringstream indexOutIn(grOption->get(PREF_INDEX_OUT));
|
||||
std::vector<std::pair<size_t, std::string> > indexPaths =
|
||||
util::createIndexPaths(indexOutIn);
|
||||
for(std::vector<std::pair<size_t, std::string> >::const_iterator i =
|
||||
indexPaths.begin(), eoi = indexPaths.end(); i != eoi; ++i) {
|
||||
dctx->setFilePathWithIndex
|
||||
((*i).first,
|
||||
util::applyDir(grOption->get(PREF_DIR), (*i).second));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_BITTORRENT
|
||||
if(option.defined(PREF_MAX_DOWNLOAD_LIMIT)) {
|
||||
group->setMaxDownloadSpeedLimit
|
||||
(grOption->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
|
||||
}
|
||||
if(option.defined(PREF_MAX_UPLOAD_LIMIT)) {
|
||||
group->setMaxUploadSpeedLimit(grOption->getAsInt(PREF_MAX_UPLOAD_LIMIT));
|
||||
}
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
const SharedHandle<BtObject>& btObject =
|
||||
e->getBtRegistry()->get(group->getGID());
|
||||
if(btObject) {
|
||||
if(option.defined(PREF_BT_MAX_PEERS)) {
|
||||
btObject->btRuntime->setMaxPeers(grOption->getAsInt(PREF_BT_MAX_PEERS));
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_BITTORRENT
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SharedHandle<ValueBase> ChangeOptionRpcMethod::process
|
||||
(const RpcRequest& req, DownloadEngine* e)
|
||||
{
|
||||
|
@ -1544,4 +1465,81 @@ bool pauseRequestGroup
|
|||
}
|
||||
}
|
||||
|
||||
void changeOption
|
||||
(const SharedHandle<RequestGroup>& group,
|
||||
const Option& option,
|
||||
DownloadEngine* e)
|
||||
{
|
||||
const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
|
||||
const SharedHandle<Option>& grOption = group->getOption();
|
||||
grOption->merge(option);
|
||||
if(option.defined(PREF_CHECKSUM)) {
|
||||
const std::string& checksum = grOption->get(PREF_CHECKSUM);
|
||||
std::pair<Scip, Scip> p;
|
||||
util::divide(p, checksum.begin(), checksum.end(), '=');
|
||||
std::string hashType(p.first.first, p.first.second);
|
||||
util::lowercase(hashType);
|
||||
dctx->setDigest(hashType, util::fromHex(p.second.first, p.second.second));
|
||||
}
|
||||
if(option.defined(PREF_SELECT_FILE)) {
|
||||
SegList<int> sgl;
|
||||
util::parseIntSegments(sgl, grOption->get(PREF_SELECT_FILE));
|
||||
sgl.normalize();
|
||||
dctx->setFileFilter(sgl);
|
||||
}
|
||||
if(option.defined(PREF_SPLIT)) {
|
||||
group->setNumConcurrentCommand(grOption->getAsInt(PREF_SPLIT));
|
||||
}
|
||||
if(option.defined(PREF_MAX_CONNECTION_PER_SERVER)) {
|
||||
int maxConn = grOption->getAsInt(PREF_MAX_CONNECTION_PER_SERVER);
|
||||
const std::vector<SharedHandle<FileEntry> >& files = dctx->getFileEntries();
|
||||
for(std::vector<SharedHandle<FileEntry> >::const_iterator i = files.begin(),
|
||||
eoi = files.end(); i != eoi; ++i) {
|
||||
(*i)->setMaxConnectionPerServer(maxConn);
|
||||
}
|
||||
}
|
||||
if(option.defined(PREF_DIR) || option.defined(PREF_OUT)) {
|
||||
if(dctx->getFileEntries().size() == 1
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
&& !dctx->hasAttribute(CTX_ATTR_BT)
|
||||
#endif // ENABLE_BITTORRENT
|
||||
) {
|
||||
dctx->getFirstFileEntry()->setPath
|
||||
(grOption->blank(PREF_OUT) ? A2STR::NIL :
|
||||
util::applyDir(grOption->get(PREF_DIR), grOption->get(PREF_OUT)));
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
if(option.defined(PREF_DIR) || option.defined(PREF_INDEX_OUT)) {
|
||||
if(dctx->hasAttribute(CTX_ATTR_BT)) {
|
||||
std::istringstream indexOutIn(grOption->get(PREF_INDEX_OUT));
|
||||
std::vector<std::pair<size_t, std::string> > indexPaths =
|
||||
util::createIndexPaths(indexOutIn);
|
||||
for(std::vector<std::pair<size_t, std::string> >::const_iterator i =
|
||||
indexPaths.begin(), eoi = indexPaths.end(); i != eoi; ++i) {
|
||||
dctx->setFilePathWithIndex
|
||||
((*i).first,
|
||||
util::applyDir(grOption->get(PREF_DIR), (*i).second));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_BITTORRENT
|
||||
if(option.defined(PREF_MAX_DOWNLOAD_LIMIT)) {
|
||||
group->setMaxDownloadSpeedLimit
|
||||
(grOption->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
|
||||
}
|
||||
if(option.defined(PREF_MAX_UPLOAD_LIMIT)) {
|
||||
group->setMaxUploadSpeedLimit(grOption->getAsInt(PREF_MAX_UPLOAD_LIMIT));
|
||||
}
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
const SharedHandle<BtObject>& btObject =
|
||||
e->getBtRegistry()->get(group->getGID());
|
||||
if(btObject) {
|
||||
if(option.defined(PREF_BT_MAX_PEERS)) {
|
||||
btObject->btRuntime->setMaxPeers(grOption->getAsInt(PREF_BT_MAX_PEERS));
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_BITTORRENT
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -608,6 +608,11 @@ void gatherBitTorrentMetadata
|
|||
bool pauseRequestGroup
|
||||
(const SharedHandle<RequestGroup>& group, bool reserved, bool forcePause);
|
||||
|
||||
void changeOption
|
||||
(const SharedHandle<RequestGroup>& group,
|
||||
const Option& option,
|
||||
DownloadEngine* e);
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // D_RPC_METHOD_IMPL_H
|
||||
|
|
|
@ -225,6 +225,27 @@ void apiGatherRequestOption(Option* option, const KeyVals& options,
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void apiGatherChangeableOption(Option* option, const KeyVals& options,
|
||||
const SharedHandle<OptionParser>& optionParser)
|
||||
{
|
||||
apiGatherOption(options.begin(), options.end(),
|
||||
std::mem_fun(&OptionHandler::getChangeOption),
|
||||
option, optionParser);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void apiGatherChangeableOptionForReserved
|
||||
(Option* option, const KeyVals& options,
|
||||
const SharedHandle<OptionParser>& optionParser)
|
||||
{
|
||||
apiGatherOption(options.begin(), options.end(),
|
||||
std::mem_fun(&OptionHandler::getChangeOptionForReserved),
|
||||
option, optionParser);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void addRequestGroup(const SharedHandle<RequestGroup>& group,
|
||||
const SharedHandle<DownloadEngine>& e,
|
||||
|
@ -419,6 +440,32 @@ int changePosition(Session* session, const A2Gid& gid, int pos, OffsetMode how)
|
|||
}
|
||||
}
|
||||
|
||||
int changeOption(Session* session, const A2Gid& gid, const KeyVals& options)
|
||||
{
|
||||
const SharedHandle<DownloadEngine>& e =
|
||||
session->context->reqinfo->getDownloadEngine();
|
||||
SharedHandle<RequestGroup> group = e->getRequestGroupMan()->findGroup(gid);
|
||||
if(group) {
|
||||
Option option;
|
||||
try {
|
||||
if(group->getState() == RequestGroup::STATE_ACTIVE) {
|
||||
apiGatherChangeableOption(&option, options,
|
||||
OptionParser::getInstance());
|
||||
} else {
|
||||
apiGatherChangeableOptionForReserved(&option, options,
|
||||
OptionParser::getInstance());
|
||||
}
|
||||
} catch(RecoverableException& err) {
|
||||
A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, err);
|
||||
return -1;
|
||||
}
|
||||
changeOption(group, option, e.get());
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<A2Gid> getActiveDownload(Session* session)
|
||||
{
|
||||
const SharedHandle<DownloadEngine>& e =
|
||||
|
@ -527,6 +574,23 @@ void createFileEntry
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
template<typename OutputIterator>
|
||||
void pushRequestOption
|
||||
(OutputIterator out,
|
||||
const SharedHandle<Option>& option,
|
||||
const SharedHandle<OptionParser>& oparser)
|
||||
{
|
||||
for(size_t i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
const OptionHandler* h = oparser->find(pref);
|
||||
if(h && h->getInitialOption() && option->defined(pref)) {
|
||||
out++ = KeyVals::value_type(pref->k, option->get(pref));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
struct RequestGroupDH : public DownloadHandle {
|
||||
RequestGroupDH(const SharedHandle<RequestGroup>& group)
|
||||
|
@ -660,6 +724,17 @@ struct RequestGroupDH : public DownloadHandle {
|
|||
#endif // ENABLE_BITTORRENT
|
||||
return res;
|
||||
}
|
||||
virtual const std::string& getOption(const std::string& name)
|
||||
{
|
||||
return group->getOption()->get(option::k2p(name));
|
||||
}
|
||||
virtual KeyVals getOption()
|
||||
{
|
||||
KeyVals res;
|
||||
pushRequestOption(std::back_inserter(res), group->getOption(),
|
||||
OptionParser::getInstance());
|
||||
return res;
|
||||
}
|
||||
SharedHandle<RequestGroup> group;
|
||||
TransferStat ts;
|
||||
};
|
||||
|
@ -761,6 +836,14 @@ struct DownloadResultDH : public DownloadHandle {
|
|||
{
|
||||
return BtMetaInfoData();
|
||||
}
|
||||
virtual const std::string& getOption(const std::string& name)
|
||||
{
|
||||
return A2STR::NIL;
|
||||
}
|
||||
virtual KeyVals getOption()
|
||||
{
|
||||
return KeyVals();
|
||||
}
|
||||
SharedHandle<DownloadResult> dr;
|
||||
};
|
||||
} // namespace
|
||||
|
|
|
@ -404,6 +404,38 @@ int pauseDownload(Session* session, const A2Gid& gid, bool force = false);
|
|||
*/
|
||||
int unpauseDownload(Session* session, const A2Gid& gid);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Apply options in the |options| to the download denoted by the |gid|
|
||||
* dynamically. The following options can be changed for downloads in
|
||||
* :c:macro:`DOWNLOAD_ACTIVE` status:
|
||||
*
|
||||
* * :option:`bt-max-peers <--bt-max-peers>`
|
||||
* * :option:`bt-request-peer-speed-limit <--bt-request-peer-speed-limit>`
|
||||
* * :option:`bt-remove-unselected-file <--bt-remove-unselected-file>`
|
||||
* * :option:`force-save <--force-save>`
|
||||
* * :option:`max-download-limit <--max-download-limit>`
|
||||
* * :option:`max-upload-limit <-u>`
|
||||
*
|
||||
* For downloads in :c:macro:`DOWNLOAD_WAITING` or
|
||||
* :c:macro:`DOWNLOAD_PAUSED` status, in addition to the above
|
||||
* options, options listed in :ref:`input-file` subsection are available,
|
||||
* except for following options:
|
||||
* :option:`dry-run <--dry-run>`,
|
||||
* :option:`metalink-base-uri <--metalink-base-uri>`,
|
||||
* :option:`parameterized-uri <-P>`,
|
||||
* :option:`pause <--pause>`,
|
||||
* :option:`piece-length <--piece-length>` and
|
||||
* :option:`rpc-save-upload-metadata <--rpc-save-upload-metadata>` option.
|
||||
*
|
||||
* The options which are not applicable or unknown, they are just
|
||||
* ignored.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or negative error code.
|
||||
*/
|
||||
int changeOption(Session* session, const A2Gid& gid, const KeyVals& options);
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
|
@ -733,6 +765,26 @@ public:
|
|||
* stopped/completed.
|
||||
*/
|
||||
virtual BtMetaInfoData getBtMetaInfo() = 0;
|
||||
/**
|
||||
* Returns the option value denoted by the |name|. If the option
|
||||
* denoted by the |name| is not available, returns empty string.
|
||||
*
|
||||
* Calling this function for the download which is not in
|
||||
* :c:macro:`DOWNLOAD_ACTIVE`, :c:macro:`DOWNLOAD_PAUSED` or
|
||||
* :c:macro:`DOWNLOAD_WAITING` will return empty string.
|
||||
*/
|
||||
virtual const std::string& getOption(const std::string& name) = 0;
|
||||
/**
|
||||
* Returns options for this download. Note that this function does
|
||||
* not return options which have no default value and have not been
|
||||
* set by :func:`sessionNew()`, configuration files or API
|
||||
* functions.
|
||||
*
|
||||
* Calling this function for the download which is not in
|
||||
* :c:macro:`DOWNLOAD_ACTIVE`, :c:macro:`DOWNLOAD_PAUSED` or
|
||||
* :c:macro:`DOWNLOAD_WAITING` will return empty array.
|
||||
*/
|
||||
virtual KeyVals getOption() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ class Aria2ApiTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testAddTorrent);
|
||||
CPPUNIT_TEST(testRemovePause);
|
||||
CPPUNIT_TEST(testChangePosition);
|
||||
CPPUNIT_TEST(testChangeOption);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
Session* session_;
|
||||
|
@ -33,6 +34,7 @@ public:
|
|||
void testAddTorrent();
|
||||
void testRemovePause();
|
||||
void testChangePosition();
|
||||
void testChangeOption();
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(Aria2ApiTest);
|
||||
|
@ -149,4 +151,43 @@ void Aria2ApiTest::testChangePosition()
|
|||
|
||||
}
|
||||
|
||||
void Aria2ApiTest::testChangeOption()
|
||||
{
|
||||
A2Gid gid;
|
||||
std::vector<std::string> uris(1);
|
||||
KeyVals options;
|
||||
uris[0] = "http://localhost/1";
|
||||
options.push_back(KeyVals::value_type("dir", "mydownload"));
|
||||
CPPUNIT_ASSERT_EQUAL(0, addUri(session_, &gid, uris, options));
|
||||
|
||||
DownloadHandle* hd = getDownloadHandle(session_, gid);
|
||||
CPPUNIT_ASSERT(hd);
|
||||
CPPUNIT_ASSERT_EQUAL(1, hd->getNumFiles());
|
||||
FileData file = hd->getFile(1);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, file.uris.size());
|
||||
CPPUNIT_ASSERT_EQUAL(uris[0], file.uris[0].uri);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("mydownload"), hd->getOption("dir"));
|
||||
CPPUNIT_ASSERT(hd->getOption("unknown").empty());
|
||||
KeyVals retopts = hd->getOption();
|
||||
CPPUNIT_ASSERT(std::find(retopts.begin(), retopts.end(),
|
||||
KeyVals::value_type("dir", "mydownload"))
|
||||
!= retopts.end());
|
||||
deleteDownloadHandle(hd);
|
||||
// failure with null gid
|
||||
CPPUNIT_ASSERT_EQUAL(-1, changeOption(session_, (A2Gid)0, options));
|
||||
// change option
|
||||
options.clear();
|
||||
options.push_back(KeyVals::value_type("dir", "newlocation"));
|
||||
CPPUNIT_ASSERT_EQUAL(0, changeOption(session_, gid, options));
|
||||
hd = getDownloadHandle(session_, gid);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("newlocation"), hd->getOption("dir"));
|
||||
deleteDownloadHandle(hd);
|
||||
// failure with bad option value
|
||||
options.clear();
|
||||
options.push_back(KeyVals::value_type("file-allocation", "foo"));
|
||||
CPPUNIT_ASSERT_EQUAL(-1, changeOption(session_, gid, options));
|
||||
}
|
||||
|
||||
|
||||
} // namespace aria2
|
||||
|
|
Loading…
Reference in New Issue