Merge pull request #1066 from kiwix/smarter_startDownload

This commit is contained in:
Matthieu Gautier 2024-03-20 10:52:56 +01:00 committed by GitHub
commit 8009edd349
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 7 deletions

View File

@ -168,7 +168,10 @@ class Download {
*/ */
class Downloader class Downloader
{ {
public: public: // types
typedef std::vector<std::pair<std::string, std::string>> Options;
public: // functions
Downloader(); Downloader();
virtual ~Downloader(); virtual ~Downloader();
@ -177,14 +180,21 @@ class Downloader
/** /**
* Start a new download. * Start a new download.
* *
* This method is thread safe and return a pointer to a newly created `Download`. * This method is thread safe and returns a pointer to a newly created
* `Download` or an existing one with a matching URI. In the latter case
* the options parameter is ignored, which can lead to surprising results.
* For example, if the old and new download requests (sharing the same URI)
* have different values for the download directory or output file name
* options, after the download is reported to be complete the downloaded file
* will be present only at the location specified for the first request.
*
* User should call `update` on the returned `Download` to have an accurate status. * User should call `update` on the returned `Download` to have an accurate status.
* *
* @param uri: The uri of the thing to download. * @param uri: The uri of the thing to download.
* @param options: A series of pair <option_name, option_value> to pass to aria. * @param options: A series of pair <option_name, option_value> to pass to aria.
* @return: The newly created Download. * @return: The newly created Download.
*/ */
std::shared_ptr<Download> startDownload(const std::string& uri, const std::vector<std::pair<std::string, std::string>>& options = {}); std::shared_ptr<Download> startDownload(const std::string& uri, const Options& options = {});
/** /**
* Get a download corrsponding to a download id (did) * Get a download corrsponding to a download id (did)
@ -206,7 +216,7 @@ class Downloader
*/ */
std::vector<std::string> getDownloadIds() const; std::vector<std::string> getDownloadIds() const;
private: private: // data
mutable std::mutex m_lock; mutable std::mutex m_lock;
std::map<std::string, std::shared_ptr<Download>> m_knownDownloads; std::map<std::string, std::shared_ptr<Download>> m_knownDownloads;
std::shared_ptr<Aria2> mp_aria; std::shared_ptr<Aria2> mp_aria;

View File

@ -18,6 +18,7 @@
*/ */
#include "downloader.h" #include "downloader.h"
#include "tools.h"
#include "tools/pathTools.h" #include "tools/pathTools.h"
#include "tools/stringTools.h" #include "tools/stringTools.h"
@ -166,13 +167,45 @@ std::vector<std::string> Downloader::getDownloadIds() const {
return ret; return ret;
} }
std::shared_ptr<Download> Downloader::startDownload(const std::string& uri, const std::vector<std::pair<std::string, std::string>>& options) namespace
{
bool downloadCanBeReused(const Download& d,
const std::string& uri,
const Downloader::Options& /*options*/)
{
const auto& uris = d.getUris();
const bool sameURI = std::find(uris.begin(), uris.end(), uri) != uris.end();
if ( !sameURI )
return false;
switch ( d.getStatus() ) {
case Download::K_ERROR:
case Download::K_UNKNOWN:
case Download::K_REMOVED:
return false;
case Download::K_ACTIVE:
case Download::K_WAITING:
case Download::K_PAUSED:
return true; // XXX: what if options are different?
case Download::K_COMPLETE:
return fileExists(d.getPath()); // XXX: what if options are different?
}
return false;
}
} // unnamed namespace
std::shared_ptr<Download> Downloader::startDownload(const std::string& uri, const Options& options)
{ {
std::unique_lock<std::mutex> lock(m_lock); std::unique_lock<std::mutex> lock(m_lock);
for (auto& p: m_knownDownloads) { for (auto& p: m_knownDownloads) {
auto& d = p.second; auto& d = p.second;
auto& uris = d->getUris(); if ( downloadCanBeReused(*d, uri, options) )
if (std::find(uris.begin(), uris.end(), uri) != uris.end())
return d; return d;
} }
std::vector<std::string> uris = {uri}; std::vector<std::string> uris = {uri};