mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-02-02 09:55:55 +00:00
Merge pull request #10871 from glassez/fix-torrent-checking
Fix torrent checking issues
This commit is contained in:
commit
7d67cc5de7
@ -1861,29 +1861,22 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
|||||||
hash = magnetUri.hash();
|
hash = magnetUri.hash();
|
||||||
|
|
||||||
if (m_loadedMetadata.contains(hash)) {
|
if (m_loadedMetadata.contains(hash)) {
|
||||||
// Adding preloaded torrent
|
// Adding preloaded torrent...
|
||||||
m_loadedMetadata.remove(hash);
|
m_addingTorrents.insert(hash, params);
|
||||||
lt::torrent_handle handle = m_nativeSession->find_torrent(hash);
|
|
||||||
--m_extraLimit;
|
|
||||||
|
|
||||||
|
lt::torrent_handle handle = m_nativeSession->find_torrent(hash);
|
||||||
|
// We need to pause it first to create TorrentHandle within the same
|
||||||
|
// underlying state as in other cases.
|
||||||
try {
|
try {
|
||||||
// Preloaded torrent is in "Upload mode" so we need to disable it
|
|
||||||
// otherwise the torrent never be downloaded (until application restart)
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
handle.auto_managed(false);
|
handle.auto_managed(false);
|
||||||
handle.set_upload_mode(false);
|
|
||||||
#else
|
#else
|
||||||
handle.unset_flags(lt::torrent_flags::auto_managed | lt::torrent_flags::upload_mode);
|
handle.unset_flags(lt::torrent_flags::auto_managed);
|
||||||
#endif
|
#endif
|
||||||
handle.pause();
|
handle.pause();
|
||||||
}
|
}
|
||||||
catch (const std::exception &) {}
|
catch (const std::exception &) {}
|
||||||
|
|
||||||
adjustLimits();
|
|
||||||
|
|
||||||
// use common 2nd step of torrent addition
|
|
||||||
m_addingTorrents.insert(hash, params);
|
|
||||||
createTorrentHandle(handle);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1923,8 +1916,15 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
|||||||
if (!fromMagnetUri) {
|
if (!fromMagnetUri) {
|
||||||
if (params.restored) { // load from existing fastresume
|
if (params.restored) { // load from existing fastresume
|
||||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
p.resume_data = std::vector<char> {fastresumeData.constData()
|
// Make sure the torrent will be initially checked and then paused
|
||||||
, (fastresumeData.constData() + fastresumeData.size())};
|
// to perform some service jobs on it. We will start it if needed.
|
||||||
|
// (Workaround to easily support libtorrent-1.1
|
||||||
|
QByteArray patchedFastresumeData = fastresumeData;
|
||||||
|
patchedFastresumeData.replace("6:pausedi0e", "6:pausedi1e");
|
||||||
|
patchedFastresumeData.replace("12:auto_managedi0e", "12:auto_managedi1e");
|
||||||
|
|
||||||
|
p.resume_data = std::vector<char> {patchedFastresumeData.constData()
|
||||||
|
, (patchedFastresumeData.constData() + patchedFastresumeData.size())};
|
||||||
p.flags |= lt::add_torrent_params::flag_use_resume_save_path;
|
p.flags |= lt::add_torrent_params::flag_use_resume_save_path;
|
||||||
|
|
||||||
// Still setup the default parameters and let libtorrent handle
|
// Still setup the default parameters and let libtorrent handle
|
||||||
@ -1975,18 +1975,25 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
|||||||
p.ti = torrentInfo.nativeInfo();
|
p.ti = torrentInfo.nativeInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasCompleteFastresume) {
|
// Common
|
||||||
// Common
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
p.flags |= lt::add_torrent_params::flag_paused; // Start in pause
|
p.flags &= ~lt::add_torrent_params::flag_duplicate_is_error; // Already checked
|
||||||
p.flags &= ~lt::add_torrent_params::flag_auto_managed; // Because it is added in paused state
|
|
||||||
p.flags &= ~lt::add_torrent_params::flag_duplicate_is_error; // Already checked
|
|
||||||
#else
|
#else
|
||||||
p.flags |= lt::torrent_flags::paused; // Start in pause
|
p.flags &= ~lt::torrent_flags::duplicate_is_error; // Already checked
|
||||||
p.flags &= ~lt::torrent_flags::auto_managed; // Because it is added in paused state
|
#endif
|
||||||
p.flags &= ~lt::torrent_flags::duplicate_is_error; // Already checked
|
// Make sure the torrent will be initially checked and then paused
|
||||||
|
// to perform some service jobs on it. We will start it if needed.
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
p.flags |= lt::add_torrent_params::flag_paused;
|
||||||
|
p.flags |= lt::add_torrent_params::flag_auto_managed;
|
||||||
|
p.flags |= lt::add_torrent_params::flag_stop_when_ready;
|
||||||
|
#else
|
||||||
|
p.flags |= lt::torrent_flags::paused;
|
||||||
|
p.flags |= lt::torrent_flags::auto_managed;
|
||||||
|
p.flags |= lt::torrent_flags::stop_when_ready;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!hasCompleteFastresume) {
|
||||||
// Limits
|
// Limits
|
||||||
p.max_connections = maxConnectionsPerTorrent();
|
p.max_connections = maxConnectionsPerTorrent();
|
||||||
p.max_uploads = maxUploadsPerTorrent();
|
p.max_uploads = maxUploadsPerTorrent();
|
||||||
@ -2012,16 +2019,6 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
|||||||
p.flags &= ~lt::add_torrent_params::flag_seed_mode;
|
p.flags &= ~lt::add_torrent_params::flag_seed_mode;
|
||||||
#else
|
#else
|
||||||
p.flags &= ~lt::torrent_flags::seed_mode;
|
p.flags &= ~lt::torrent_flags::seed_mode;
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.restored && !params.paused) {
|
|
||||||
// Make sure the torrent will restored in "paused" state
|
|
||||||
// Then we will start it if needed
|
|
||||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
|
||||||
p.flags |= lt::add_torrent_params::flag_stop_when_ready;
|
|
||||||
#else
|
|
||||||
p.flags |= lt::torrent_flags::stop_when_ready;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2105,6 +2102,7 @@ bool Session::loadMetadata(const MagnetUri &magnetUri)
|
|||||||
p.flags &= ~lt::torrent_flags::paused;
|
p.flags &= ~lt::torrent_flags::paused;
|
||||||
p.flags &= ~lt::torrent_flags::auto_managed;
|
p.flags &= ~lt::torrent_flags::auto_managed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Solution to avoid accidental file writes
|
// Solution to avoid accidental file writes
|
||||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
p.flags |= lt::add_torrent_params::flag_upload_mode;
|
p.flags |= lt::add_torrent_params::flag_upload_mode;
|
||||||
@ -3872,10 +3870,7 @@ void Session::handleAlert(const lt::alert *a)
|
|||||||
case lt::tracker_warning_alert::alert_type:
|
case lt::tracker_warning_alert::alert_type:
|
||||||
case lt::fastresume_rejected_alert::alert_type:
|
case lt::fastresume_rejected_alert::alert_type:
|
||||||
case lt::torrent_checked_alert::alert_type:
|
case lt::torrent_checked_alert::alert_type:
|
||||||
dispatchTorrentAlert(a);
|
|
||||||
break;
|
|
||||||
case lt::metadata_received_alert::alert_type:
|
case lt::metadata_received_alert::alert_type:
|
||||||
handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a));
|
|
||||||
dispatchTorrentAlert(a);
|
dispatchTorrentAlert(a);
|
||||||
break;
|
break;
|
||||||
case lt::state_update_alert::alert_type:
|
case lt::state_update_alert::alert_type:
|
||||||
@ -3933,8 +3928,19 @@ void Session::handleAlert(const lt::alert *a)
|
|||||||
void Session::dispatchTorrentAlert(const lt::alert *a)
|
void Session::dispatchTorrentAlert(const lt::alert *a)
|
||||||
{
|
{
|
||||||
TorrentHandle *const torrent = m_torrents.value(static_cast<const lt::torrent_alert*>(a)->handle.info_hash());
|
TorrentHandle *const torrent = m_torrents.value(static_cast<const lt::torrent_alert*>(a)->handle.info_hash());
|
||||||
if (torrent)
|
if (torrent) {
|
||||||
torrent->handleAlert(a);
|
torrent->handleAlert(a);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a->type()) {
|
||||||
|
case lt::torrent_paused_alert::alert_type:
|
||||||
|
handleTorrentPausedAlert(static_cast<const lt::torrent_paused_alert*>(a));
|
||||||
|
break;
|
||||||
|
case lt::metadata_received_alert::alert_type:
|
||||||
|
handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::createTorrentHandle(const lt::torrent_handle &nativeHandle)
|
void Session::createTorrentHandle(const lt::torrent_handle &nativeHandle)
|
||||||
@ -4064,6 +4070,32 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p)
|
||||||
|
{
|
||||||
|
const InfoHash hash {p->handle.info_hash()};
|
||||||
|
|
||||||
|
if (m_loadedMetadata.contains(hash)) {
|
||||||
|
// Adding preloaded torrent
|
||||||
|
m_loadedMetadata.remove(hash);
|
||||||
|
lt::torrent_handle handle = p->handle;
|
||||||
|
--m_extraLimit;
|
||||||
|
|
||||||
|
// Preloaded torrent is in "Upload mode" so we need to disable it
|
||||||
|
// otherwise the torrent never be downloaded (until application restart)
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
handle.set_upload_mode(false);
|
||||||
|
handle.auto_managed(true);
|
||||||
|
#else
|
||||||
|
handle.unset_flags(lt::torrent_flags::upload_mode);
|
||||||
|
handle.set_flags(lt::torrent_flags::auto_managed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
adjustLimits();
|
||||||
|
// use common 2nd step of torrent addition
|
||||||
|
createTorrentHandle(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Session::handleFileErrorAlert(const lt::file_error_alert *p)
|
void Session::handleFileErrorAlert(const lt::file_error_alert *p)
|
||||||
{
|
{
|
||||||
TorrentHandle *const torrent = m_torrents.value(p->handle.info_hash());
|
TorrentHandle *const torrent = m_torrents.value(p->handle.info_hash());
|
||||||
|
@ -551,6 +551,7 @@ namespace BitTorrent
|
|||||||
void handleAddTorrentAlert(const lt::add_torrent_alert *p);
|
void handleAddTorrentAlert(const lt::add_torrent_alert *p);
|
||||||
void handleStateUpdateAlert(const lt::state_update_alert *p);
|
void handleStateUpdateAlert(const lt::state_update_alert *p);
|
||||||
void handleMetadataReceivedAlert(const lt::metadata_received_alert *p);
|
void handleMetadataReceivedAlert(const lt::metadata_received_alert *p);
|
||||||
|
void handleTorrentPausedAlert(const lt::torrent_paused_alert *p);
|
||||||
void handleFileErrorAlert(const lt::file_error_alert *p);
|
void handleFileErrorAlert(const lt::file_error_alert *p);
|
||||||
void handleTorrentRemovedAlert(const lt::torrent_removed_alert *p);
|
void handleTorrentRemovedAlert(const lt::torrent_removed_alert *p);
|
||||||
void handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p);
|
void handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p);
|
||||||
|
@ -191,6 +191,7 @@ TorrentHandle::TorrentHandle(Session *session, const lt::torrent_handle &nativeH
|
|||||||
, m_hasRootFolder(params.hasRootFolder)
|
, m_hasRootFolder(params.hasRootFolder)
|
||||||
, m_needsToSetFirstLastPiecePriority(false)
|
, m_needsToSetFirstLastPiecePriority(false)
|
||||||
, m_needsToStartForced(params.forced)
|
, m_needsToStartForced(params.forced)
|
||||||
|
, m_pauseWhenReady(params.paused)
|
||||||
{
|
{
|
||||||
if (m_useAutoTMM)
|
if (m_useAutoTMM)
|
||||||
m_savePath = Utils::Fs::toNativePath(m_session->categorySavePath(m_category));
|
m_savePath = Utils::Fs::toNativePath(m_session->categorySavePath(m_category));
|
||||||
@ -216,18 +217,18 @@ TorrentHandle::TorrentHandle(Session *session, const lt::torrent_handle &nativeH
|
|||||||
m_hasRootFolder = false;
|
m_hasRootFolder = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "started" means "all initialization has completed and torrent has started regular processing".
|
if (!hasMetadata()) {
|
||||||
// When torrent added/restored in "paused" state it become "started" immediately after construction.
|
// There is nothing to prepare
|
||||||
// When it is added/restored in "resumed" state, it become "started" after it is really resumed
|
if (!m_pauseWhenReady) {
|
||||||
// (i.e. after receiving "torrent resumed" alert).
|
// Resume torrent because it was added in "resumed" state
|
||||||
if (params.paused) {
|
// but it's actually paused during initialization.
|
||||||
m_startupState = Started;
|
m_startupState = Starting;
|
||||||
}
|
resume(m_needsToStartForced);
|
||||||
else if (!params.restored || !hasMetadata()) {
|
}
|
||||||
// Resume torrent because it was added in "resumed" state
|
else {
|
||||||
// but it's actually paused during initialization
|
m_startupState = Started;
|
||||||
m_startupState = Starting;
|
m_pauseWhenReady = false;
|
||||||
resume(params.forced);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,7 +1347,8 @@ void TorrentHandle::forceRecheck()
|
|||||||
#else
|
#else
|
||||||
m_nativeHandle.set_flags(lt::torrent_flags::stop_when_ready);
|
m_nativeHandle.set_flags(lt::torrent_flags::stop_when_ready);
|
||||||
#endif
|
#endif
|
||||||
resume_impl(false);
|
setAutoManaged(true);
|
||||||
|
m_pauseWhenReady = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1618,17 +1620,22 @@ void TorrentHandle::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p
|
|||||||
Q_UNUSED(p);
|
Q_UNUSED(p);
|
||||||
qDebug("\"%s\" have just finished checking", qUtf8Printable(name()));
|
qDebug("\"%s\" have just finished checking", qUtf8Printable(name()));
|
||||||
|
|
||||||
if (m_startupState == NotStarted) {
|
if (m_startupState == Preparing) {
|
||||||
if (!m_hasMissingFiles) {
|
if (!m_pauseWhenReady) {
|
||||||
// Resume torrent because it was added in "resumed" state
|
if (!m_hasMissingFiles) {
|
||||||
// but it's actually paused during initialization.
|
// Resume torrent because it was added in "resumed" state
|
||||||
m_startupState = Starting;
|
// but it's actually paused during initialization.
|
||||||
resume(m_needsToStartForced);
|
m_startupState = Starting;
|
||||||
|
resume(m_needsToStartForced);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Torrent that has missing files is paused.
|
||||||
|
m_startupState = Started;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Torrent that has missing files is marked as "started"
|
|
||||||
// but it remains paused.
|
|
||||||
m_startupState = Started;
|
m_startupState = Started;
|
||||||
|
m_pauseWhenReady = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1652,10 +1659,10 @@ void TorrentHandle::handleTorrentFinishedAlert(const lt::torrent_finished_alert
|
|||||||
Q_UNUSED(p);
|
Q_UNUSED(p);
|
||||||
qDebug("Got a torrent finished alert for \"%s\"", qUtf8Printable(name()));
|
qDebug("Got a torrent finished alert for \"%s\"", qUtf8Printable(name()));
|
||||||
qDebug("Torrent has seed status: %s", m_hasSeedStatus ? "yes" : "no");
|
qDebug("Torrent has seed status: %s", m_hasSeedStatus ? "yes" : "no");
|
||||||
|
m_hasMissingFiles = false;
|
||||||
if (m_hasSeedStatus) return;
|
if (m_hasSeedStatus) return;
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
m_hasMissingFiles = false;
|
|
||||||
m_hasSeedStatus = true;
|
m_hasSeedStatus = true;
|
||||||
|
|
||||||
adjustActualSavePath();
|
adjustActualSavePath();
|
||||||
@ -1679,9 +1686,14 @@ void TorrentHandle::handleTorrentPausedAlert(const lt::torrent_paused_alert *p)
|
|||||||
Q_UNUSED(p);
|
Q_UNUSED(p);
|
||||||
|
|
||||||
if (m_startupState == Started) {
|
if (m_startupState == Started) {
|
||||||
updateStatus();
|
if (!m_pauseWhenReady) {
|
||||||
m_speedMonitor.reset();
|
updateStatus();
|
||||||
m_session->handleTorrentPaused(this);
|
m_speedMonitor.reset();
|
||||||
|
m_session->handleTorrentPaused(this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_pauseWhenReady = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1710,8 +1722,8 @@ void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert *
|
|||||||
|
|
||||||
if (useDummyResumeData) {
|
if (useDummyResumeData) {
|
||||||
resumeData["qBt-magnetUri"] = toMagnetUri().toStdString();
|
resumeData["qBt-magnetUri"] = toMagnetUri().toStdString();
|
||||||
resumeData["qBt-paused"] = isPaused();
|
resumeData["paused"] = isPaused();
|
||||||
resumeData["qBt-forced"] = isForced();
|
resumeData["auto_managed"] = isAutoManaged();
|
||||||
// Both firstLastPiecePriority and sequential need to be stored in the
|
// Both firstLastPiecePriority and sequential need to be stored in the
|
||||||
// resume data if there is no metadata, otherwise they won't be
|
// resume data if there is no metadata, otherwise they won't be
|
||||||
// restored if qBittorrent quits before the metadata are retrieved:
|
// restored if qBittorrent quits before the metadata are retrieved:
|
||||||
@ -1733,6 +1745,14 @@ void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert *
|
|||||||
resumeData["qBt-queuePosition"] = (static_cast<int>(nativeHandle().queue_position()) + 1); // qBt starts queue at 1
|
resumeData["qBt-queuePosition"] = (static_cast<int>(nativeHandle().queue_position()) + 1); // qBt starts queue at 1
|
||||||
resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
|
resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
|
||||||
|
|
||||||
|
if (m_pauseWhenReady) {
|
||||||
|
// We need to redefine these values when torrent starting/rechecking
|
||||||
|
// in "paused" state since native values can be logically wrong
|
||||||
|
// (torrent can be not paused and auto_managed when it is checking).
|
||||||
|
resumeData["paused"] = true;
|
||||||
|
resumeData["auto_managed"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
m_session->handleTorrentResumeDataReady(this, resumeData);
|
m_session->handleTorrentResumeDataReady(this, resumeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,12 +447,15 @@ namespace BitTorrent
|
|||||||
|
|
||||||
enum StartupState
|
enum StartupState
|
||||||
{
|
{
|
||||||
NotStarted,
|
Preparing, // torrent is preparing to start regular processing
|
||||||
Starting,
|
Starting, // torrent is prepared and starting to perform regular processing
|
||||||
Started
|
Started // torrent is performing regular processing
|
||||||
};
|
};
|
||||||
|
StartupState m_startupState = Preparing;
|
||||||
|
// Handle torrent state when it starts performing some service job
|
||||||
|
// being in Paused state so it might be unpaused internally and then paused again
|
||||||
|
bool m_pauseWhenReady;
|
||||||
|
|
||||||
StartupState m_startupState = NotStarted;
|
|
||||||
bool m_unchecked = false;
|
bool m_unchecked = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user