Browse Source

Merge pull request #9580 from glassez/start_paused

Improve handling of torrent startup/recheck
adaptive-webui-19844
Vladimir Golovnev 6 years ago committed by GitHub
parent
commit
46ec72f688
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      src/base/bittorrent/session.cpp
  2. 66
      src/base/bittorrent/torrenthandle.cpp
  3. 11
      src/base/bittorrent/torrenthandle.h

32
src/base/bittorrent/session.cpp

@ -2194,15 +2194,6 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
return false; return false;
} }
if (params.restored && !fromMagnetUri) {
// Set torrent fast resume data
p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
}
else {
p.file_priorities = {params.filePriorities.begin(), params.filePriorities.end()};
}
// We should not add torrent if it already // We should not add torrent if it already
// processed or adding to session // processed or adding to session
if (m_addingTorrents.contains(hash) || m_loadedMetadata.contains(hash)) return false; if (m_addingTorrents.contains(hash) || m_loadedMetadata.contains(hash)) return false;
@ -2236,6 +2227,23 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
else else
p.flags &= ~libt::add_torrent_params::flag_seed_mode; p.flags &= ~libt::add_torrent_params::flag_seed_mode;
if (!fromMagnetUri) {
if (params.restored) {
// Set torrent fast resume data
p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
}
else {
p.file_priorities = {params.filePriorities.begin(), params.filePriorities.end()};
}
}
if (params.restored && !params.paused) {
// Make sure the torrent will restored in "paused" state
// Then we will start it if needed
p.flags |= libt::add_torrent_params::flag_stop_when_ready;
}
// Limits // Limits
p.max_connections = maxConnectionsPerTorrent(); p.max_connections = maxConnectionsPerTorrent();
p.max_uploads = maxUploadsPerTorrent(); p.max_uploads = maxUploadsPerTorrent();
@ -4565,8 +4573,10 @@ namespace
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder"); torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri"))); magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri")));
torrentParams.paused = fast.dict_find_int_value("qBt-paused"); const bool isAutoManaged = fast.dict_find_int_value("auto_managed");
torrentParams.forced = fast.dict_find_int_value("qBt-forced"); const bool isPaused = fast.dict_find_int_value("paused");
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));
torrentParams.forced = fast.dict_find_int_value("qBt-forced", (!isPaused && !isAutoManaged));
torrentParams.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority"); torrentParams.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.sequential = fast.dict_find_int_value("qBt-sequential"); torrentParams.sequential = fast.dict_find_int_value("qBt-sequential");

66
src/base/bittorrent/torrenthandle.cpp

@ -190,7 +190,7 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
, m_hasMissingFiles(false) , m_hasMissingFiles(false)
, m_hasRootFolder(params.hasRootFolder) , m_hasRootFolder(params.hasRootFolder)
, m_needsToSetFirstLastPiecePriority(false) , m_needsToSetFirstLastPiecePriority(false)
, m_pauseAfterRecheck(false) , m_needsToStartForced(params.forced)
{ {
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));
@ -220,16 +220,16 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
// When torrent added/restored in "paused" state it become "started" immediately after construction. // When torrent added/restored in "paused" state it become "started" immediately after construction.
// When it is added/restored in "resumed" state, it become "started" after it is really resumed // When it is added/restored in "resumed" state, it become "started" after it is really resumed
// (i.e. after receiving "torrent resumed" alert). // (i.e. after receiving "torrent resumed" alert).
m_started = (params.restored && hasMetadata() ? isPaused() : params.paused); if (params.paused) {
m_startupState = Started;
if (!m_started) { }
if (!params.restored || !hasMetadata()) { else if (!params.restored) {
// Resume torrent because it was added in "resumed" state // Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization // but it's actually paused during initialization
m_startupState = Starting;
resume(params.forced); resume(params.forced);
} }
} }
}
TorrentHandle::~TorrentHandle() {} TorrentHandle::~TorrentHandle() {}
@ -1274,11 +1274,9 @@ void TorrentHandle::forceRecheck()
m_unchecked = false; m_unchecked = false;
if (isPaused()) { if (isPaused()) {
m_pauseAfterRecheck = true; m_nativeHandle.stop_when_ready(true);
resume_impl(true, true); resume_impl(true, true);
} }
m_nativeHandle.force_recheck();
} }
void TorrentHandle::setSequentialDownload(bool b) void TorrentHandle::setSequentialDownload(bool b)
@ -1363,7 +1361,12 @@ void TorrentHandle::resume_impl(bool forced, bool uploadMode)
{ {
if (hasError()) if (hasError())
m_nativeHandle.clear_error(); m_nativeHandle.clear_error();
if (m_hasMissingFiles) {
m_hasMissingFiles = false; m_hasMissingFiles = false;
m_nativeHandle.force_recheck();
}
m_nativeHandle.auto_managed(!forced); m_nativeHandle.auto_managed(!forced);
m_nativeHandle.set_upload_mode(uploadMode); m_nativeHandle.set_upload_mode(uploadMode);
m_nativeHandle.resume(); m_nativeHandle.resume();
@ -1555,10 +1558,25 @@ void TorrentHandle::handleTrackerErrorAlert(const libtorrent::tracker_error_aler
void TorrentHandle::handleTorrentCheckedAlert(const libtorrent::torrent_checked_alert *p) void TorrentHandle::handleTorrentCheckedAlert(const libtorrent::torrent_checked_alert *p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
qDebug("%s have just finished checking", qUtf8Printable(hash())); qDebug("\"%s\" have just finished checking", qUtf8Printable(name()));
if (m_startupState == NotStarted) {
if (!m_hasMissingFiles) {
// Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization.
m_startupState = Starting;
resume(m_needsToStartForced);
}
else {
// Torrent that has missing files is marked as "started"
// but it remains paused.
m_startupState = Started;
}
}
updateStatus(); updateStatus();
if (!m_hasMissingFiles) {
if ((progress() < 1.0) && (wantedSize() > 0)) if ((progress() < 1.0) && (wantedSize() > 0))
m_hasSeedStatus = false; m_hasSeedStatus = false;
else if (progress() == 1.0) else if (progress() == 1.0)
@ -1566,10 +1584,6 @@ void TorrentHandle::handleTorrentCheckedAlert(const libtorrent::torrent_checked_
adjustActualSavePath(); adjustActualSavePath();
manageIncompleteFiles(); manageIncompleteFiles();
if (m_pauseAfterRecheck) {
m_pauseAfterRecheck = false;
pause();
} }
m_session->handleTorrentChecked(this); m_session->handleTorrentChecked(this);
@ -1578,7 +1592,7 @@ void TorrentHandle::handleTorrentCheckedAlert(const libtorrent::torrent_checked_
void TorrentHandle::handleTorrentFinishedAlert(const libtorrent::torrent_finished_alert *p) void TorrentHandle::handleTorrentFinishedAlert(const libtorrent::torrent_finished_alert *p)
{ {
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");
if (m_hasSeedStatus) return; if (m_hasSeedStatus) return;
@ -1605,19 +1619,22 @@ void TorrentHandle::handleTorrentFinishedAlert(const libtorrent::torrent_finishe
void TorrentHandle::handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p) void TorrentHandle::handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
if (m_startupState == Started) {
updateStatus(); updateStatus();
m_speedMonitor.reset(); m_speedMonitor.reset();
m_session->handleTorrentPaused(this); m_session->handleTorrentPaused(this);
} }
}
void TorrentHandle::handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p) void TorrentHandle::handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
if (m_started) if (m_startupState == Started)
m_session->handleTorrentResumed(this); m_session->handleTorrentResumed(this);
else else if (m_startupState == Starting)
m_started = true; m_startupState = Started;
} }
void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p) void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p)
@ -1668,7 +1685,6 @@ void TorrentHandle::handleFastResumeRejectedAlert(const libtorrent::fastresume_r
{ {
if (p->error.value() == libt::errors::mismatching_file_size) { if (p->error.value() == libt::errors::mismatching_file_size) {
// Mismatching file size (files were probably moved) // Mismatching file size (files were probably moved)
pause();
m_hasMissingFiles = true; m_hasMissingFiles = true;
LogMsg(tr("File sizes mismatch for torrent '%1', pausing it.").arg(name()), Log::CRITICAL); LogMsg(tr("File sizes mismatch for torrent '%1', pausing it.").arg(name()), Log::CRITICAL);
} }
@ -1703,7 +1719,9 @@ void TorrentHandle::handleFileRenamedAlert(const libtorrent::file_renamed_alert
} }
} }
updateStatus(); // We don't really need to call updateStatus() in this place.
// All we need to do is make sure we have a valid instance of the TorrentInfo object.
m_torrentInfo = TorrentInfo {m_nativeHandle.torrent_file()};
--m_renameCount; --m_renameCount;
while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty()) while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty())
@ -1721,7 +1739,9 @@ void TorrentHandle::handleFileRenameFailedAlert(const libtorrent::file_rename_fa
void TorrentHandle::handleFileCompletedAlert(const libtorrent::file_completed_alert *p) void TorrentHandle::handleFileCompletedAlert(const libtorrent::file_completed_alert *p)
{ {
updateStatus(); // We don't really need to call updateStatus() in this place.
// All we need to do is make sure we have a valid instance of the TorrentInfo object.
m_torrentInfo = TorrentInfo {m_nativeHandle.torrent_file()};
qDebug("A file completed download in torrent \"%s\"", qUtf8Printable(name())); qDebug("A file completed download in torrent \"%s\"", qUtf8Printable(name()));
if (m_session->isAppendExtensionEnabled()) { if (m_session->isAppendExtensionEnabled()) {
@ -1984,8 +2004,6 @@ void TorrentHandle::setDownloadLimit(int limit)
void TorrentHandle::setSuperSeeding(bool enable) void TorrentHandle::setSuperSeeding(bool enable)
{ {
m_nativeHandle.super_seeding(enable); m_nativeHandle.super_seeding(enable);
if (superSeeding() != enable)
updateStatus();
} }
void TorrentHandle::flushCache() void TorrentHandle::flushCache()
@ -2078,8 +2096,6 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
// Restore first/last piece first option if necessary // Restore first/last piece first option if necessary
if (firstLastPieceFirst) if (firstLastPieceFirst)
setFirstLastPiecePriorityImpl(true, priorities); setFirstLastPiecePriorityImpl(true, priorities);
updateStatus();
} }
QVector<qreal> TorrentHandle::availableFileFractions() const QVector<qreal> TorrentHandle::availableFileFractions() const

11
src/base/bittorrent/torrenthandle.h

@ -461,11 +461,18 @@ namespace BitTorrent
bool m_hasMissingFiles; bool m_hasMissingFiles;
bool m_hasRootFolder; bool m_hasRootFolder;
bool m_needsToSetFirstLastPiecePriority; bool m_needsToSetFirstLastPiecePriority;
bool m_needsToStartForced;
bool m_pauseAfterRecheck;
QHash<QString, TrackerInfo> m_trackerInfos; QHash<QString, TrackerInfo> m_trackerInfos;
bool m_started = false; enum StartupState
{
NotStarted,
Starting,
Started
};
StartupState m_startupState = NotStarted;
bool m_unchecked = false; bool m_unchecked = false;
}; };
} }

Loading…
Cancel
Save