mirror of https://github.com/aria2/aria2
Merge branch 'dynamic-select-file'
commit
c7d242e27d
|
@ -3159,7 +3159,19 @@ For information on the *secret* parameter, see :ref:`rpc_auth`.
|
||||||
|
|
||||||
This method changes options of the download denoted by *gid* (string)
|
This method changes options of the download denoted by *gid* (string)
|
||||||
dynamically. *options* is a struct.
|
dynamically. *options* is a struct.
|
||||||
The following options are available for active downloads:
|
The options listed in `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>`
|
||||||
|
* :option:`rpc-save-upload-metadata <--rpc-save-upload-metadata>`
|
||||||
|
|
||||||
|
Except for the following options, changing the other options of
|
||||||
|
active download makes it restart (restart itself is managed by
|
||||||
|
aria2, and no user intervention is required):
|
||||||
|
|
||||||
* :option:`bt-max-peers <--bt-max-peers>`
|
* :option:`bt-max-peers <--bt-max-peers>`
|
||||||
* :option:`bt-request-peer-speed-limit <--bt-request-peer-speed-limit>`
|
* :option:`bt-request-peer-speed-limit <--bt-request-peer-speed-limit>`
|
||||||
|
@ -3168,15 +3180,6 @@ For information on the *secret* parameter, see :ref:`rpc_auth`.
|
||||||
* :option:`max-download-limit <--max-download-limit>`
|
* :option:`max-download-limit <--max-download-limit>`
|
||||||
* :option:`max-upload-limit <-u>`
|
* :option:`max-upload-limit <-u>`
|
||||||
|
|
||||||
For waiting or paused downloads, in addition to the above options,
|
|
||||||
options listed in `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.
|
|
||||||
This method returns ``OK`` for success.
|
This method returns ``OK`` for success.
|
||||||
|
|
||||||
The following examples set the :option:`max-download-limit
|
The following examples set the :option:`max-download-limit
|
||||||
|
|
|
@ -190,4 +190,10 @@ void Option::setParent(const std::shared_ptr<Option>& parent)
|
||||||
|
|
||||||
const std::shared_ptr<Option>& Option::getParent() const { return parent_; }
|
const std::shared_ptr<Option>& Option::getParent() const { return parent_; }
|
||||||
|
|
||||||
|
bool Option::emptyLocal() const
|
||||||
|
{
|
||||||
|
size_t dst;
|
||||||
|
return !bitfield::getFirstSetBitIndex(dst, use_, use_.size() * 8);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -92,6 +92,8 @@ public:
|
||||||
// Sets parent Option object for this object.
|
// Sets parent Option object for this object.
|
||||||
void setParent(const std::shared_ptr<Option>& parent);
|
void setParent(const std::shared_ptr<Option>& parent);
|
||||||
const std::shared_ptr<Option>& getParent() const;
|
const std::shared_ptr<Option>& getParent() const;
|
||||||
|
// Returns true if there is no option stored.
|
||||||
|
bool emptyLocal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -986,6 +986,8 @@ void RequestGroup::setForceHaltRequested(bool f, HaltReason haltReason)
|
||||||
|
|
||||||
void RequestGroup::setPauseRequested(bool f) { pauseRequested_ = f; }
|
void RequestGroup::setPauseRequested(bool f) { pauseRequested_ = f; }
|
||||||
|
|
||||||
|
void RequestGroup::setRestartRequested(bool f) { restartRequested_ = f; }
|
||||||
|
|
||||||
void RequestGroup::releaseRuntimeResource(DownloadEngine* e)
|
void RequestGroup::releaseRuntimeResource(DownloadEngine* e)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
|
@ -1308,4 +1310,9 @@ bool RequestGroup::isSeeder() const
|
||||||
#endif // !ENABLE_BITTORRENT
|
#endif // !ENABLE_BITTORRENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestGroup::setPendingOption(std::shared_ptr<Option> option)
|
||||||
|
{
|
||||||
|
pendingOption_ = std::move(option);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -96,6 +96,9 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<Option> option_;
|
std::shared_ptr<Option> option_;
|
||||||
|
|
||||||
|
// options applied on restart
|
||||||
|
std::shared_ptr<Option> pendingOption_;
|
||||||
|
|
||||||
std::shared_ptr<SegmentMan> segmentMan_;
|
std::shared_ptr<SegmentMan> segmentMan_;
|
||||||
|
|
||||||
std::shared_ptr<DownloadContext> downloadContext_;
|
std::shared_ptr<DownloadContext> downloadContext_;
|
||||||
|
@ -178,6 +181,11 @@ private:
|
||||||
|
|
||||||
bool pauseRequested_;
|
bool pauseRequested_;
|
||||||
|
|
||||||
|
// restartRequested_ indicates that this download should be
|
||||||
|
// restarted. Usually, it is used with pauseRequested_ to stop
|
||||||
|
// download first.
|
||||||
|
bool restartRequested_;
|
||||||
|
|
||||||
// This flag just indicates that the downloaded file is not saved disk but
|
// This flag just indicates that the downloaded file is not saved disk but
|
||||||
// just sits in memory.
|
// just sits in memory.
|
||||||
bool inMemoryDownload_;
|
bool inMemoryDownload_;
|
||||||
|
@ -345,6 +353,10 @@ public:
|
||||||
|
|
||||||
bool isPauseRequested() const { return pauseRequested_; }
|
bool isPauseRequested() const { return pauseRequested_; }
|
||||||
|
|
||||||
|
void setRestartRequested(bool f);
|
||||||
|
|
||||||
|
bool isRestartRequested() const { return restartRequested_; }
|
||||||
|
|
||||||
void dependsOn(const std::shared_ptr<Dependency>& dep);
|
void dependsOn(const std::shared_ptr<Dependency>& dep);
|
||||||
|
|
||||||
bool isDependencyResolved();
|
bool isDependencyResolved();
|
||||||
|
@ -500,6 +512,12 @@ public:
|
||||||
|
|
||||||
// Returns true if this download is now seeding.
|
// Returns true if this download is now seeding.
|
||||||
bool isSeeder() const;
|
bool isSeeder() const;
|
||||||
|
|
||||||
|
void setPendingOption(std::shared_ptr<Option> option);
|
||||||
|
const std::shared_ptr<Option>& getPendingOption() const
|
||||||
|
{
|
||||||
|
return pendingOption_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#include "array_fun.h"
|
#include "array_fun.h"
|
||||||
#include "OpenedFileCounter.h"
|
#include "OpenedFileCounter.h"
|
||||||
#include "wallclock.h"
|
#include "wallclock.h"
|
||||||
|
#include "RpcMethodImpl.h"
|
||||||
#ifdef ENABLE_BITTORRENT
|
#ifdef ENABLE_BITTORRENT
|
||||||
#include "bittorrent_helper.h"
|
#include "bittorrent_helper.h"
|
||||||
#endif // ENABLE_BITTORRENT
|
#endif // ENABLE_BITTORRENT
|
||||||
|
@ -369,8 +370,10 @@ public:
|
||||||
try {
|
try {
|
||||||
group->closeFile();
|
group->closeFile();
|
||||||
if (group->isPauseRequested()) {
|
if (group->isPauseRequested()) {
|
||||||
|
if (!group->isRestartRequested()) {
|
||||||
A2_LOG_NOTICE(fmt(_("Download GID#%s paused"),
|
A2_LOG_NOTICE(fmt(_("Download GID#%s paused"),
|
||||||
GroupId::toHex(group->getGID()).c_str()));
|
GroupId::toHex(group->getGID()).c_str()));
|
||||||
|
}
|
||||||
group->saveControlFile();
|
group->saveControlFile();
|
||||||
}
|
}
|
||||||
else if (group->downloadFinished() &&
|
else if (group->downloadFinished() &&
|
||||||
|
@ -433,9 +436,20 @@ public:
|
||||||
reservedGroups_.push_front(group->getGID(), group);
|
reservedGroups_.push_front(group->getGID(), group);
|
||||||
group->releaseRuntimeResource(e_);
|
group->releaseRuntimeResource(e_);
|
||||||
group->setForceHaltRequested(false);
|
group->setForceHaltRequested(false);
|
||||||
|
|
||||||
|
auto pendingOption = group->getPendingOption();
|
||||||
|
if (pendingOption) {
|
||||||
|
changeOption(group, *pendingOption, e_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->isRestartRequested()) {
|
||||||
|
group->setPauseRequested(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
util::executeHookByOptName(group, e_->getOption(),
|
util::executeHookByOptName(group, e_->getOption(),
|
||||||
PREF_ON_DOWNLOAD_PAUSE);
|
PREF_ON_DOWNLOAD_PAUSE);
|
||||||
notifyDownloadEvent(EVENT_ON_DOWNLOAD_PAUSE, group);
|
notifyDownloadEvent(EVENT_ON_DOWNLOAD_PAUSE, group);
|
||||||
|
}
|
||||||
// TODO Should we have to prepend spend uris to remaining uris
|
// TODO Should we have to prepend spend uris to remaining uris
|
||||||
// in case PREF_REUSE_URI is disabled?
|
// in case PREF_REUSE_URI is disabled?
|
||||||
}
|
}
|
||||||
|
@ -445,6 +459,10 @@ public:
|
||||||
executeStopHook(group, e_->getOption(), dr->result);
|
executeStopHook(group, e_->getOption(), dr->result);
|
||||||
group->releaseRuntimeResource(e_);
|
group->releaseRuntimeResource(e_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group->setRestartRequested(false);
|
||||||
|
group->setPendingOption(nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -147,12 +147,53 @@ void RpcMethod::gatherRequestOption(Option* option, const Dict* optionsDict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcMethod::gatherChangeableOption(Option* option, const Dict* optionsDict)
|
void RpcMethod::gatherChangeableOption(Option* option, Option* pendingOption,
|
||||||
|
const Dict* optionsDict)
|
||||||
{
|
{
|
||||||
if (optionsDict) {
|
if (!optionsDict) {
|
||||||
gatherOption(optionsDict->begin(), optionsDict->end(),
|
return;
|
||||||
std::mem_fn(&OptionHandler::getChangeOption), option,
|
}
|
||||||
optionParser_);
|
|
||||||
|
auto first = optionsDict->begin();
|
||||||
|
auto last = optionsDict->end();
|
||||||
|
|
||||||
|
for (; first != last; ++first) {
|
||||||
|
const auto& optionName = (*first).first;
|
||||||
|
auto pref = option::k2p(optionName);
|
||||||
|
auto handler = optionParser_->find(pref);
|
||||||
|
if (!handler) {
|
||||||
|
// Just ignore the unacceptable options in this context.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Option* dst = nullptr;
|
||||||
|
if (handler->getChangeOption()) {
|
||||||
|
dst = option;
|
||||||
|
}
|
||||||
|
else if (handler->getChangeOptionForReserved()) {
|
||||||
|
dst = pendingOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dst) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto opval = downcast<String>((*first).second);
|
||||||
|
if (opval) {
|
||||||
|
handler->parse(*dst, opval->s());
|
||||||
|
}
|
||||||
|
else if (handler->getCumulative()) {
|
||||||
|
// header and index-out option can take array as value
|
||||||
|
const auto oplist = downcast<List>((*first).second);
|
||||||
|
if (oplist) {
|
||||||
|
for (auto& elem : *oplist) {
|
||||||
|
const auto opval = downcast<String>(elem);
|
||||||
|
if (opval) {
|
||||||
|
handler->parse(*dst, opval->s());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,8 @@ protected:
|
||||||
|
|
||||||
void gatherRequestOption(Option* option, const Dict* optionsDict);
|
void gatherRequestOption(Option* option, const Dict* optionsDict);
|
||||||
|
|
||||||
void gatherChangeableOption(Option* option, const Dict* optionDict);
|
void gatherChangeableOption(Option* option, Option* pendingOption,
|
||||||
|
const Dict* optionDict);
|
||||||
|
|
||||||
void gatherChangeableOptionForReserved(Option* option,
|
void gatherChangeableOptionForReserved(Option* option,
|
||||||
const Dict* optionsDict);
|
const Dict* optionsDict);
|
||||||
|
|
|
@ -1113,10 +1113,22 @@ std::unique_ptr<ValueBase> ChangeOptionRpcMethod::process(const RpcRequest& req,
|
||||||
|
|
||||||
a2_gid_t gid = str2Gid(gidParam);
|
a2_gid_t gid = str2Gid(gidParam);
|
||||||
auto group = e->getRequestGroupMan()->findGroup(gid);
|
auto group = e->getRequestGroupMan()->findGroup(gid);
|
||||||
Option option;
|
|
||||||
if (group) {
|
if (group) {
|
||||||
|
Option option;
|
||||||
|
std::shared_ptr<Option> pendingOption;
|
||||||
if (group->getState() == RequestGroup::STATE_ACTIVE) {
|
if (group->getState() == RequestGroup::STATE_ACTIVE) {
|
||||||
gatherChangeableOption(&option, optsParam);
|
pendingOption = std::make_shared<Option>();
|
||||||
|
gatherChangeableOption(&option, pendingOption.get(), optsParam);
|
||||||
|
if (!pendingOption->emptyLocal()) {
|
||||||
|
group->setPendingOption(pendingOption);
|
||||||
|
// pauseRequestGroup() may fail if group has been told to
|
||||||
|
// stop/pause already. In that case, we can still apply the
|
||||||
|
// pending options on pause.
|
||||||
|
if (pauseRequestGroup(group, false, false)) {
|
||||||
|
group->setRestartRequested(true);
|
||||||
|
e->setRefreshInterval(std::chrono::milliseconds(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gatherChangeableOptionForReserved(&option, optsParam);
|
gatherChangeableOptionForReserved(&option, optsParam);
|
||||||
|
|
|
@ -143,8 +143,7 @@ size_t countSetBitSlow(const Array& bitfield, size_t nbits)
|
||||||
void flipBit(unsigned char* data, size_t length, size_t bitIndex);
|
void flipBit(unsigned char* data, size_t length, size_t bitIndex);
|
||||||
|
|
||||||
// Stores first set bit index of bitfield to index. bitfield contains
|
// Stores first set bit index of bitfield to index. bitfield contains
|
||||||
// nbits. Returns true if missing bit index is found. Otherwise
|
// nbits. Returns true if set bit is found. Otherwise returns false.
|
||||||
// returns false.
|
|
||||||
template <typename Array>
|
template <typename Array>
|
||||||
bool getFirstSetBitIndex(size_t& index, const Array& bitfield, size_t nbits)
|
bool getFirstSetBitIndex(size_t& index, const Array& bitfield, size_t nbits)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue