mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-25 14:04:23 +00:00
Merge pull request #16922 from glassez/avoid-blocking
Avoid some blocking calls to libtorrent
This commit is contained in:
commit
7432c4dbfe
@ -4256,7 +4256,7 @@ bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath
|
|||||||
});
|
});
|
||||||
|
|
||||||
const bool torrentHasOutstandingJob = (iter != m_moveStorageQueue.end());
|
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
|
|||||||
? lt::move_flags_t::always_replace_files : lt::move_flags_t::dont_replace));
|
? 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();
|
const MoveStorageJob finishedJob = m_moveStorageQueue.takeFirst();
|
||||||
if (!m_moveStorageQueue.isEmpty())
|
if (!m_moveStorageQueue.isEmpty())
|
||||||
@ -4324,7 +4324,7 @@ void Session::handleMoveTorrentStorageJobFinished()
|
|||||||
TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
|
TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
|
||||||
if (torrent)
|
if (torrent)
|
||||||
{
|
{
|
||||||
torrent->handleMoveStorageJobFinished(torrentHasOutstandingJob);
|
torrent->handleMoveStorageJobFinished(newPath, torrentHasOutstandingJob);
|
||||||
}
|
}
|
||||||
else if (!torrentHasOutstandingJob)
|
else if (!torrentHasOutstandingJob)
|
||||||
{
|
{
|
||||||
@ -5295,7 +5295,7 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p)
|
|||||||
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
||||||
LogMsg(tr("Moved torrent successfully. Torrent: \"%1\". Destination: \"%2\"").arg(torrentName, newPath.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)
|
void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert *p)
|
||||||
@ -5313,12 +5313,13 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert
|
|||||||
|
|
||||||
TorrentImpl *torrent = m_torrents.value(id);
|
TorrentImpl *torrent = m_torrents.value(id);
|
||||||
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
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());
|
const QString errorMessage = QString::fromStdString(p->message());
|
||||||
LogMsg(tr("Failed to move torrent. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\". Reason: \"%4\"")
|
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)
|
void Session::handleStateUpdateAlert(const lt::state_update_alert *p)
|
||||||
|
@ -661,7 +661,7 @@ namespace BitTorrent
|
|||||||
std::vector<lt::alert *> getPendingAlerts(lt::time_duration time = lt::time_duration::zero()) const;
|
std::vector<lt::alert *> getPendingAlerts(lt::time_duration time = lt::time_duration::zero()) const;
|
||||||
|
|
||||||
void moveTorrentStorage(const MoveStorageJob &job) const;
|
void moveTorrentStorage(const MoveStorageJob &job) const;
|
||||||
void handleMoveTorrentStorageJobFinished();
|
void handleMoveTorrentStorageJobFinished(const Path &newPath);
|
||||||
|
|
||||||
void loadCategories();
|
void loadCategories();
|
||||||
void storeCategories() const;
|
void storeCategories() const;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* 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>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -286,6 +286,7 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
|||||||
m_filePaths.reserve(filesCount);
|
m_filePaths.reserve(filesCount);
|
||||||
m_indexMap.reserve(filesCount);
|
m_indexMap.reserve(filesCount);
|
||||||
m_filePriorities.reserve(filesCount);
|
m_filePriorities.reserve(filesCount);
|
||||||
|
m_completedFiles.resize(filesCount);
|
||||||
const std::vector<lt::download_priority_t> filePriorities =
|
const std::vector<lt::download_priority_t> filePriorities =
|
||||||
resized(m_ltAddTorrentParams.file_priorities, m_ltAddTorrentParams.ti->num_files()
|
resized(m_ltAddTorrentParams.file_priorities, m_ltAddTorrentParams.ti->num_files()
|
||||||
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
|
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
|
||||||
@ -839,7 +840,7 @@ Path TorrentImpl::filePath(const int index) const
|
|||||||
Path TorrentImpl::actualFilePath(const int index) const
|
Path TorrentImpl::actualFilePath(const int index) const
|
||||||
{
|
{
|
||||||
const auto nativeIndex = m_torrentInfo.nativeIndexes().at(index);
|
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
|
qlonglong TorrentImpl::fileSize(const int index) const
|
||||||
@ -1125,6 +1126,9 @@ QVector<qreal> TorrentImpl::filesProgress() const
|
|||||||
if (!hasMetadata())
|
if (!hasMetadata())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
if (m_completedFiles.count(true) == filesCount())
|
||||||
|
return QVector<qreal>(filesCount(), 1);
|
||||||
|
|
||||||
std::vector<int64_t> fp;
|
std::vector<int64_t> fp;
|
||||||
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
m_nativeHandle.file_progress(fp, lt::torrent_handle::piece_granularity);
|
||||||
|
|
||||||
@ -1422,6 +1426,7 @@ void TorrentImpl::forceRecheck()
|
|||||||
m_nativeHandle.force_recheck();
|
m_nativeHandle.force_recheck();
|
||||||
m_hasMissingFiles = false;
|
m_hasMissingFiles = false;
|
||||||
m_unchecked = false;
|
m_unchecked = false;
|
||||||
|
m_completedFiles.fill(false);
|
||||||
|
|
||||||
if (isPaused())
|
if (isPaused())
|
||||||
{
|
{
|
||||||
@ -1509,15 +1514,23 @@ void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endp
|
|||||||
m_trackerPeerCounts[trackerUrl][endpoint] = count;
|
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)
|
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_filePaths.isEmpty());
|
Q_ASSERT(m_filePaths.isEmpty());
|
||||||
|
|
||||||
lt::add_torrent_params &p = m_ltAddTorrentParams;
|
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_torrentInfo = TorrentInfo(*metadata);
|
||||||
m_filePriorities.reserve(filesCount());
|
m_filePriorities.reserve(filesCount());
|
||||||
|
m_completedFiles.resize(filesCount());
|
||||||
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
|
const auto nativeIndexes = m_torrentInfo.nativeIndexes();
|
||||||
const std::vector<lt::download_priority_t> filePriorities =
|
const std::vector<lt::download_priority_t> filePriorities =
|
||||||
resized(p.file_priorities, metadata->files().num_files()
|
resized(p.file_priorities, metadata->files().num_files()
|
||||||
@ -1546,7 +1559,6 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
|
|||||||
applyFirstLastPiecePriority(true);
|
applyFirstLastPiecePriority(true);
|
||||||
|
|
||||||
m_maintenanceJob = MaintenanceJob::None;
|
m_maintenanceJob = MaintenanceJob::None;
|
||||||
updateStatus();
|
|
||||||
prepareResumeData(p);
|
prepareResumeData(p);
|
||||||
|
|
||||||
m_session->handleTorrentMetadataReceived(this);
|
m_session->handleTorrentMetadataReceived(this);
|
||||||
@ -1554,6 +1566,9 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi
|
|||||||
|
|
||||||
void TorrentImpl::reload()
|
void TorrentImpl::reload()
|
||||||
{
|
{
|
||||||
|
m_completedFiles.fill(false);
|
||||||
|
m_pieces.clear();
|
||||||
|
|
||||||
const auto queuePos = m_nativeHandle.queue_position();
|
const auto queuePos = m_nativeHandle.queue_position();
|
||||||
|
|
||||||
m_nativeSession->remove_torrent(m_nativeHandle, lt::session::delete_partfile);
|
m_nativeSession->remove_torrent(m_nativeHandle, lt::session::delete_partfile);
|
||||||
@ -1580,6 +1595,9 @@ void TorrentImpl::reload()
|
|||||||
m_nativeHandle = m_nativeSession->add_torrent(p);
|
m_nativeHandle = m_nativeSession->add_torrent(p);
|
||||||
if (queuePos >= lt::queue_position_t {})
|
if (queuePos >= lt::queue_position_t {})
|
||||||
m_nativeHandle.queue_position_set(queuePos);
|
m_nativeHandle.queue_position_set(queuePos);
|
||||||
|
|
||||||
|
initializeStatus(m_nativeStatus, m_ltAddTorrentParams);
|
||||||
|
updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::pause()
|
void TorrentImpl::pause()
|
||||||
@ -1614,9 +1632,8 @@ void TorrentImpl::resume(const TorrentOperatingMode mode)
|
|||||||
{
|
{
|
||||||
m_hasMissingFiles = false;
|
m_hasMissingFiles = false;
|
||||||
m_isStopped = 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();
|
reload();
|
||||||
updateStatus();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1644,7 +1661,7 @@ void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageMode mode)
|
|||||||
if (m_session->addMoveTorrentStorageJob(this, newPath, mode))
|
if (m_session->addMoveTorrentStorageJob(this, newPath, mode))
|
||||||
{
|
{
|
||||||
m_storageIsMoving = true;
|
m_storageIsMoving = true;
|
||||||
updateStatus();
|
updateState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1660,13 +1677,16 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
|
|||||||
updateStatus(nativeStatus);
|
updateStatus(nativeStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
|
void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const bool hasOutstandingJob)
|
||||||
{
|
{
|
||||||
m_session->handleTorrentNeedSaveResumeData(this);
|
m_session->handleTorrentNeedSaveResumeData(this);
|
||||||
m_storageIsMoving = hasOutstandingJob;
|
m_storageIsMoving = hasOutstandingJob;
|
||||||
|
|
||||||
updateStatus();
|
if (actualStorageLocation() != path)
|
||||||
m_session->handleTorrentSavePathChanged(this);
|
{
|
||||||
|
m_nativeStatus.save_path = path.toString().toStdString();
|
||||||
|
m_session->handleTorrentSavePathChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_storageIsMoving)
|
if (!m_storageIsMoving)
|
||||||
{
|
{
|
||||||
@ -1675,21 +1695,18 @@ void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
|
|||||||
// it can be moved to the proper location
|
// it can be moved to the proper location
|
||||||
m_hasMissingFiles = false;
|
m_hasMissingFiles = false;
|
||||||
m_ltAddTorrentParams.save_path = m_nativeStatus.save_path;
|
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();
|
reload();
|
||||||
updateStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
while ((m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
|
||||||
m_moveFinishedTriggers.takeFirst()();
|
std::invoke(m_moveFinishedTriggers.dequeue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
||||||
{
|
{
|
||||||
Q_UNUSED(p);
|
Q_UNUSED(p);
|
||||||
qDebug("\"%s\" have just finished checking.", qUtf8Printable(name()));
|
|
||||||
|
|
||||||
|
|
||||||
if (!hasMetadata())
|
if (!hasMetadata())
|
||||||
{
|
{
|
||||||
@ -1698,26 +1715,29 @@ void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nativeHandle.need_save_resume_data())
|
m_statusUpdatedTriggers.enqueue([this]()
|
||||||
m_session->handleTorrentNeedSaveResumeData(this);
|
|
||||||
|
|
||||||
if (m_fastresumeDataRejected && !m_hasMissingFiles)
|
|
||||||
m_fastresumeDataRejected = false;
|
|
||||||
|
|
||||||
updateStatus();
|
|
||||||
|
|
||||||
if (!m_hasMissingFiles)
|
|
||||||
{
|
{
|
||||||
if ((progress() < 1.0) && (wantedSize() > 0))
|
qDebug("\"%s\" have just finished checking.", qUtf8Printable(name()));
|
||||||
m_hasSeedStatus = false;
|
|
||||||
else if (progress() == 1.0)
|
|
||||||
m_hasSeedStatus = true;
|
|
||||||
|
|
||||||
adjustStorageLocation();
|
if (m_nativeStatus.need_save_resume)
|
||||||
manageIncompleteFiles();
|
m_session->handleTorrentNeedSaveResumeData(this);
|
||||||
}
|
|
||||||
|
|
||||||
m_session->handleTorrentChecked(this);
|
if (m_fastresumeDataRejected && !m_hasMissingFiles)
|
||||||
|
m_fastresumeDataRejected = false;
|
||||||
|
|
||||||
|
if (!m_hasMissingFiles)
|
||||||
|
{
|
||||||
|
if ((progress() < 1.0) && (wantedSize() > 0))
|
||||||
|
m_hasSeedStatus = false;
|
||||||
|
else if (progress() == 1.0)
|
||||||
|
m_hasSeedStatus = true;
|
||||||
|
|
||||||
|
adjustStorageLocation();
|
||||||
|
manageIncompleteFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_session->handleTorrentChecked(this);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p)
|
void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p)
|
||||||
@ -1728,27 +1748,29 @@ void TorrentImpl::handleTorrentFinishedAlert(const lt::torrent_finished_alert *p
|
|||||||
m_hasMissingFiles = false;
|
m_hasMissingFiles = false;
|
||||||
if (m_hasSeedStatus) return;
|
if (m_hasSeedStatus) return;
|
||||||
|
|
||||||
updateStatus();
|
m_statusUpdatedTriggers.enqueue([this]()
|
||||||
m_hasSeedStatus = true;
|
|
||||||
|
|
||||||
adjustStorageLocation();
|
|
||||||
manageIncompleteFiles();
|
|
||||||
|
|
||||||
m_session->handleTorrentNeedSaveResumeData(this);
|
|
||||||
|
|
||||||
const bool recheckTorrentsOnCompletion = Preferences::instance()->recheckTorrentsOnCompletion();
|
|
||||||
if (isMoveInProgress() || (m_renameCount > 0))
|
|
||||||
{
|
{
|
||||||
if (recheckTorrentsOnCompletion)
|
m_hasSeedStatus = true;
|
||||||
m_moveFinishedTriggers.append([this]() { forceRecheck(); });
|
|
||||||
m_moveFinishedTriggers.append([this]() { m_session->handleTorrentFinished(this); });
|
adjustStorageLocation();
|
||||||
}
|
manageIncompleteFiles();
|
||||||
else
|
|
||||||
{
|
m_session->handleTorrentNeedSaveResumeData(this);
|
||||||
if (recheckTorrentsOnCompletion && m_unchecked)
|
|
||||||
forceRecheck();
|
const bool recheckTorrentsOnCompletion = Preferences::instance()->recheckTorrentsOnCompletion();
|
||||||
m_session->handleTorrentFinished(this);
|
if (isMoveInProgress() || (m_renameCount > 0))
|
||||||
}
|
{
|
||||||
|
if (recheckTorrentsOnCompletion)
|
||||||
|
m_moveFinishedTriggers.enqueue([this]() { forceRecheck(); });
|
||||||
|
m_moveFinishedTriggers.enqueue([this]() { m_session->handleTorrentFinished(this); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (recheckTorrentsOnCompletion && m_unchecked)
|
||||||
|
forceRecheck();
|
||||||
|
m_session->handleTorrentFinished(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleTorrentPausedAlert(const lt::torrent_paused_alert *p)
|
void TorrentImpl::handleTorrentPausedAlert(const lt::torrent_paused_alert *p)
|
||||||
@ -1772,7 +1794,7 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
|
|||||||
m_ltAddTorrentParams.have_pieces.clear();
|
m_ltAddTorrentParams.have_pieces.clear();
|
||||||
m_ltAddTorrentParams.verified_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;
|
const auto &renamedFiles = m_ltAddTorrentParams.renamed_files;
|
||||||
PathList filePaths = metadata.filePaths();
|
PathList filePaths = metadata.filePaths();
|
||||||
@ -1933,11 +1955,13 @@ void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p)
|
|||||||
if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
|
if (m_maintenanceJob == MaintenanceJob::HandleMetadata)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const int fileIndex = m_indexMap.value(p->index, -1);
|
||||||
|
Q_ASSERT(fileIndex >= 0);
|
||||||
|
|
||||||
|
m_completedFiles[fileIndex] = true;
|
||||||
|
|
||||||
if (m_session->isAppendExtensionEnabled())
|
if (m_session->isAppendExtensionEnabled())
|
||||||
{
|
{
|
||||||
const int fileIndex = m_indexMap.value(p->index, -1);
|
|
||||||
Q_ASSERT(fileIndex >= 0);
|
|
||||||
|
|
||||||
const Path path = filePath(fileIndex);
|
const Path path = filePath(fileIndex);
|
||||||
const Path actualPath = actualFilePath(fileIndex);
|
const Path actualPath = actualFilePath(fileIndex);
|
||||||
if (actualPath != path)
|
if (actualPath != path)
|
||||||
@ -2042,15 +2066,9 @@ void TorrentImpl::handleAlert(const lt::alert *a)
|
|||||||
|
|
||||||
void TorrentImpl::manageIncompleteFiles()
|
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 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)
|
for (int i = 0; i < filesCount(); ++i)
|
||||||
{
|
{
|
||||||
@ -2059,7 +2077,7 @@ void TorrentImpl::manageIncompleteFiles()
|
|||||||
const auto nativeIndex = m_torrentInfo.nativeIndexes().at(i);
|
const auto nativeIndex = m_torrentInfo.nativeIndexes().at(i);
|
||||||
const Path actualPath {nativeFiles.file_path(nativeIndex)};
|
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;
|
const Path wantedPath = path + QB_EXT;
|
||||||
if (actualPath != wantedPath)
|
if (actualPath != wantedPath)
|
||||||
@ -2099,11 +2117,6 @@ bool TorrentImpl::isMoveInProgress() const
|
|||||||
return m_storageIsMoving;
|
return m_storageIsMoving;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::updateStatus()
|
|
||||||
{
|
|
||||||
updateStatus(m_nativeHandle.status());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
|
void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
|
||||||
{
|
{
|
||||||
m_pieces.clear();
|
m_pieces.clear();
|
||||||
@ -2122,6 +2135,9 @@ void TorrentImpl::updateStatus(const lt::torrent_status &nativeStatus)
|
|||||||
else if (isDownloading())
|
else if (isDownloading())
|
||||||
m_unchecked = true;
|
m_unchecked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!m_statusUpdatedTriggers.isEmpty())
|
||||||
|
std::invoke(m_statusUpdatedTriggers.dequeue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::setRatioLimit(qreal limit)
|
void TorrentImpl::setRatioLimit(qreal limit)
|
||||||
@ -2273,13 +2289,12 @@ void TorrentImpl::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
|||||||
|
|
||||||
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
||||||
// 'torrent_finished_alert' and eg show tray notifications
|
// 'torrent_finished_alert' and eg show tray notifications
|
||||||
const QVector<qreal> progress = filesProgress();
|
|
||||||
const QVector<DownloadPriority> oldPriorities = filePriorities();
|
const QVector<DownloadPriority> oldPriorities = filePriorities();
|
||||||
for (int i = 0; i < oldPriorities.size(); ++i)
|
for (int i = 0; i < oldPriorities.size(); ++i)
|
||||||
{
|
{
|
||||||
if ((oldPriorities[i] == DownloadPriority::Ignored)
|
if ((oldPriorities[i] == DownloadPriority::Ignored)
|
||||||
&& (priorities[i] > DownloadPriority::Ignored)
|
&& (priorities[i] > DownloadPriority::Ignored)
|
||||||
&& (progress[i] < 1.0))
|
&& !m_completedFiles.at(i))
|
||||||
{
|
{
|
||||||
m_hasSeedStatus = false;
|
m_hasSeedStatus = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt and libtorrent.
|
* 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>
|
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@ -30,11 +30,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <libtorrent/add_torrent_params.hpp>
|
#include <libtorrent/add_torrent_params.hpp>
|
||||||
#include <libtorrent/fwd.hpp>
|
#include <libtorrent/fwd.hpp>
|
||||||
#include <libtorrent/socket.hpp>
|
#include <libtorrent/socket.hpp>
|
||||||
#include <libtorrent/torrent_handle.hpp>
|
#include <libtorrent/torrent_handle.hpp>
|
||||||
|
#include <libtorrent/torrent_info.hpp>
|
||||||
#include <libtorrent/torrent_status.hpp>
|
#include <libtorrent/torrent_status.hpp>
|
||||||
|
|
||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
@ -239,14 +241,15 @@ namespace BitTorrent
|
|||||||
void handleCategoryOptionsChanged();
|
void handleCategoryOptionsChanged();
|
||||||
void handleAppendExtensionToggled();
|
void handleAppendExtensionToggled();
|
||||||
void saveResumeData();
|
void saveResumeData();
|
||||||
void handleMoveStorageJobFinished(bool hasOutstandingJob);
|
void handleMoveStorageJobFinished(const Path &path, bool hasOutstandingJob);
|
||||||
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
|
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
|
||||||
void updatePeerCount(const QString &trackerUrl, const lt::tcp::endpoint &endpoint, int count);
|
void updatePeerCount(const QString &trackerUrl, const lt::tcp::endpoint &endpoint, int count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using EventTrigger = std::function<void ()>;
|
using EventTrigger = std::function<void ()>;
|
||||||
|
|
||||||
void updateStatus();
|
std::shared_ptr<const lt::torrent_info> nativeTorrentInfo() const;
|
||||||
|
|
||||||
void updateStatus(const lt::torrent_status &nativeStatus);
|
void updateStatus(const lt::torrent_status &nativeStatus);
|
||||||
void updateState();
|
void updateState();
|
||||||
|
|
||||||
@ -283,12 +286,13 @@ namespace BitTorrent
|
|||||||
Session *const m_session;
|
Session *const m_session;
|
||||||
lt::session *m_nativeSession;
|
lt::session *m_nativeSession;
|
||||||
lt::torrent_handle m_nativeHandle;
|
lt::torrent_handle m_nativeHandle;
|
||||||
lt::torrent_status m_nativeStatus;
|
mutable lt::torrent_status m_nativeStatus;
|
||||||
TorrentState m_state = TorrentState::Unknown;
|
TorrentState m_state = TorrentState::Unknown;
|
||||||
TorrentInfo m_torrentInfo;
|
TorrentInfo m_torrentInfo;
|
||||||
PathList m_filePaths;
|
PathList m_filePaths;
|
||||||
QHash<lt::file_index_t, int> m_indexMap;
|
QHash<lt::file_index_t, int> m_indexMap;
|
||||||
QVector<DownloadPriority> m_filePriorities;
|
QVector<DownloadPriority> m_filePriorities;
|
||||||
|
QBitArray m_completedFiles;
|
||||||
SpeedMonitor m_speedMonitor;
|
SpeedMonitor m_speedMonitor;
|
||||||
|
|
||||||
InfoHash m_infoHash;
|
InfoHash m_infoHash;
|
||||||
@ -299,6 +303,8 @@ namespace BitTorrent
|
|||||||
int m_renameCount = 0;
|
int m_renameCount = 0;
|
||||||
bool m_storageIsMoving = false;
|
bool m_storageIsMoving = false;
|
||||||
|
|
||||||
|
QQueue<EventTrigger> m_statusUpdatedTriggers;
|
||||||
|
|
||||||
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
|
MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
|
||||||
|
|
||||||
QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;
|
QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user