Browse Source

Redesign torrent startup handling

adaptive-webui-19844
Vladimir Golovnev (Glassez) 5 years ago
parent
commit
f2285e1b63
No known key found for this signature in database
GPG Key ID: 52A2C7DEE2DFA6F7
  1. 4
      src/base/CMakeLists.txt
  2. 4
      src/base/base.pri
  3. 74
      src/base/bittorrent/private/nativesessionextension.cpp
  4. 43
      src/base/bittorrent/private/nativesessionextension.h
  5. 94
      src/base/bittorrent/private/nativetorrentextension.cpp
  6. 49
      src/base/bittorrent/private/nativetorrentextension.h
  7. 109
      src/base/bittorrent/session.cpp
  8. 1
      src/base/bittorrent/session.h
  9. 99
      src/base/bittorrent/torrenthandle.cpp
  10. 12
      src/base/bittorrent/torrenthandle.h

4
src/base/CMakeLists.txt

@ -12,6 +12,8 @@ bittorrent/peerinfo.h
bittorrent/private/bandwidthscheduler.h bittorrent/private/bandwidthscheduler.h
bittorrent/private/filterparserthread.h bittorrent/private/filterparserthread.h
bittorrent/private/ltunderlyingtype.h bittorrent/private/ltunderlyingtype.h
bittorrent/private/nativesessionextension.h
bittorrent/private/nativetorrentextension.h
bittorrent/private/portforwarderimpl.h bittorrent/private/portforwarderimpl.h
bittorrent/private/resumedatasavingmanager.h bittorrent/private/resumedatasavingmanager.h
bittorrent/private/speedmonitor.h bittorrent/private/speedmonitor.h
@ -88,6 +90,8 @@ bittorrent/peeraddress.cpp
bittorrent/peerinfo.cpp bittorrent/peerinfo.cpp
bittorrent/private/bandwidthscheduler.cpp bittorrent/private/bandwidthscheduler.cpp
bittorrent/private/filterparserthread.cpp bittorrent/private/filterparserthread.cpp
bittorrent/private/nativesessionextension.cpp
bittorrent/private/nativetorrentextension.cpp
bittorrent/private/portforwarderimpl.cpp bittorrent/private/portforwarderimpl.cpp
bittorrent/private/resumedatasavingmanager.cpp bittorrent/private/resumedatasavingmanager.cpp
bittorrent/private/speedmonitor.cpp bittorrent/private/speedmonitor.cpp

4
src/base/base.pri

@ -11,6 +11,8 @@ HEADERS += \
$$PWD/bittorrent/private/bandwidthscheduler.h \ $$PWD/bittorrent/private/bandwidthscheduler.h \
$$PWD/bittorrent/private/filterparserthread.h \ $$PWD/bittorrent/private/filterparserthread.h \
$$PWD/bittorrent/private/ltunderlyingtype.h \ $$PWD/bittorrent/private/ltunderlyingtype.h \
$$PWD/bittorrent/private/nativesessionextension.h \
$$PWD/bittorrent/private/nativetorrentextension.h \
$$PWD/bittorrent/private/portforwarderimpl.h \ $$PWD/bittorrent/private/portforwarderimpl.h \
$$PWD/bittorrent/private/resumedatasavingmanager.h \ $$PWD/bittorrent/private/resumedatasavingmanager.h \
$$PWD/bittorrent/private/speedmonitor.h \ $$PWD/bittorrent/private/speedmonitor.h \
@ -87,6 +89,8 @@ SOURCES += \
$$PWD/bittorrent/peerinfo.cpp \ $$PWD/bittorrent/peerinfo.cpp \
$$PWD/bittorrent/private/bandwidthscheduler.cpp \ $$PWD/bittorrent/private/bandwidthscheduler.cpp \
$$PWD/bittorrent/private/filterparserthread.cpp \ $$PWD/bittorrent/private/filterparserthread.cpp \
$$PWD/bittorrent/private/nativesessionextension.cpp \
$$PWD/bittorrent/private/nativetorrentextension.cpp \
$$PWD/bittorrent/private/portforwarderimpl.cpp \ $$PWD/bittorrent/private/portforwarderimpl.cpp \
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \ $$PWD/bittorrent/private/resumedatasavingmanager.cpp \
$$PWD/bittorrent/private/speedmonitor.cpp \ $$PWD/bittorrent/private/speedmonitor.cpp \

74
src/base/bittorrent/private/nativesessionextension.cpp

@ -0,0 +1,74 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include "nativesessionextension.h"
#include <libtorrent/alert_types.hpp>
#include "nativetorrentextension.h"
namespace
{
void handleFastresumeRejectedAlert(const lt::fastresume_rejected_alert *alert)
{
if (alert->error.value() == lt::errors::mismatching_file_size) {
#if (LIBTORRENT_VERSION_NUM < 10200)
alert->handle.auto_managed(false);
#else
alert->handle.unset_flags(lt::torrent_flags::auto_managed);
#endif
alert->handle.pause();
}
}
}
#if (LIBTORRENT_VERSION_NUM >= 10200)
lt::feature_flags_t NativeSessionExtension::implemented_features()
{
return alert_feature;
}
std::shared_ptr<lt::torrent_plugin> NativeSessionExtension::new_torrent(const lt::torrent_handle &torrentHandle, void *)
{
return std::make_shared<NativeTorrentExtension>(torrentHandle);
}
#else
boost::shared_ptr<lt::torrent_plugin> NativeSessionExtension::new_torrent(const lt::torrent_handle &torrentHandle, void *)
{
return boost::shared_ptr<lt::torrent_plugin> {new NativeTorrentExtension {torrentHandle}};
}
#endif
void NativeSessionExtension::on_alert(const lt::alert *alert)
{
switch (alert->type()) {
case lt::fastresume_rejected_alert::alert_type:
handleFastresumeRejectedAlert(static_cast<const lt::fastresume_rejected_alert *>(alert));
break;
}
}

43
src/base/bittorrent/private/nativesessionextension.h

@ -0,0 +1,43 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#pragma once
#include <libtorrent/extensions.hpp>
#include <libtorrent/version.hpp>
class NativeSessionExtension : public lt::plugin
{
#if (LIBTORRENT_VERSION_NUM >= 10200)
lt::feature_flags_t implemented_features() override;
std::shared_ptr<lt::torrent_plugin> new_torrent(const lt::torrent_handle &torrentHandle, void *userData) override;
#else
boost::shared_ptr<lt::torrent_plugin> new_torrent(const lt::torrent_handle &torrentHandle, void *userData) override;
#endif
void on_alert(const lt::alert *alert) override;
};

94
src/base/bittorrent/private/nativetorrentextension.cpp

@ -0,0 +1,94 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include "nativetorrentextension.h"
#include <libtorrent/torrent_status.hpp>
namespace
{
bool isPaused(const lt::torrent_status &torrentStatus)
{
#if (LIBTORRENT_VERSION_NUM < 10200)
return (torrentStatus.paused && !torrentStatus.auto_managed);
#else
return ((torrentStatus.flags & lt::torrent_flags::paused)
&& !(torrentStatus.flags & lt::torrent_flags::auto_managed));
#endif
}
bool isAutoManaged(const lt::torrent_status &torrentStatus)
{
#if (LIBTORRENT_VERSION_NUM < 10200)
return torrentStatus.auto_managed;
#else
return bool {torrentStatus.flags & lt::torrent_flags::auto_managed};
#endif
}
}
NativeTorrentExtension::NativeTorrentExtension(const lt::torrent_handle &torrentHandle)
: m_torrentHandle {torrentHandle}
{
}
// This method is called when state of torrent is changed
#if (LIBTORRENT_VERSION_NUM < 10200)
void NativeTorrentExtension::on_state(const int state)
#else
void NativeTorrentExtension::on_state(const lt::torrent_status::state_t state)
#endif
{
// When a torrent enters "checking files" state while paused, we temporarily resume it
// (really we just allow libtorrent to resume it by enabling auto management for it).
if (state == lt::torrent_status::checking_files) {
if (isPaused(m_torrentHandle.status({}))) {
#if (LIBTORRENT_VERSION_NUM < 10200)
m_torrentHandle.stop_when_ready(true);
m_torrentHandle.auto_managed(true);
#else
m_torrentHandle.set_flags(lt::torrent_flags::stop_when_ready | lt::torrent_flags::auto_managed);
#endif
}
}
}
bool NativeTorrentExtension::on_pause()
{
if (!isAutoManaged(m_torrentHandle.status({}))) {
#if (LIBTORRENT_VERSION_NUM < 10200)
m_torrentHandle.stop_when_ready(false);
#else
m_torrentHandle.unset_flags(lt::torrent_flags::stop_when_ready);
#endif
}
// return `false` to allow standard handler
// and other extensions to be also invoked.
return false;
}

49
src/base/bittorrent/private/nativetorrentextension.h

@ -0,0 +1,49 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2020 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#pragma once
#include <libtorrent/extensions.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/version.hpp>
class NativeTorrentExtension : public lt::torrent_plugin
{
public:
explicit NativeTorrentExtension(const lt::torrent_handle &torrentHandle);
private:
#if (LIBTORRENT_VERSION_NUM < 10200)
void on_state(int state) override;
#else
void on_state(lt::torrent_status::state_t state) override;
#endif
bool on_pause() override;
lt::torrent_handle m_torrentHandle;
};

109
src/base/bittorrent/session.cpp

@ -90,6 +90,7 @@
#include "private/bandwidthscheduler.h" #include "private/bandwidthscheduler.h"
#include "private/filterparserthread.h" #include "private/filterparserthread.h"
#include "private/ltunderlyingtype.h" #include "private/ltunderlyingtype.h"
#include "private/nativesessionextension.h"
#include "private/portforwarderimpl.h" #include "private/portforwarderimpl.h"
#include "private/resumedatasavingmanager.h" #include "private/resumedatasavingmanager.h"
#include "private/statistics.h" #include "private/statistics.h"
@ -1127,6 +1128,12 @@ void Session::initializeNativeSession()
m_nativeSession->add_extension(&lt::create_ut_metadata_plugin); m_nativeSession->add_extension(&lt::create_ut_metadata_plugin);
if (isPeXEnabled()) if (isPeXEnabled())
m_nativeSession->add_extension(&lt::create_ut_pex_plugin); m_nativeSession->add_extension(&lt::create_ut_pex_plugin);
#if (LIBTORRENT_VERSION_NUM < 10200)
m_nativeSession->add_extension(boost::shared_ptr<lt::plugin> {new NativeSessionExtension});
#else
m_nativeSession->add_extension(std::make_shared<NativeSessionExtension>());
#endif
} }
void Session::processBannedIPs(lt::ip_filter &filter) void Session::processBannedIPs(lt::ip_filter &filter)
@ -2012,14 +2019,28 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
// Reuse existing torrent_handle // Reuse existing torrent_handle
lt::torrent_handle handle = m_nativeSession->find_torrent(hash); 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. // Preloaded torrent is in "Upload mode" so we need to disable it
handle.auto_managed(false); // otherwise the torrent never be downloaded (until application restart)
handle.pause(); handle.set_upload_mode(false);
// createTorrentHandle() for this is called in the torrent_paused_alert handler
if (params.paused) {
// Preloaded torrent isn't auto managed already
handle.pause();
}
else if (!params.forced) {
handle.auto_managed(true);
handle.pause();
}
m_loadedMetadata.remove(hash); m_loadedMetadata.remove(hash);
m_addingTorrents.insert(hash, params); m_addingTorrents.insert(hash, params);
--m_extraLimit;
adjustLimits();
// use common 2nd step of torrent addition
createTorrentHandle(handle);
return true; return true;
} }
@ -2108,11 +2129,14 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
// Common // Common
p.flags &= ~lt::add_torrent_params::flag_duplicate_is_error; // Already checked p.flags &= ~lt::add_torrent_params::flag_duplicate_is_error; // Already checked
// Make sure the torrent will be initially checked and then paused if (params.paused || !params.forced)
// to perform some service jobs on it. We will start it if needed. p.flags |= lt::add_torrent_params::flag_paused;
p.flags |= lt::add_torrent_params::flag_paused; else
p.flags |= lt::add_torrent_params::flag_auto_managed; p.flags &= ~lt::add_torrent_params::flag_paused;
p.flags |= lt::add_torrent_params::flag_stop_when_ready; if (params.paused || params.forced)
p.flags &= ~lt::add_torrent_params::flag_auto_managed;
else
p.flags |= lt::add_torrent_params::flag_auto_managed;
// Limits // Limits
p.max_connections = maxConnectionsPerTorrent(); p.max_connections = maxConnectionsPerTorrent();
p.max_uploads = maxUploadsPerTorrent(); p.max_uploads = maxUploadsPerTorrent();
@ -2162,14 +2186,29 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
// Reuse existing torrent_handle // Reuse existing torrent_handle
lt::torrent_handle handle = m_nativeSession->find_torrent(hash); 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. // Preloaded torrent is in "Upload mode" so we need to disable it
handle.unset_flags(lt::torrent_flags::auto_managed); // otherwise the torrent never be downloaded (until application restart)
handle.pause(); handle.unset_flags(lt::torrent_flags::upload_mode);
// createTorrentHandle() for this is called in the torrent_paused_alert handler
if (params.paused) {
// Preloaded torrent isn't auto managed already
handle.pause();
}
else if (!params.forced) {
handle.set_flags(lt::torrent_flags::auto_managed);
handle.pause();
}
m_loadedMetadata.remove(hash); m_loadedMetadata.remove(hash);
m_addingTorrents.insert(hash, params); m_addingTorrents.insert(hash, params);
--m_extraLimit;
adjustLimits();
// use common 2nd step of torrent addition
createTorrentHandle(handle);
return true; return true;
} }
@ -2270,11 +2309,15 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
// Common // Common
p.flags &= ~lt::torrent_flags::duplicate_is_error; // Already checked p.flags &= ~lt::torrent_flags::duplicate_is_error; // Already checked
// Make sure the torrent will be initially checked and then paused if (params.paused || !params.forced)
// to perform some service jobs on it. We will start it if needed. p.flags |= lt::torrent_flags::paused;
p.flags |= lt::torrent_flags::paused; else
p.flags |= lt::torrent_flags::auto_managed; p.flags &= ~lt::torrent_flags::paused;
p.flags |= lt::torrent_flags::stop_when_ready; if (params.paused || params.forced)
p.flags &= ~lt::torrent_flags::auto_managed;
else
p.flags |= lt::torrent_flags::auto_managed;
// Limits // Limits
p.max_connections = maxConnectionsPerTorrent(); p.max_connections = maxConnectionsPerTorrent();
p.max_uploads = maxUploadsPerTorrent(); p.max_uploads = maxUploadsPerTorrent();
@ -4265,9 +4308,6 @@ void Session::dispatchTorrentAlert(const lt::alert *a)
} }
switch (a->type()) { 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: case lt::metadata_received_alert::alert_type:
handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a)); handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a));
break; break;
@ -4412,29 +4452,6 @@ 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_addingTorrents.contains(hash)) {
// Adding preloaded torrent
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);
#else
handle.unset_flags(lt::torrent_flags::upload_mode);
#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());

1
src/base/bittorrent/session.h

@ -566,7 +566,6 @@ 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);

99
src/base/bittorrent/torrenthandle.cpp

@ -213,8 +213,6 @@ TorrentHandle::TorrentHandle(Session *session, const lt::torrent_handle &nativeH
, m_hasMissingFiles(false) , m_hasMissingFiles(false)
, m_hasRootFolder(params.hasRootFolder) , m_hasRootFolder(params.hasRootFolder)
, m_needsToSetFirstLastPiecePriority(false) , m_needsToSetFirstLastPiecePriority(false)
, 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));
@ -239,20 +237,6 @@ TorrentHandle::TorrentHandle(Session *session, const lt::torrent_handle &nativeH
if (filesCount() == 1) if (filesCount() == 1)
m_hasRootFolder = false; m_hasRootFolder = false;
} }
if (!hasMetadata()) {
// There is nothing to prepare
if (!m_pauseWhenReady) {
// Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization.
m_startupState = Starting;
resume_impl(m_needsToStartForced);
}
else {
m_startupState = Started;
m_pauseWhenReady = false;
}
}
} }
TorrentHandle::~TorrentHandle() {} TorrentHandle::~TorrentHandle() {}
@ -1360,8 +1344,6 @@ bool TorrentHandle::setCategory(const QString &category)
void TorrentHandle::move(QString path) void TorrentHandle::move(QString path)
{ {
if (m_startupState != Started) return;
m_useAutoTMM = false; m_useAutoTMM = false;
m_session->handleTorrentSavingModeChanged(this); m_session->handleTorrentSavingModeChanged(this);
@ -1404,18 +1386,6 @@ void TorrentHandle::forceRecheck()
m_nativeHandle.force_recheck(); m_nativeHandle.force_recheck();
m_unchecked = false; m_unchecked = false;
if ((m_startupState != Started) || isPaused()) {
#if (LIBTORRENT_VERSION_NUM < 10200)
m_nativeHandle.stop_when_ready(true);
#else
m_nativeHandle.set_flags(lt::torrent_flags::stop_when_ready);
#endif
setAutoManaged(true);
}
if ((m_startupState == Started) && isPaused())
m_pauseWhenReady = true;
} }
void TorrentHandle::setSequentialDownload(const bool enable) void TorrentHandle::setSequentialDownload(const bool enable)
@ -1504,22 +1474,11 @@ void TorrentHandle::pause()
setAutoManaged(false); setAutoManaged(false);
m_nativeHandle.pause(); m_nativeHandle.pause();
if (m_startupState == Started) { // Libtorrent doesn't emit a torrent_paused_alert when the
if (m_pauseWhenReady) { // torrent is queued (no I/O)
#if (LIBTORRENT_VERSION_NUM < 10200) // We test on the cached m_nativeStatus
m_nativeHandle.stop_when_ready(false); if (isQueued())
#else m_session->handleTorrentPaused(this);
m_nativeHandle.unset_flags(lt::torrent_flags::stop_when_ready);
#endif
m_pauseWhenReady = false;
}
// Libtorrent doesn't emit a torrent_paused_alert when the
// torrent is queued (no I/O)
// We test on the cached m_nativeStatus
if (isQueued())
m_session->handleTorrentPaused(this);
}
} }
void TorrentHandle::resume(bool forced) void TorrentHandle::resume(bool forced)
@ -1711,25 +1670,9 @@ 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 == Preparing) { if (m_fastresumeDataRejected && !m_hasMissingFiles) {
if (!m_pauseWhenReady) { saveResumeData();
if (!m_hasMissingFiles) { m_fastresumeDataRejected = false;
// Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization.
m_startupState = Starting;
resume_impl(m_needsToStartForced);
}
else {
// Torrent that has missing files is paused.
m_startupState = Started;
}
}
else {
m_startupState = Started;
m_pauseWhenReady = false;
if (m_fastresumeDataRejected && !m_hasMissingFiles)
saveResumeData();
}
} }
updateStatus(); updateStatus();
@ -1778,27 +1721,17 @@ void TorrentHandle::handleTorrentPausedAlert(const lt::torrent_paused_alert *p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
if (m_startupState == Started) { updateStatus();
if (!m_pauseWhenReady) { m_speedMonitor.reset();
updateStatus();
m_speedMonitor.reset();
}
else {
m_pauseWhenReady = false;
}
m_session->handleTorrentPaused(this); m_session->handleTorrentPaused(this);
}
} }
void TorrentHandle::handleTorrentResumedAlert(const lt::torrent_resumed_alert *p) void TorrentHandle::handleTorrentResumedAlert(const lt::torrent_resumed_alert *p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
if (m_startupState == Started) m_session->handleTorrentResumed(this);
m_session->handleTorrentResumed(this);
else if (m_startupState == Starting)
m_startupState = Started;
} }
void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p)
@ -1814,6 +1747,8 @@ void TorrentHandle::handleSaveResumeDataAlert(const lt::save_resume_data_alert *
lt::entry resumeData = useDummyResumeData ? lt::entry() : lt::write_resume_data(p->params); lt::entry resumeData = useDummyResumeData ? lt::entry() : lt::write_resume_data(p->params);
#endif #endif
updateStatus();
if (useDummyResumeData) { if (useDummyResumeData) {
resumeData["qBt-magnetUri"] = toMagnetUri().toStdString(); resumeData["qBt-magnetUri"] = toMagnetUri().toStdString();
resumeData["paused"] = isPaused(); resumeData["paused"] = isPaused();
@ -1841,7 +1776,11 @@ 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) { #if (LIBTORRENT_VERSION_NUM < 10200)
if (m_nativeStatus.stop_when_ready) {
#else
if (m_nativeStatus.flags & lt::torrent_flags::stop_when_ready) {
#endif
// We need to redefine these values when torrent starting/rechecking // We need to redefine these values when torrent starting/rechecking
// in "paused" state since native values can be logically wrong // in "paused" state since native values can be logically wrong
// (torrent can be not paused and auto_managed when it is checking). // (torrent can be not paused and auto_managed when it is checking).

12
src/base/bittorrent/torrenthandle.h

@ -443,21 +443,9 @@ namespace BitTorrent
bool m_hasMissingFiles; bool m_hasMissingFiles;
bool m_hasRootFolder; bool m_hasRootFolder;
bool m_needsToSetFirstLastPiecePriority; bool m_needsToSetFirstLastPiecePriority;
bool m_needsToStartForced;
QHash<QString, TrackerInfo> m_trackerInfos; QHash<QString, TrackerInfo> m_trackerInfos;
enum StartupState
{
Preparing, // torrent is preparing to start regular processing
Starting, // torrent is prepared and starting to perform regular processing
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;
bool m_unchecked = false; bool m_unchecked = false;
}; };
} }

Loading…
Cancel
Save