Revamp handling of getting resume data from libtorrent

PR #20310.
This commit is contained in:
Vladimir Golovnev 2024-01-24 15:40:08 +03:00 committed by GitHub
parent 31d456c43b
commit bab9c15913
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 66 additions and 79 deletions

View file

@ -2400,7 +2400,8 @@ void SessionImpl::banIP(const QString &ip)
bool SessionImpl::deleteTorrent(const TorrentID &id, const DeleteOption deleteOption)
{
TorrentImpl *const torrent = m_torrents.take(id);
if (!torrent) return false;
if (!torrent)
return false;
qDebug("Deleting torrent with ID: %s", qUtf8Printable(torrent->id().toString()));
emit torrentAboutToBeRemoved(torrent);
@ -2595,36 +2596,12 @@ void SessionImpl::bottomTorrentsQueuePos(const QVector<TorrentID> &ids)
m_torrentsQueueChanged = true;
}
void SessionImpl::handleTorrentNeedSaveResumeData(const TorrentImpl *torrent)
{
if (m_needSaveResumeDataTorrents.empty())
{
QMetaObject::invokeMethod(this, [this]()
{
for (const TorrentID &torrentID : asConst(m_needSaveResumeDataTorrents))
{
TorrentImpl *torrent = m_torrents.value(torrentID);
if (torrent)
torrent->saveResumeData();
}
m_needSaveResumeDataTorrents.clear();
}, Qt::QueuedConnection);
}
m_needSaveResumeDataTorrents.insert(torrent->id());
}
void SessionImpl::handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent)
void SessionImpl::handleTorrentResumeDataRequested(const TorrentImpl *torrent)
{
qDebug("Saving resume data is requested for torrent '%s'...", qUtf8Printable(torrent->name()));
++m_numResumeData;
}
void SessionImpl::handleTorrentSaveResumeDataFailed([[maybe_unused]] const TorrentImpl *torrent)
{
--m_numResumeData;
}
QVector<Torrent *> SessionImpl::torrents() const
{
QVector<Torrent *> result;
@ -3084,27 +3061,21 @@ void SessionImpl::generateResumeData()
{
for (TorrentImpl *const torrent : asConst(m_torrents))
{
if (!torrent->isValid()) continue;
if (torrent->needSaveResumeData())
{
torrent->saveResumeData();
m_needSaveResumeDataTorrents.remove(torrent->id());
}
torrent->requestResumeData();
}
}
// Called on exit
void SessionImpl::saveResumeData()
{
for (const TorrentImpl *torrent : asConst(m_torrents))
for (TorrentImpl *torrent : asConst(m_torrents))
{
// When the session is terminated due to unrecoverable error
// some of the torrent handles can be corrupted
try
{
torrent->nativeHandle().save_resume_data(lt::torrent_handle::only_if_modified);
++m_numResumeData;
torrent->requestResumeData(lt::torrent_handle::only_if_modified);
}
catch (const std::exception &) {}
}
@ -4969,8 +4940,6 @@ void SessionImpl::handleTorrentFinished(TorrentImpl *const torrent)
void SessionImpl::handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data)
{
--m_numResumeData;
m_resumeDataStorage->store(torrent->id(), data);
const auto iter = m_changedTorrentIDs.find(torrent->id());
if (iter != m_changedTorrentIDs.end())
@ -5534,6 +5503,15 @@ void SessionImpl::handleAlert(const lt::alert *a)
void SessionImpl::dispatchTorrentAlert(const lt::torrent_alert *a)
{
// The torrent can be deleted between the time the resume data was requested and
// the time we received the appropriate alert. We have to decrease `m_numResumeData` anyway,
// so we do this before checking for an existing torrent.
if ((a->type() == lt::save_resume_data_alert::alert_type)
|| (a->type() == lt::save_resume_data_failed_alert::alert_type))
{
--m_numResumeData;
}
const TorrentID torrentID {a->handle.info_hash()};
TorrentImpl *torrent = m_torrents.value(torrentID);
#ifdef QBT_USES_LIBTORRENT2
@ -5571,7 +5549,7 @@ TorrentImpl *SessionImpl::createTorrent(const lt::torrent_handle &nativeHandle,
if (params.addToQueueTop)
nativeHandle.queue_position_top();
torrent->saveResumeData(lt::torrent_handle::save_info_dict);
torrent->requestResumeData(lt::torrent_handle::save_info_dict);
// The following is useless for newly added magnet
if (torrent->hasMetadata())

View file

@ -426,9 +426,7 @@ namespace BitTorrent
void bottomTorrentsQueuePos(const QVector<TorrentID> &ids) override;
// Torrent interface
void handleTorrentNeedSaveResumeData(const TorrentImpl *torrent);
void handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent);
void handleTorrentSaveResumeDataFailed(const TorrentImpl *torrent);
void handleTorrentResumeDataRequested(const TorrentImpl *torrent);
void handleTorrentShareLimitChanged(TorrentImpl *torrent);
void handleTorrentNameChanged(TorrentImpl *torrent);
void handleTorrentSavePathChanged(TorrentImpl *torrent);
@ -755,7 +753,6 @@ namespace BitTorrent
QHash<TorrentID, TorrentImpl *> m_hybridTorrentsByAltID;
QHash<TorrentID, LoadTorrentParams> m_loadingTorrents;
QHash<TorrentID, RemovingTorrentData> m_removingTorrents;
QSet<TorrentID> m_needSaveResumeDataTorrents;
QHash<TorrentID, TorrentID> m_changedTorrentIDs;
QMap<QString, CategoryOptions> m_categories;
TagSet m_tags;

View file

@ -468,7 +468,7 @@ void TorrentImpl::setSavePath(const Path &path)
{
m_savePath = resolvedPath;
m_session->handleTorrentSavePathChanged(this);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
}
@ -496,7 +496,7 @@ void TorrentImpl::setDownloadPath(const Path &path)
{
m_downloadPath = resolvedPath;
m_session->handleTorrentSavePathChanged(this);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
}
@ -541,7 +541,7 @@ void TorrentImpl::setAutoTMMEnabled(bool enabled)
m_downloadPath = m_session->categoryDownloadPath(category());
}
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentSavingModeChanged(this);
adjustStorageLocation();
@ -621,7 +621,7 @@ void TorrentImpl::addTrackers(QVector<TrackerEntry> trackers)
std::sort(m_trackerEntries.begin(), m_trackerEntries.end()
, [](const TrackerEntry &lhs, const TrackerEntry &rhs) { return lhs.tier < rhs.tier; });
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentTrackersAdded(this, trackers);
}
@ -643,7 +643,7 @@ void TorrentImpl::removeTrackers(const QStringList &trackers)
{
m_nativeHandle.replace_trackers(nativeTrackers);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentTrackersRemoved(this, removedTrackers);
}
}
@ -670,7 +670,7 @@ void TorrentImpl::replaceTrackers(QVector<TrackerEntry> trackers)
if (isPrivate())
clearPeers();
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentTrackersChanged(this);
}
@ -714,7 +714,7 @@ void TorrentImpl::addUrlSeeds(const QVector<QUrl> &urlSeeds)
thisTorrent->m_urlSeeds = currentSeeds;
if (!addedUrlSeeds.isEmpty())
{
session->handleTorrentNeedSaveResumeData(thisTorrent);
thisTorrent->deferredRequestResumeData();
session->handleTorrentUrlSeedsAdded(thisTorrent, addedUrlSeeds);
}
});
@ -758,7 +758,7 @@ void TorrentImpl::removeUrlSeeds(const QVector<QUrl> &urlSeeds)
if (!removedUrlSeeds.isEmpty())
{
session->handleTorrentNeedSaveResumeData(thisTorrent);
thisTorrent->deferredRequestResumeData();
session->handleTorrentUrlSeedsRemoved(thisTorrent, removedUrlSeeds);
}
});
@ -799,10 +799,21 @@ bool TorrentImpl::needSaveResumeData() const
return m_nativeStatus.need_save_resume;
}
void TorrentImpl::saveResumeData(lt::resume_data_flags_t flags)
void TorrentImpl::requestResumeData(const lt::resume_data_flags_t flags)
{
m_nativeHandle.save_resume_data(flags);
m_session->handleTorrentSaveResumeDataRequested(this);
m_deferredRequestResumeDataInvoked = false;
m_session->handleTorrentResumeDataRequested(this);
}
void TorrentImpl::deferredRequestResumeData()
{
if (!m_deferredRequestResumeDataInvoked)
{
QMetaObject::invokeMethod(this, [this] { requestResumeData(); }, Qt::QueuedConnection);
m_deferredRequestResumeDataInvoked = true;
}
}
int TorrentImpl::filesCount() const
@ -881,7 +892,7 @@ bool TorrentImpl::addTag(const Tag &tag)
return false;
}
m_tags.insert(tag);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentTagAdded(this, tag);
return true;
}
@ -890,7 +901,7 @@ bool TorrentImpl::removeTag(const Tag &tag)
{
if (m_tags.remove(tag))
{
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentTagRemoved(this, tag);
return true;
}
@ -1521,7 +1532,7 @@ void TorrentImpl::setName(const QString &name)
if (m_name != name)
{
m_name = name;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentNameChanged(this);
}
}
@ -1535,7 +1546,7 @@ bool TorrentImpl::setCategory(const QString &category)
const QString oldCategory = m_category;
m_category = category;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentCategoryChanged(this, oldCategory);
if (m_useAutoTMM)
@ -1600,7 +1611,7 @@ void TorrentImpl::setSequentialDownload(const bool enable)
m_nativeStatus.flags &= ~lt::torrent_flags::sequential_download; // prevent return cached value
}
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setFirstLastPiecePriority(const bool enabled)
@ -1615,7 +1626,7 @@ void TorrentImpl::setFirstLastPiecePriority(const bool enabled)
LogMsg(tr("Download first and last piece first: %1, torrent: '%2'")
.arg((enabled ? tr("On") : tr("Off")), name()));
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::applyFirstLastPiecePriority(const bool enabled)
@ -1824,7 +1835,7 @@ void TorrentImpl::pause()
{
m_stopCondition = StopCondition::None;
m_isStopped = true;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentPaused(this);
}
@ -1859,7 +1870,7 @@ void TorrentImpl::resume(const TorrentOperatingMode mode)
if (m_isStopped)
{
m_isStopped = false;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentResumed(this);
}
@ -1918,7 +1929,7 @@ void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const MoveStora
m_nativeStatus.save_path = path.toString().toStdString();
m_session->handleTorrentSavePathChanged(this);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
if (!m_storageIsMoving)
{
@ -1976,7 +1987,7 @@ void TorrentImpl::handleTorrentCheckedAlert([[maybe_unused]] const lt::torrent_c
}
if (m_nativeStatus.need_save_resume)
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentChecked(this);
});
@ -1993,7 +2004,7 @@ void TorrentImpl::handleTorrentFinishedAlert([[maybe_unused]] const lt::torrent_
adjustStorageLocation();
manageActualFilePaths();
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
const bool recheckTorrentsOnCompletion = Preferences::instance()->recheckTorrentsOnCompletion();
if (recheckTorrentsOnCompletion && m_unchecked)
@ -2137,8 +2148,6 @@ void TorrentImpl::handleSaveResumeDataFailedAlert(const lt::save_resume_data_fai
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)
@ -2216,7 +2225,7 @@ void TorrentImpl::handleFileRenamedAlert(const lt::file_renamed_alert *p)
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
m_moveFinishedTriggers.takeFirst()();
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert *p)
@ -2231,7 +2240,7 @@ void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
m_moveFinishedTriggers.takeFirst()();
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
@ -2274,7 +2283,7 @@ void TorrentImpl::handleFileErrorAlert(const lt::file_error_alert *p)
#ifdef QBT_USES_LIBTORRENT2
void TorrentImpl::handleFilePrioAlert(const lt::file_prio_alert *)
{
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
#endif
@ -2290,7 +2299,7 @@ void TorrentImpl::handleMetadataReceivedAlert([[maybe_unused]] const lt::metadat
#endif
m_maintenanceJob = MaintenanceJob::HandleMetadata;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::handlePerformanceAlert(const lt::performance_alert *p) const
@ -2540,7 +2549,7 @@ void TorrentImpl::setRatioLimit(qreal limit)
if (m_ratioLimit != limit)
{
m_ratioLimit = limit;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentShareLimitChanged(this);
}
}
@ -2555,7 +2564,7 @@ void TorrentImpl::setSeedingTimeLimit(int limit)
if (m_seedingTimeLimit != limit)
{
m_seedingTimeLimit = limit;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentShareLimitChanged(this);
}
}
@ -2570,7 +2579,7 @@ void TorrentImpl::setInactiveSeedingTimeLimit(int limit)
if (m_inactiveSeedingTimeLimit != limit)
{
m_inactiveSeedingTimeLimit = limit;
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
m_session->handleTorrentShareLimitChanged(this);
}
}
@ -2583,7 +2592,7 @@ void TorrentImpl::setUploadLimit(const int limit)
m_uploadLimit = cleanValue;
m_nativeHandle.set_upload_limit(m_uploadLimit);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setDownloadLimit(const int limit)
@ -2594,7 +2603,7 @@ void TorrentImpl::setDownloadLimit(const int limit)
m_downloadLimit = cleanValue;
m_nativeHandle.set_download_limit(m_downloadLimit);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setSuperSeeding(const bool enable)
@ -2607,7 +2616,7 @@ void TorrentImpl::setSuperSeeding(const bool enable)
else
m_nativeHandle.unset_flags(lt::torrent_flags::super_seeding);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setDHTDisabled(const bool disable)
@ -2620,7 +2629,7 @@ void TorrentImpl::setDHTDisabled(const bool disable)
else
m_nativeHandle.unset_flags(lt::torrent_flags::disable_dht);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setPEXDisabled(const bool disable)
@ -2633,7 +2642,7 @@ void TorrentImpl::setPEXDisabled(const bool disable)
else
m_nativeHandle.unset_flags(lt::torrent_flags::disable_pex);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::setLSDDisabled(const bool disable)
@ -2646,7 +2655,7 @@ void TorrentImpl::setLSDDisabled(const bool disable)
else
m_nativeHandle.unset_flags(lt::torrent_flags::disable_lsd);
m_session->handleTorrentNeedSaveResumeData(this);
deferredRequestResumeData();
}
void TorrentImpl::flushCache() const

View file

@ -264,7 +264,8 @@ namespace BitTorrent
void handleCategoryOptionsChanged();
void handleAppendExtensionToggled();
void handleUnwantedFolderToggled();
void saveResumeData(lt::resume_data_flags_t flags = {});
void requestResumeData(lt::resume_data_flags_t flags = {});
void deferredRequestResumeData();
void handleMoveStorageJobFinished(const Path &path, MoveStorageContext context, bool hasOutstandingJob);
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
TrackerEntry updateTrackerEntry(const lt::announce_entry &announceEntry, const QHash<lt::tcp::endpoint, QMap<int, int>> &updateInfo);
@ -372,5 +373,7 @@ namespace BitTorrent
QBitArray m_pieces;
QVector<std::int64_t> m_filesProgress;
bool m_deferredRequestResumeDataInvoked = false;
};
}