fix: magnet links are always paused when added (#4856)

This commit is contained in:
Charles Kerr
2023-02-13 12:33:33 -06:00
committed by GitHub
parent 62a60b4ea4
commit f551b4adbf
8 changed files with 102 additions and 111 deletions

View File

@@ -43,6 +43,7 @@
#include "session.h" #include "session.h"
#include "timer.h" #include "timer.h"
#include "torrent.h" #include "torrent.h"
#include "torrent-magnet.h"
#include "tr-assert.h" #include "tr-assert.h"
#include "tr-utp.h" #include "tr-utp.h"
#include "utils.h" #include "utils.h"
@@ -2391,8 +2392,11 @@ void tr_peerMgr::bandwidthPulse()
session->top_bandwidth_.allocate(Msec); session->top_bandwidth_.allocate(Msec);
// torrent upkeep // torrent upkeep
auto& torrents = session->torrents(); for (auto* const tor : session->torrents())
std::for_each(std::begin(torrents), std::end(torrents), [](auto* tor) { tor->do_idle_work(); }); {
tor->do_idle_work();
tr_torrentMagnetDoIdleWork(tor);
}
/* pump the queues */ /* pump the queues */
queuePulse(session, TR_UP); queuePulse(session, TR_UP);

View File

@@ -712,7 +712,7 @@ auto loadFromFile(tr_torrent* tor, tr_resume::fields_t fields_to_load, bool* did
if (auto val = bool{}; (fields_to_load & tr_resume::Run) != 0 && tr_variantDictFindBool(&top, TR_KEY_paused, &val)) if (auto val = bool{}; (fields_to_load & tr_resume::Run) != 0 && tr_variantDictFindBool(&top, TR_KEY_paused, &val))
{ {
tor->isRunning = !val; tor->start_when_stable = !val;
fields_loaded |= tr_resume::Run; fields_loaded |= tr_resume::Run;
} }
@@ -831,7 +831,7 @@ auto setFromCtor(tr_torrent* tor, tr_resume::fields_t fields, tr_ctor const* cto
{ {
if (auto is_paused = bool{}; tr_ctorGetPaused(ctor, mode, &is_paused)) if (auto is_paused = bool{}; tr_ctorGetPaused(ctor, mode, &is_paused))
{ {
tor->isRunning = !is_paused; tor->start_when_stable = !is_paused;
ret |= tr_resume::Run; ret |= tr_resume::Run;
} }
} }
@@ -907,7 +907,7 @@ void save(tr_torrent* tor)
tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur); tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur);
tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->peerLimit()); tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->peerLimit());
tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tor->getPriority()); tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tor->getPriority());
tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued()); tr_variantDictAddBool(&top, TR_KEY_paused, !tor->start_when_stable);
savePeers(&top, tor); savePeers(&top, tor);
if (tor->hasMetainfo()) if (tor->hasMetainfo())

View File

@@ -176,13 +176,6 @@ bool tr_torrentUseMetainfoFromFile(
delete tor->incompleteMetadata; delete tor->incompleteMetadata;
tor->incompleteMetadata = nullptr; tor->incompleteMetadata = nullptr;
} }
tor->isStopping = true;
tor->magnetVerify = true;
if (tor->session->shouldPauseAddedTorrents())
{
tor->startAfterVerify = false;
}
tor->markEdited();
return true; return true;
} }
@@ -310,13 +303,6 @@ void on_have_all_metainfo(tr_torrent* tor, tr_incomplete_metadata* m)
{ {
delete tor->incompleteMetadata; delete tor->incompleteMetadata;
tor->incompleteMetadata = nullptr; tor->incompleteMetadata = nullptr;
tor->isStopping = true;
tor->magnetVerify = true;
if (tor->session->shouldPauseAddedTorrents() && !tor->magnetStartAfterVerify)
{
tor->startAfterVerify = false;
}
tor->markEdited();
} }
else /* drat. */ else /* drat. */
{ {
@@ -340,6 +326,19 @@ void on_have_all_metainfo(tr_torrent* tor, tr_incomplete_metadata* m)
} // namespace set_metadata_piece_helpers } // namespace set_metadata_piece_helpers
} // namespace } // namespace
void tr_torrentMagnetDoIdleWork(tr_torrent* const tor)
{
using namespace set_metadata_piece_helpers;
TR_ASSERT(tr_isTorrent(tor));
if (auto* const m = tor->incompleteMetadata; m != nullptr && std::empty(m->pieces_needed))
{
tr_logAddDebugTor(tor, fmt::format("we now have all the metainfo!"));
on_have_all_metainfo(tor, m);
}
}
void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, size_t len) void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, size_t len)
{ {
using namespace set_metadata_piece_helpers; using namespace set_metadata_piece_helpers;
@@ -384,13 +383,6 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, si
needed.erase(iter); needed.erase(iter);
tr_logAddDebugTor(tor, fmt::format("saving metainfo piece {}... {} remain", piece, std::size(needed))); tr_logAddDebugTor(tor, fmt::format("saving metainfo piece {}... {} remain", piece, std::size(needed)));
// are we done?
if (std::empty(needed))
{
tr_logAddDebugTor(tor, fmt::format("metainfo piece {} was the last one", piece));
on_have_all_metainfo(tor, m);
}
} }
// --- // ---

View File

@@ -33,6 +33,8 @@ bool tr_torrentSetMetadataSizeHint(tr_torrent* tor, int64_t metadata_size);
double tr_torrentGetMetadataPercent(tr_torrent const* tor); double tr_torrentGetMetadataPercent(tr_torrent const* tor);
void tr_torrentMagnetDoIdleWork(tr_torrent* tor);
bool tr_torrentUseMetainfoFromFile( bool tr_torrentUseMetainfoFromFile(
tr_torrent* tor, tr_torrent* tor,
tr_torrent_metainfo const* metainfo, tr_torrent_metainfo const* metainfo,

View File

@@ -830,6 +830,8 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
{ {
using namespace start_stop_helpers; using namespace start_stop_helpers;
auto const lock = tor->unique_lock();
switch (tor->activity()) switch (tor->activity())
{ {
case TR_STATUS_SEED: case TR_STATUS_SEED:
@@ -849,7 +851,6 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
case TR_STATUS_CHECK_WAIT: case TR_STATUS_CHECK_WAIT:
/* verifying right now... wait until that's done so /* verifying right now... wait until that's done so
* we'll know what completeness to use/announce */ * we'll know what completeness to use/announce */
tor->startAfterVerify = true;
return; return;
case TR_STATUS_STOPPED: case TR_STATUS_STOPPED:
@@ -868,9 +869,6 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
return; return;
} }
/* otherwise, start it now... */
auto const lock = tor->unique_lock();
/* allow finished torrents to be resumed */ /* allow finished torrents to be resumed */
if (tr_torrentIsSeedRatioDone(tor)) if (tr_torrentIsSeedRatioDone(tor))
{ {
@@ -895,6 +893,9 @@ void torrentStop(tr_torrent* const tor)
TR_ASSERT(tor->session->amInSessionThread()); TR_ASSERT(tor->session->amInSessionThread());
auto const lock = tor->unique_lock(); auto const lock = tor->unique_lock();
tor->isRunning = false;
tor->isStopping = false;
if (!tor->session->isClosing()) if (!tor->session->isClosing())
{ {
tr_logAddInfoTor(tor, _("Pausing torrent")); tr_logAddInfoTor(tor, _("Pausing torrent"));
@@ -913,16 +914,6 @@ void torrentStop(tr_torrent* const tor)
} }
torrentSetQueued(tor, false); torrentSetQueued(tor, false);
if (tor->magnetVerify)
{
tor->magnetVerify = false;
tr_logAddTraceTor(tor, "Magnet Verify");
tor->refreshCurrentDir();
tr_torrentVerify(tor);
callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
}
} }
} // namespace } // namespace
@@ -935,8 +926,7 @@ void tr_torrentStop(tr_torrent* tor)
auto const lock = tor->unique_lock(); auto const lock = tor->unique_lock();
tor->isRunning = false; tor->start_when_stable = false;
tor->isStopping = false;
tor->setDirty(); tor->setDirty();
tor->session->runInSessionThread(torrentStop, tor); tor->session->runInSessionThread(torrentStop, tor);
} }
@@ -965,7 +955,6 @@ void tr_torrentFreeInSessionThread(tr_torrent* tor)
tr_logAddInfoTor(tor, _("Removing torrent")); tr_logAddInfoTor(tor, _("Removing torrent"));
} }
tor->magnetVerify = false;
torrentStop(tor); torrentStop(tor);
if (tor->isDeleting) if (tor->isDeleting)
@@ -975,7 +964,6 @@ void tr_torrentFreeInSessionThread(tr_torrent* tor)
tr_torrent_metainfo::removeFile(tor->session->resumeDir(), tor->name(), tor->infoHashString(), ".resume"sv); tr_torrent_metainfo::removeFile(tor->session->resumeDir(), tor->name(), tor->infoHashString(), ".resume"sv);
} }
tor->isRunning = false;
freeTorrent(tor); freeTorrent(tor);
} }
@@ -1036,6 +1024,34 @@ void torrentInitFromInfoDict(tr_torrent* tor)
tor->checked_pieces_ = tr_bitfield{ size_t(tor->pieceCount()) }; tor->checked_pieces_ = tr_bitfield{ size_t(tor->pieceCount()) };
} }
void on_metainfo_completed(tr_torrent* tor)
{
// we can look for files now that we know what files are in the torrent
tor->refreshCurrentDir();
callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
if (tor->session->shouldFullyVerifyAddedTorrents() || !isNewTorrentASeed(tor))
{
tr_torrentVerify(tor);
}
else
{
tor->completion.setHasAll();
tor->doneDate = tor->addedDate;
tor->recheckCompleteness();
if (tor->start_when_stable)
{
torrentStart(tor, {});
}
else if (tor->isRunning)
{
tr_torrentStop(tor);
}
}
}
void torrentInit(tr_torrent* tor, tr_ctor const* ctor) void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
{ {
tr_session* session = tr_ctorGetSession(ctor); tr_session* session = tr_ctorGetSession(ctor);
@@ -1081,7 +1097,7 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tor->anyDate = now; tor->anyDate = now;
tr_resume::fields_t loaded = {}; tr_resume::fields_t loaded = {};
if (tor->hasMetainfo())
{ {
// tr_resume::load() calls a lot of tr_torrentSetFoo() methods // tr_resume::load() calls a lot of tr_torrentSetFoo() methods
// that set things as dirty, but... these settings being loaded are // that set things as dirty, but... these settings being loaded are
@@ -1106,9 +1122,6 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tor->refreshCurrentDir(); tor->refreshCurrentDir();
bool const do_start = tor->isRunning;
tor->isRunning = false;
if ((loaded & tr_resume::Speedlimit) == 0) if ((loaded & tr_resume::Speedlimit) == 0)
{ {
tor->useSpeedLimit(TR_UP, false); tor->useSpeedLimit(TR_UP, false);
@@ -1174,37 +1187,14 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tor->torrent_announcer = session->announcer_->addTorrent(tor, &tr_torrent::onTrackerResponse); tor->torrent_announcer = session->announcer_->addTorrent(tor, &tr_torrent::onTrackerResponse);
if (is_new_torrent) if (auto const has_metainfo = tor->hasMetainfo(); is_new_torrent && has_metainfo)
{ {
if (tor->hasMetainfo()) on_metainfo_completed(tor);
{
callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
}
if (!tor->hasMetainfo() && !do_start)
{
auto opts = torrent_start_opts{};
opts.bypass_queue = true;
opts.has_local_data = has_local_data;
torrentStart(tor, opts);
}
else if (!session->shouldFullyVerifyAddedTorrents() && isNewTorrentASeed(tor))
{
tor->completion.setHasAll();
tor->doneDate = tor->addedDate;
tor->recheckCompleteness();
}
else
{
tor->startAfterVerify = do_start;
tr_torrentVerify(tor);
}
} }
else if (do_start) else if (tor->start_when_stable || !has_metainfo)
{ {
// if checked_pieces_ got populated from the loading the resume
// file above, then torrentStart doesn't need to check again
auto opts = torrent_start_opts{}; auto opts = torrent_start_opts{};
opts.bypass_queue = !has_metainfo; // to fetch metainfo from peers
opts.has_local_data = has_local_data; opts.has_local_data = has_local_data;
torrentStart(tor, opts); torrentStart(tor, opts);
} }
@@ -1216,16 +1206,20 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
} // namespace torrent_init_helpers } // namespace torrent_init_helpers
} // namespace } // namespace
void tr_torrent::setMetainfo(tr_torrent_metainfo const& tm) void tr_torrent::setMetainfo(tr_torrent_metainfo tm)
{ {
using namespace torrent_init_helpers; using namespace torrent_init_helpers;
metainfo_ = tm; TR_ASSERT(!hasMetainfo());
metainfo_ = std::move(tm);
torrentInitFromInfoDict(this); torrentInitFromInfoDict(this);
tr_peerMgrOnTorrentGotMetainfo(this); tr_peerMgrOnTorrentGotMetainfo(this);
session->onMetadataCompleted(this); session->onMetadataCompleted(this);
this->setDirty(); this->setDirty();
this->markEdited();
on_metainfo_completed(this);
} }
tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of) tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of)
@@ -1763,33 +1757,35 @@ void tr_torrentAmountFinished(tr_torrent const* tor, float* tabs, int n_tabs)
// --- Start/Stop Callback // --- Start/Stop Callback
namespace
{
void tr_torrentStartImpl(tr_torrent* tor, bool bypass_queue)
{
if (!tr_isTorrent(tor))
{
return;
}
tor->start_when_stable = true;
auto opts = torrent_start_opts{};
opts.bypass_queue = bypass_queue;
torrentStart(tor, opts);
}
} // namespace
void tr_torrentStart(tr_torrent* tor) void tr_torrentStart(tr_torrent* tor)
{ {
if (tr_isTorrent(tor)) tr_torrentStartImpl(tor, false);
{
tor->startAfterVerify = true;
torrentStart(tor, {});
}
} }
void tr_torrentStartNow(tr_torrent* tor) void tr_torrentStartNow(tr_torrent* tor)
{ {
if (tr_isTorrent(tor)) tr_torrentStartImpl(tor, true);
{
auto opts = torrent_start_opts{};
opts.bypass_queue = true;
torrentStart(tor, opts);
}
} }
void tr_torrentStartMagnet(tr_torrent* tor) void tr_torrentStartMagnet(tr_torrent* tor)
{ {
if (tr_isTorrent(tor)) tr_torrentStart(tor);
{
tor->magnetStartAfterVerify = true;
tor->startAfterVerify = true;
torrentStart(tor, {});
}
} }
// --- // ---
@@ -1809,10 +1805,8 @@ void onVerifyDoneThreadFunc(tr_torrent* const tor)
tor->recheckCompleteness(); tor->recheckCompleteness();
if (tor->startAfterVerify) if (tor->start_when_stable)
{ {
tor->startAfterVerify = false;
auto opts = torrent_start_opts{}; auto opts = torrent_start_opts{};
opts.has_local_data = !tor->checked_pieces_.hasNone(); opts.has_local_data = !tor->checked_pieces_.hasNone();
torrentStart(tor, opts); torrentStart(tor, opts);
@@ -1832,20 +1826,18 @@ void verifyTorrent(tr_torrent* const tor)
/* if the torrent's already being verified, stop it */ /* if the torrent's already being verified, stop it */
tor->session->verifyRemove(tor); tor->session->verifyRemove(tor);
bool const start_after = (tor->isRunning || tor->startAfterVerify) && !tor->isStopping; if (!tor->hasMetainfo())
{
return;
}
if (tor->isRunning) if (tor->isRunning)
{ {
tr_torrentStop(tor); torrentStop(tor);
} }
if (setLocalErrorIfFilesDisappeared(tor)) if (!setLocalErrorIfFilesDisappeared(tor))
{ {
tor->startAfterVerify = false;
}
else
{
tor->startAfterVerify = start_after;
tor->session->verifyAdd(tor); tor->session->verifyAdd(tor);
} }
} }

View File

@@ -109,7 +109,8 @@ public:
// but more refactoring is needed before that can happen // but more refactoring is needed before that can happen
// because much of tr_torrent's impl is in the non-member C bindings // because much of tr_torrent's impl is in the non-member C bindings
void setMetainfo(tr_torrent_metainfo const& tm); // Used to add metainfo to a magnet torrent.
void setMetainfo(tr_torrent_metainfo tm);
[[nodiscard]] auto unique_lock() const [[nodiscard]] auto unique_lock() const
{ {
@@ -903,10 +904,10 @@ public:
bool is_queued = false; bool is_queued = false;
bool isRunning = false; bool isRunning = false;
bool isStopping = false; bool isStopping = false;
bool startAfterVerify = false;
bool magnetStartAfterVerify = false;
bool magnetVerify = false; // start the torrent after all the startup scaffolding is done,
// e.g. fetching metadata from peers and/or verifying the torrent
bool start_when_stable = false;
private: private:
[[nodiscard]] constexpr bool isPieceTransferAllowed(tr_direction direction) const noexcept [[nodiscard]] constexpr bool isPieceTransferAllowed(tr_direction direction) const noexcept

View File

@@ -601,7 +601,7 @@ void tr_sessionSetAntiBruteForceEnabled(tr_session* session, bool enabled);
/** @brief Like `tr_torrentStart()`, but resumes right away regardless of the queues. */ /** @brief Like `tr_torrentStart()`, but resumes right away regardless of the queues. */
void tr_torrentStartNow(tr_torrent* tor); void tr_torrentStartNow(tr_torrent* tor);
/** @brief Like tr_torrentStart(), but sets magnetStartAfterVerify to true. */ /** @brief DEPRECATED. Equivalent to tr_torrentStart(). Use that instead. */
void tr_torrentStartMagnet(tr_torrent*); void tr_torrentStartMagnet(tr_torrent*);
/** @brief Return the queued torrent's position in the queue it's in. [0...n) */ /** @brief Return the queued torrent's position in the queue it's in. [0...n) */

View File

@@ -280,7 +280,7 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error** error)
{ {
if ([self alertForRemainingDiskSpace]) if ([self alertForRemainingDiskSpace])
{ {
tr_torrentStartMagnet(self.fHandle); tr_torrentStart(self.fHandle);
[self update]; [self update];
//capture, specifically, stop-seeding settings changing to unlimited //capture, specifically, stop-seeding settings changing to unlimited