From a44bca3f070b828f46049b831f13a66e5b04c111 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Fri, 14 Oct 2022 20:52:12 +0800 Subject: [PATCH 1/3] Revise "save resume data" handling on shutdown When shutting down, instead of waiting for all types of alert from libtorrent, now it only waits for specific alert types. This potentially help shorten the shutdown waiting time. --- src/base/bittorrent/sessionimpl.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 6a1fd4a49..478ee59cc 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -2892,28 +2892,41 @@ void SessionImpl::saveResumeData() ++m_numResumeData; } + QElapsedTimer timer; + timer.start(); + while (m_numResumeData > 0) { - const std::vector alerts = getPendingAlerts(lt::seconds {30}); - if (alerts.empty()) - { - LogMsg(tr("Aborted saving resume data. Number of outstanding torrents: %1").arg(QString::number(m_numResumeData)) - , Log::CRITICAL); - break; - } + const lt::seconds waitTime {5}; + const lt::seconds expireTime {30}; + const std::vector alerts = getPendingAlerts(waitTime); + bool hasWantedAlert = false; for (const lt::alert *a : alerts) { switch (a->type()) { case lt::save_resume_data_failed_alert::alert_type: + hasWantedAlert = true; --m_numResumeData; break; case lt::save_resume_data_alert::alert_type: + hasWantedAlert = true; dispatchTorrentAlert(static_cast(a)); break; } } + + if (hasWantedAlert) + { + timer.start(); + } + else if (timer.hasExpired(lt::total_milliseconds(expireTime))) + { + LogMsg(tr("Aborted saving resume data. Number of outstanding torrents: %1").arg(QString::number(m_numResumeData)) + , Log::CRITICAL); + break; + } } } From c94152c47ca984daca94b0624a4d41aa02424e19 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 17 Oct 2022 02:21:03 +0800 Subject: [PATCH 2/3] Reuse alert dispatcher Instead of using a specific alert handler in `SessionImpl::saveResumeData()`, reuse the generic one. --- src/base/bittorrent/sessionimpl.cpp | 18 ++++++++++-------- src/base/bittorrent/sessionimpl.h | 1 + src/base/bittorrent/torrentimpl.cpp | 9 +++++++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 478ee59cc..04888a2c6 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -2444,6 +2444,12 @@ void SessionImpl::handleTorrentSaveResumeDataRequested(const TorrentImpl *torren ++m_numResumeData; } +void SessionImpl::handleTorrentSaveResumeDataFailed(const TorrentImpl *torrent) +{ + Q_UNUSED(torrent); + --m_numResumeData; +} + QVector SessionImpl::torrents() const { QVector result; @@ -2904,16 +2910,12 @@ void SessionImpl::saveResumeData() bool hasWantedAlert = false; for (const lt::alert *a : alerts) { - switch (a->type()) + if (const int alertType = a->type(); + (alertType == lt::save_resume_data_alert::alert_type) + || (alertType == lt::save_resume_data_failed_alert::alert_type)) { - case lt::save_resume_data_failed_alert::alert_type: - hasWantedAlert = true; - --m_numResumeData; - break; - case lt::save_resume_data_alert::alert_type: hasWantedAlert = true; - dispatchTorrentAlert(static_cast(a)); - break; + handleAlert(a); } } diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 0d105a395..c09ef72fe 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -410,6 +410,7 @@ namespace BitTorrent // Torrent interface void handleTorrentNeedSaveResumeData(const TorrentImpl *torrent); void handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent); + void handleTorrentSaveResumeDataFailed(const TorrentImpl *torrent); void handleTorrentShareLimitChanged(TorrentImpl *const torrent); void handleTorrentNameChanged(TorrentImpl *const torrent); void handleTorrentSavePathChanged(TorrentImpl *const torrent); diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index 94d65587b..d79c45df6 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -1949,8 +1949,13 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms) void TorrentImpl::handleSaveResumeDataFailedAlert(const lt::save_resume_data_failed_alert *p) { - Q_UNUSED(p); - Q_ASSERT_X(false, Q_FUNC_INFO, "This point should be unreachable since libtorrent 1.2.11"); + if (p->error != lt::errors::resume_data_not_modified) + { + LogMsg(tr("Generate resume data failed. Torrent: \"%1\". Reason: \"%2\"") + .arg(name(), QString::fromLocal8Bit(p->error.message().c_str())), Log::CRITICAL); + } + + m_session->handleTorrentSaveResumeDataFailed(this); } void TorrentImpl::handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p) From a325ab8d6e5151ae26dbcdc8626fa2db7495cb34 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 17 Oct 2022 03:17:32 +0800 Subject: [PATCH 3/3] Delay saving session statistics Pausing the libtorrent session should be scheduled before this. --- src/base/bittorrent/sessionimpl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 04888a2c6..9d85c7944 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -1030,11 +1030,12 @@ void SessionImpl::setGlobalMaxSeedingMinutes(int minutes) // Main destructor SessionImpl::~SessionImpl() { - saveStatistics(); - - // Do some BT related saving + // Do some bittorrent related saving + // After this, (ideally) no more important alerts will be generated/handled saveResumeData(); + saveStatistics(); + // We must delete FilterParserThread // before we delete lt::session delete m_filterParser;