Merge pull request #1097 from kiwix/robust_download_management

kiwix::Downloader's constructor pauses all downloads found in the aria session file
This commit is contained in:
Veloman Yunkan 2024-07-08 20:26:24 +04:00 committed by GitHub
commit ece40966f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 7 deletions

View File

@ -4,6 +4,7 @@
#include "xmlrpc.h" #include "xmlrpc.h"
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <fstream>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
@ -29,6 +30,31 @@
namespace kiwix { namespace kiwix {
namespace {
void pauseAnyActiveDownloads(const std::string& ariaSessionFilePath)
{
std::ifstream inputFile(ariaSessionFilePath);
if ( !inputFile )
return;
std::ostringstream ss;
std::string line;
while ( std::getline(inputFile, line) ) {
if ( !startsWith(line, " pause=") ) {
ss << line << "\n";
}
if ( !line.empty() && line[0] != ' ' && line[0] != '#' ) {
ss << " pause=true\n";
}
}
std::ofstream outputFile(ariaSessionFilePath);
outputFile << ss.str();
}
} // unnamed namespace
Aria2::Aria2(): Aria2::Aria2():
mp_aria(nullptr), mp_aria(nullptr),
m_port(42042), m_port(42042),
@ -41,6 +67,7 @@ Aria2::Aria2():
std::string rpc_port = "--rpc-listen-port=" + to_string(m_port); std::string rpc_port = "--rpc-listen-port=" + to_string(m_port);
std::string download_dir = "--dir=" + getDataDirectory(); std::string download_dir = "--dir=" + getDataDirectory();
std::string session_file = appendToDirectory(getDataDirectory(), "kiwix.session"); std::string session_file = appendToDirectory(getDataDirectory(), "kiwix.session");
pauseAnyActiveDownloads(session_file);
std::string session = "--save-session=" + session_file; std::string session = "--save-session=" + session_file;
std::string inputFile = "--input-file=" + session_file; std::string inputFile = "--input-file=" + session_file;
// std::string log_dir = "--log=\"" + logDir + "\""; // std::string log_dir = "--log=\"" + logDir + "\"";
@ -97,20 +124,30 @@ Aria2::Aria2():
curl_easy_setopt(p_curl, CURLOPT_PORT, m_port); curl_easy_setopt(p_curl, CURLOPT_PORT, m_port);
curl_easy_setopt(p_curl, CURLOPT_POST, 1L); curl_easy_setopt(p_curl, CURLOPT_POST, 1L);
curl_easy_setopt(p_curl, CURLOPT_ERRORBUFFER, curlErrorBuffer); curl_easy_setopt(p_curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
curl_easy_setopt(p_curl, CURLOPT_TIMEOUT_MS, 100);
int watchdog = 50; typedef std::chrono::duration<double> Seconds;
while(--watchdog) {
const double MAX_WAITING_TIME_SECONDS = 0.5;
const auto t0 = std::chrono::steady_clock::now();
bool maxWaitingTimeWasExceeded = false;
CURLcode res = CURLE_OK;
while ( !maxWaitingTimeWasExceeded ) {
sleep(10); sleep(10);
curlErrorBuffer[0] = 0; curlErrorBuffer[0] = 0;
auto res = curl_easy_perform(p_curl); res = curl_easy_perform(p_curl);
if (res == CURLE_OK) { if (res == CURLE_OK) {
break; break;
} else if (watchdog == 1) {
LOG_ARIA_ERROR();
} }
const auto dt = std::chrono::steady_clock::now() - t0;
const double elapsedTime = std::chrono::duration_cast<Seconds>(dt).count();
maxWaitingTimeWasExceeded = elapsedTime > MAX_WAITING_TIME_SECONDS;
} }
curl_easy_cleanup(p_curl); curl_easy_cleanup(p_curl);
if (!watchdog) { if ( maxWaitingTimeWasExceeded ) {
LOG_ARIA_ERROR();
throw std::runtime_error("Cannot connect to aria2c rpc. Aria2c launch cmd : " + launchCmd); throw std::runtime_error("Cannot connect to aria2c rpc. Aria2c launch cmd : " + launchCmd);
} }
} }

View File

@ -151,11 +151,20 @@ Downloader::Downloader() :
/* Destructor */ /* Destructor */
Downloader::~Downloader() Downloader::~Downloader()
{ {
close();
} }
void Downloader::close() void Downloader::close()
{ {
if ( mp_aria ) {
try {
mp_aria->close(); mp_aria->close();
} catch (const std::exception& err) {
std::cerr << "ERROR: Failed to save the downloader state: "
<< err.what() << std::endl;
}
mp_aria.reset();
}
} }
std::vector<std::string> Downloader::getDownloadIds() const { std::vector<std::string> Downloader::getDownloadIds() const {