Merge branch 'dynamic-select-file'

pull/675/head
Tatsuhiro Tsujikawa 2016-06-07 21:13:30 +09:00
commit c7d242e27d
10 changed files with 132 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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());
}
}
}
}
} }
} }

View File

@ -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);

View File

@ -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);

View File

@ -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)
{ {