Browse Source

Merge pull request #16922 from glassez/avoid-blocking

Avoid some blocking calls to libtorrent
adaptive-webui-19844
Vladimir Golovnev 3 years ago committed by GitHub
parent
commit
7432c4dbfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      src/base/bittorrent/session.cpp
  2. 2
      src/base/bittorrent/session.h
  3. 93
      src/base/bittorrent/torrentimpl.cpp
  4. 14
      src/base/bittorrent/torrentimpl.h

15
src/base/bittorrent/session.cpp

@ -4256,7 +4256,7 @@ bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath @@ -4256,7 +4256,7 @@ bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath
});
const bool torrentHasOutstandingJob = (iter != m_moveStorageQueue.end());
torrent->handleMoveStorageJobFinished(torrentHasOutstandingJob);
torrent->handleMoveStorageJobFinished(currentLocation, torrentHasOutstandingJob);
}
}
@ -4307,7 +4307,7 @@ void Session::moveTorrentStorage(const MoveStorageJob &job) const @@ -4307,7 +4307,7 @@ void Session::moveTorrentStorage(const MoveStorageJob &job) const
? lt::move_flags_t::always_replace_files : lt::move_flags_t::dont_replace));
}
void Session::handleMoveTorrentStorageJobFinished()
void Session::handleMoveTorrentStorageJobFinished(const Path &newPath)
{
const MoveStorageJob finishedJob = m_moveStorageQueue.takeFirst();
if (!m_moveStorageQueue.isEmpty())
@ -4324,7 +4324,7 @@ void Session::handleMoveTorrentStorageJobFinished() @@ -4324,7 +4324,7 @@ void Session::handleMoveTorrentStorageJobFinished()
TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
if (torrent)
{
torrent->handleMoveStorageJobFinished(torrentHasOutstandingJob);
torrent->handleMoveStorageJobFinished(newPath, torrentHasOutstandingJob);
}
else if (!torrentHasOutstandingJob)
{
@ -5295,7 +5295,7 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p) @@ -5295,7 +5295,7 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p)
const QString torrentName = (torrent ? torrent->name() : id.toString());
LogMsg(tr("Moved torrent successfully. Torrent: \"%1\". Destination: \"%2\"").arg(torrentName, newPath.toString()));
handleMoveTorrentStorageJobFinished();
handleMoveTorrentStorageJobFinished(newPath);
}
void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert *p)
@ -5313,12 +5313,13 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert @@ -5313,12 +5313,13 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert
TorrentImpl *torrent = m_torrents.value(id);
const QString torrentName = (torrent ? torrent->name() : id.toString());
const QString currentLocation = QString::fromStdString(p->handle.status(lt::torrent_handle::query_save_path).save_path);
const Path currentLocation = (torrent ? torrent->actualStorageLocation()
: Path(p->handle.status(lt::torrent_handle::query_save_path).save_path));
const QString errorMessage = QString::fromStdString(p->message());
LogMsg(tr("Failed to move torrent. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\". Reason: \"%4\"")
.arg(torrentName, currentLocation, currentJob.path.toString(), errorMessage), Log::WARNING);
.arg(torrentName, currentLocation.toString(), currentJob.path.toString(), errorMessage), Log::WARNING);
handleMoveTorrentStorageJobFinished();
handleMoveTorrentStorageJobFinished(currentLocation);
}
void Session::handleStateUpdateAlert(const lt::state_update_alert *p)

2
src/base/bittorrent/session.h

@ -661,7 +661,7 @@ namespace BitTorrent @@ -661,7 +661,7 @@ namespace BitTorrent
std::vector<lt::alert *> getPendingAlerts(lt::time_duration time = lt::time_duration::zero()) const;
void moveTorrentStorage(const MoveStorageJob &job) const;
void handleMoveTorrentStorageJobFinished();
void handleMoveTorrentStorageJobFinished(const Path &newPath);
void loadCategories();
void storeCategories() const;

93
src/base/bittorrent/torrentimpl.cpp

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2022 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
@ -286,6 +286,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession @@ -286,6 +286,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
m_filePaths.reserve(filesCount);
m_indexMap.reserve(filesCount);
m_filePriorities.reserve(filesCount);
m_completedFiles.resize(filesCount);
const std::vector<lt::download_priority_t> filePriorities =
resized(m_ltAddTorrentParams.file_priorities, m_ltAddTorrentParams.ti->num_files()
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
@ -839,7 +840,7 @@ Path TorrentImpl::filePath(const int index) const @@ -839,7 +840,7 @@ Path TorrentImpl::filePath(const int index) const
Path TorrentImpl::actualFilePath(const int index) const
{
const auto nativeIndex = m_torrentInfo.nativeIndexes().at(index);
return Path(m_nativeHandle.torrent_file()->files().file_path(nativeIndex));
return Path(nativeTorrentInfo()->files().file_path(nativeIndex));
}
qlonglong TorrentImpl::fileSize(const int index) const
@ -1125,6 +1126,9 @@ QVector<qreal> TorrentImpl::filesProgress() const @@ -1125,6 +1126,9 @@ QVector<qreal> TorrentImpl::filesProgress() const
if (!hasMetadata())
return {};
if (m_completedFiles.count(true) == filesCount())
return QVector<qreal>(filesCount(), 1);
std::vector<int64_t> fp;
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
@ -1422,6 +1426,7 @@ void TorrentImpl::forceRecheck() @@ -1422,6 +1426,7 @@ void TorrentImpl::forceRecheck()
m_nativeHandle.force_recheck();
m_hasMissingFiles = false;
m_unchecked = false;
m_completedFiles.fill(false);
if (isPaused())
{
@ -1509,15 +1514,23 @@ void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endp @@ -1509,15 +1514,23 @@ void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endp
m_trackerPeerCounts[trackerUrl][endpoint] = count;
}
std::shared_ptr<const libtorrent::torrent_info> TorrentImpl::nativeTorrentInfo() const
{
if (m_nativeStatus.torrent_file.expired())
m_nativeStatus.torrent_file = m_nativeHandle.torrent_file();
return m_nativeStatus.torrent_file.lock();
}
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
{
Q_ASSERT(m_filePaths.isEmpty());
lt::add_torrent_params &p = m_ltAddTorrentParams;
const std::shared_ptr<lt::torrent_info> metadata = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file());
const std::shared_ptr<lt::torrent_info> metadata = std::const_pointer_cast<lt::torrent_info>(nativeTorrentInfo());
m_torrentInfo = TorrentInfo(*metadata);
m_filePriorities.reserve(filesCount());
m_completedFiles.resize(filesCount());
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
const std::vector<lt::download_priority_t> filePriorities =
resized(p.file_priorities, metadata->files().num_files()
@ -1546,7 +1559,6 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi @@ -1546,7 +1559,6 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
applyFirstLastPiecePriority(true);
m_maintenanceJob = MaintenanceJob::None;
updateStatus();
prepareResumeData(p);
m_session->handleTorrentMetadataReceived(this);
@ -1554,6 +1566,9 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi @@ -1554,6 +1566,9 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
void TorrentImpl::reload()
{
m_completedFiles.fill(false);
m_pieces.clear();
const auto queuePos = m_nativeHandle.queue_position();
m_nativeSession->remove_torrent(m_nativeHandle, lt::session::delete_partfile);
@ -1580,6 +1595,9 @@ void TorrentImpl::reload() @@ -1580,6 +1595,9 @@ void TorrentImpl::reload()
m_nativeHandle = m_nativeSession->add_torrent(p);
if (queuePos >= lt::queue_position_t {})
m_nativeHandle.queue_position_set(queuePos);
initializeStatus(m_nativeStatus, m_ltAddTorrentParams);
updateState();
}
void TorrentImpl::pause()
@ -1614,9 +1632,8 @@ void TorrentImpl::resume(const TorrentOperatingMode mode) @@ -1614,9 +1632,8 @@ void TorrentImpl::resume(const TorrentOperatingMode mode)
{
m_hasMissingFiles = false;
m_isStopped = false;
m_ltAddTorrentParams.ti = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file());
m_ltAddTorrentParams.ti = std::const_pointer_cast<lt::torrent_info>(nativeTorrentInfo());
reload();
updateStatus();
return;
}
@ -1644,7 +1661,7 @@ void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageMode mode) @@ -1644,7 +1661,7 @@ void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageMode mode)
if (m_session->addMoveTorrentStorageJob(this, newPath, mode))
{
m_storageIsMoving = true;
updateStatus();
updateState();
}
}
@ -1660,13 +1677,16 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus) @@ -1660,13 +1677,16 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
updateStatus(nativeStatus);
}
void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const bool hasOutstandingJob)
{
m_session->handleTorrentNeedSaveResumeData(this);
m_storageIsMoving = hasOutstandingJob;
updateStatus();
if (actualStorageLocation() != path)
{
m_nativeStatus.save_path = path.toString().toStdString();
m_session->handleTorrentSavePathChanged(this);
}
if (!m_storageIsMoving)
{
@ -1675,21 +1695,18 @@ void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob) @@ -1675,21 +1695,18 @@ void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
// it can be moved to the proper location
m_hasMissingFiles = false;
m_ltAddTorrentParams.save_path = m_nativeStatus.save_path;
m_ltAddTorrentParams.ti = std::const_pointer_cast<lt::torrent_info>(m_nativeHandle.torrent_file());
m_ltAddTorrentParams.ti = std::const_pointer_cast<lt::torrent_info>(nativeTorrentInfo());
reload();
updateStatus();
}
while ((m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
m_moveFinishedTriggers.takeFirst()();
std::invoke(m_moveFinishedTriggers.dequeue());
}
}
void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
{
Q_UNUSED(p);
qDebug("\"%s\" have just finished checking.", qUtf8Printable(name()));
if (!hasMetadata())
{
@ -1698,14 +1715,16 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p) @@ -1698,14 +1715,16 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
return;
}
if (m_nativeHandle.need_save_resume_data())
m_statusUpdatedTriggers.enqueue([this]()
{
qDebug("\"%s\" have just finished checking.", qUtf8Printable(name()));
if (m_nativeStatus.need_save_resume)
m_session->handleTorrentNeedSaveResumeData(this);
if (m_fastresumeDataRejected && !m_hasMissingFiles)
m_fastresumeDataRejected = false;
updateStatus();
if (!m_hasMissingFiles)
{
if ((progress() < 1.0) && (wantedSize() > 0))
@ -1718,6 +1737,7 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p) @@ -1718,6 +1737,7 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
}
m_session->handleTorrentChecked(this);
});
}
void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p)
@ -1728,7 +1748,8 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p @@ -1728,7 +1748,8 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p
m_hasMissingFiles = false;
if (m_hasSeedStatus) return;
updateStatus();
m_statusUpdatedTriggers.enqueue([this]()
{
m_hasSeedStatus = true;
adjustStorageLocation();
@ -1740,8 +1761,8 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p @@ -1740,8 +1761,8 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p
if (isMoveInProgress() || (m_renameCount > 0))
{
if (recheckTorrentsOnCompletion)
m_moveFinishedTriggers.append([this]() { forceRecheck(); });
m_moveFinishedTriggers.append([this]() { m_session->handleTorrentFinished(this); });
m_moveFinishedTriggers.enqueue([this]() { forceRecheck(); });
m_moveFinishedTriggers.enqueue([this]() { m_session->handleTorrentFinished(this); });
}
else
{
@ -1749,6 +1770,7 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p @@ -1749,6 +1770,7 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p
forceRecheck();
m_session->handleTorrentFinished(this);
}
});
}
void TorrentImpl::handleTorrentPausedAlert(const lt::torrent_paused_alert *p)
@ -1772,7 +1794,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) @@ -1772,7 +1794,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
m_ltAddTorrentParams.have_pieces.clear();
m_ltAddTorrentParams.verified_pieces.clear();
TorrentInfo metadata = TorrentInfo(*m_nativeHandle.torrent_file());
TorrentInfo metadata = TorrentInfo(*nativeTorrentInfo());
const auto &renamedFiles = m_ltAddTorrentParams.renamed_files;
PathList filePaths = metadata.filePaths();
@ -1933,11 +1955,13 @@ void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p) @@ -1933,11 +1955,13 @@ void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
return;
if (m_session->isAppendExtensionEnabled())
{
const int fileIndex = m_indexMap.value(p->index, -1);
Q_ASSERT(fileIndex >= 0);
m_completedFiles[fileIndex] = true;
if (m_session->isAppendExtensionEnabled())
{
const Path path = filePath(fileIndex);
const Path actualPath = actualFilePath(fileIndex);
if (actualPath != path)
@ -2042,15 +2066,9 @@ void TorrentImpl::handleAlert(const lt::alert *a) @@ -2042,15 +2066,9 @@ void TorrentImpl::handleAlert(const lt::alert *a)
void TorrentImpl::manageIncompleteFiles()
{
const std::shared_ptr<const lt::torrent_info> nativeInfo = nativeTorrentInfo();
const lt::file_storage &nativeFiles = nativeInfo->files();
const bool isAppendExtensionEnabled = m_session->isAppendExtensionEnabled();
const QVector<qreal> fp = filesProgress();
if (fp.size() != filesCount())
{
qDebug() << "skip manageIncompleteFiles because of invalid torrent meta-data or empty file-progress";
return;
}
const lt::file_storage &nativeFiles = m_nativeHandle.torrent_file()->files();
for (int i = 0; i < filesCount(); ++i)
{
@ -2059,7 +2077,7 @@ void TorrentImpl::manageIncompleteFiles() @@ -2059,7 +2077,7 @@ void TorrentImpl::manageIncompleteFiles()
const auto nativeIndex = m_torrentInfo.nativeIndexes().at(i);
const Path actualPath {nativeFiles.file_path(nativeIndex)};
if (isAppendExtensionEnabled && (fileSize(i) > 0) && (fp[i] < 1))
if (isAppendExtensionEnabled && (fileSize(i) > 0) && !m_completedFiles.at(i))
{
const Path wantedPath = path + QB_EXT;
if (actualPath != wantedPath)
@ -2099,11 +2117,6 @@ bool TorrentImpl::isMoveInProgress() const @@ -2099,11 +2117,6 @@ bool TorrentImpl::isMoveInProgress() const
return m_storageIsMoving;
}
void TorrentImpl::updateStatus()
{
updateStatus(m_nativeHandle.status());
}
void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
{
m_pieces.clear();
@ -2122,6 +2135,9 @@ void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus) @@ -2122,6 +2135,9 @@ void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
else if (isDownloading())
m_unchecked = true;
}
while (!m_statusUpdatedTriggers.isEmpty())
std::invoke(m_statusUpdatedTriggers.dequeue());
}
void TorrentImpl::setRatioLimit(qreal limit)
@ -2273,13 +2289,12 @@ void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities) @@ -2273,13 +2289,12 @@ void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
// Reset 'm_hasSeedStatus' if needed in order to react again to
// 'torrent_finished_alert' and eg show tray notifications
const QVector<qreal> progress = filesProgress();
const QVector<DownloadPriority> oldPriorities = filePriorities();
for (int i = 0; i < oldPriorities.size(); ++i)
{
if ((oldPriorities[i] == DownloadPriority::Ignored)
&& (priorities[i] > DownloadPriority::Ignored)
&& (progress[i] < 1.0))
&& !m_completedFiles.at(i))
{
m_hasSeedStatus = false;
break;

14
src/base/bittorrent/torrentimpl.h

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2022 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
@ -30,11 +30,13 @@ @@ -30,11 +30,13 @@
#pragma once
#include <functional>
#include <memory>
#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/fwd.hpp>
#include <libtorrent/socket.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/torrent_status.hpp>
#include <QBitArray>
@ -239,14 +241,15 @@ namespace BitTorrent @@ -239,14 +241,15 @@ namespace BitTorrent
void handleCategoryOptionsChanged();
void handleAppendExtensionToggled();
void saveResumeData();
void handleMoveStorageJobFinished(bool hasOutstandingJob);
void handleMoveStorageJobFinished(const Path &path, bool hasOutstandingJob);
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
void updatePeerCount(const QString &trackerUrl, const lt::tcp::endpoint &endpoint, int count);
private:
using EventTrigger = std::function<void ()>;
void updateStatus();
std::shared_ptr<const lt::torrent_info> nativeTorrentInfo() const;
void updateStatus(const lt::torrent_status &nativeStatus);
void updateState();
@ -283,12 +286,13 @@ namespace BitTorrent @@ -283,12 +286,13 @@ namespace BitTorrent
Session *const m_session;
lt::session *m_nativeSession;
lt::torrent_handle m_nativeHandle;
lt::torrent_status m_nativeStatus;
mutable lt::torrent_status m_nativeStatus;
TorrentState m_state = TorrentState::Unknown;
TorrentInfo m_torrentInfo;
PathList m_filePaths;
QHash<lt::file_index_t, int> m_indexMap;
QVector<DownloadPriority> m_filePriorities;
QBitArray m_completedFiles;
SpeedMonitor m_speedMonitor;
InfoHash m_infoHash;
@ -299,6 +303,8 @@ namespace BitTorrent @@ -299,6 +303,8 @@ namespace BitTorrent
int m_renameCount = 0;
bool m_storageIsMoving = false;
QQueue<EventTrigger> m_statusUpdatedTriggers;
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;

Loading…
Cancel
Save