diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index d4c1b4fe3..cebfca167 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include #include #include @@ -303,6 +305,17 @@ namespace }; } + using ListType = lt::entry::list_type; + + ListType setToEntryList(const QSet &input) + { + ListType entryList; + entryList.reserve(input.size()); + for (const QString &setValue : input) + entryList.emplace_back(setValue.toStdString()); + return entryList; + } + #ifdef Q_OS_WIN QString convertIfaceNameToGuid(const QString &name) { @@ -3926,16 +3939,52 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent) emit allTorrentsFinished(); } -void Session::handleTorrentResumeDataReady(TorrentImpl *const torrent, const std::shared_ptr &data) +void Session::handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data) { --m_numResumeData; + // We need to adjust native libtorrent resume data + lt::add_torrent_params p = data.ltAddTorrentParams; + p.save_path = Profile::instance()->toPortablePath(QString::fromStdString(p.save_path)).toStdString(); + if (data.paused) + { + p.flags |= lt::torrent_flags::paused; + p.flags &= ~lt::torrent_flags::auto_managed; + } + else + { + // Torrent can be actually "running" but temporarily "paused" to perform some + // service jobs behind the scenes so we need to restore it as "running" + if (!data.forced) + { + p.flags |= lt::torrent_flags::auto_managed; + } + else + { + p.flags &= ~lt::torrent_flags::paused; + p.flags &= ~lt::torrent_flags::auto_managed; + } + } + // Separated thread is used for the blocking IO which results in slow processing of many torrents. // Copying lt::entry objects around isn't cheap. + auto resumeDataPtr = std::make_shared(lt::write_resume_data(p)); + lt::entry &resumeData = *resumeDataPtr; + + resumeData["qBt-savePath"] = Profile::instance()->toPortablePath(data.savePath).toStdString(); + resumeData["qBt-ratioLimit"] = static_cast(data.ratioLimit * 1000); + resumeData["qBt-seedingTimeLimit"] = data.seedingTimeLimit; + resumeData["qBt-category"] = data.category.toStdString(); + resumeData["qBt-tags"] = setToEntryList(data.tags); + resumeData["qBt-name"] = data.name.toStdString(); + resumeData["qBt-seedStatus"] = data.hasSeedStatus; + resumeData["qBt-contentLayout"] = Utils::String::fromEnum(data.contentLayout).toStdString(); + resumeData["qBt-firstLastPiecePriority"] = data.firstLastPiecePriority; + const QString filename = QString::fromLatin1("%1.fastresume").arg(torrent->id().toString()); QMetaObject::invokeMethod(m_resumeDataSavingManager - , [this, filename, data]() { m_resumeDataSavingManager->save(filename, data); }); + , [this, filename, resumeDataPtr]() { m_resumeDataSavingManager->save(filename, resumeDataPtr); }); } void Session::handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl) diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index c8752d645..c6bd8c813 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -484,7 +484,7 @@ namespace BitTorrent void handleTorrentTrackersChanged(TorrentImpl *const torrent); void handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector &newUrlSeeds); void handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector &urlSeeds); - void handleTorrentResumeDataReady(TorrentImpl *const torrent, const std::shared_ptr &data); + void handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data); void handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl); void handleTorrentTrackerWarning(TorrentImpl *const torrent, const QString &trackerUrl); void handleTorrentTrackerError(TorrentImpl *const torrent, const QString &trackerUrl); diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index cae29edb8..bbc1bde31 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -39,13 +39,11 @@ #include #include -#include #include #include #include #include #include -#include #if (LIBTORRENT_VERSION_NUM >= 20000) #include @@ -61,7 +59,6 @@ #include "base/global.h" #include "base/logger.h" #include "base/preferences.h" -#include "base/profile.h" #include "base/utils/fs.h" #include "base/utils/string.h" #include "common.h" @@ -91,16 +88,6 @@ namespace return out; } - using ListType = lt::entry::list_type; - - ListType setToEntryList(const QSet &input) - { - ListType entryList; - for (const QString &setValue : input) - entryList.emplace_back(setValue.toStdString()); - return entryList; - } - lt::announce_entry makeNativeAnnouncerEntry(const QString &url, const int tier) { lt::announce_entry entry {url.toStdString()}; @@ -1759,29 +1746,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) m_ltAddTorrentParams = p->params; } - if (m_isStopped) - { - m_ltAddTorrentParams.flags |= lt::torrent_flags::paused; - m_ltAddTorrentParams.flags &= ~lt::torrent_flags::auto_managed; - } - else - { - // Torrent can be actually "running" but temporarily "paused" to perform some - // service jobs behind the scenes so we need to restore it as "running" - if (m_operatingMode == TorrentOperatingMode::AutoManaged) - { - m_ltAddTorrentParams.flags |= lt::torrent_flags::auto_managed; - } - else - { - m_ltAddTorrentParams.flags &= ~lt::torrent_flags::paused; - m_ltAddTorrentParams.flags &= ~lt::torrent_flags::auto_managed; - } - } - m_ltAddTorrentParams.added_time = addedTime().toSecsSinceEpoch(); - m_ltAddTorrentParams.save_path = Profile::instance()->toPortablePath( - QString::fromStdString(m_ltAddTorrentParams.save_path)).toStdString(); if (m_maintenanceJob == MaintenanceJob::HandleMetadata) { @@ -1794,20 +1759,21 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) m_session->findIncompleteFiles(metadata, m_savePath); } - auto resumeDataPtr = std::make_shared(lt::write_resume_data(m_ltAddTorrentParams)); - lt::entry &resumeData = *resumeDataPtr; - - resumeData["qBt-savePath"] = m_useAutoTMM ? "" : Profile::instance()->toPortablePath(m_savePath).toStdString(); - resumeData["qBt-ratioLimit"] = static_cast(m_ratioLimit * 1000); - resumeData["qBt-seedingTimeLimit"] = m_seedingTimeLimit; - resumeData["qBt-category"] = m_category.toStdString(); - resumeData["qBt-tags"] = setToEntryList(m_tags); - resumeData["qBt-name"] = m_name.toStdString(); - resumeData["qBt-seedStatus"] = m_hasSeedStatus; - resumeData["qBt-contentLayout"] = Utils::String::fromEnum(m_contentLayout).toStdString(); - resumeData["qBt-firstLastPiecePriority"] = m_hasFirstLastPiecePriority; - - m_session->handleTorrentResumeDataReady(this, resumeDataPtr); + LoadTorrentParams resumeData; + resumeData.name = m_name; + resumeData.category = m_category; + resumeData.savePath = m_useAutoTMM ? "" : m_savePath; + resumeData.tags = m_tags; + resumeData.contentLayout = m_contentLayout; + resumeData.ratioLimit = m_ratioLimit; + resumeData.seedingTimeLimit = m_seedingTimeLimit; + resumeData.firstLastPiecePriority = m_hasFirstLastPiecePriority; + resumeData.hasSeedStatus = m_hasSeedStatus; + resumeData.paused = m_isStopped; + resumeData.forced = (m_operatingMode == TorrentOperatingMode::Forced); + resumeData.ltAddTorrentParams = m_ltAddTorrentParams; + + m_session->handleTorrentResumeDataReady(this, resumeData); } void TorrentImpl::handleSaveResumeDataFailedAlert(const lt::save_resume_data_failed_alert *p)