forked from premiere/premiere-libtorrent
add stop-when-ready feature, to support checking torrents without starting the download afterwards
This commit is contained in:
parent
5c96a35a66
commit
51c6079c42
|
@ -1,3 +1,4 @@
|
|||
* add feature to stop torrents immediately after checking files is done
|
||||
* make all non-auto managed torrents exempt from queuing logic, including
|
||||
checking torrents.
|
||||
* add option to not proxy tracker connections through proxy
|
||||
|
|
|
@ -616,6 +616,7 @@ void bind_session()
|
|||
.value("flag_sequential_download", add_torrent_params::flag_sequential_download)
|
||||
.value("flag_use_resume_save_path", add_torrent_params::flag_use_resume_save_path)
|
||||
.value("flag_merge_resume_http_seeds", add_torrent_params::flag_merge_resume_http_seeds)
|
||||
.value("flag_stop_when_ready", add_torrent_params::flag_stop_when_ready)
|
||||
;
|
||||
class_<cache_status>("cache_status")
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
|
|
|
@ -417,6 +417,7 @@ void bind_torrent_handle()
|
|||
.def("is_valid", _(&torrent_handle::is_valid))
|
||||
.def("pause", _(&torrent_handle::pause), arg("flags") = 0)
|
||||
.def("resume", _(&torrent_handle::resume))
|
||||
.def("stop_when_ready", _(&torrent_handle::stop_when_ready))
|
||||
.def("clear_error", _(&torrent_handle::clear_error))
|
||||
.def("set_priority", _(&torrent_handle::set_priority))
|
||||
.def("super_seeding", super_seeding1)
|
||||
|
|
|
@ -28,6 +28,7 @@ void bind_torrent_status()
|
|||
.def_readonly("info_hash", &torrent_status::info_hash)
|
||||
.def_readonly("state", &torrent_status::state)
|
||||
.def_readonly("paused", &torrent_status::paused)
|
||||
.def_readonly("stop_when_ready", &torrent_status::stop_when_ready)
|
||||
.def_readonly("auto_managed", &torrent_status::auto_managed)
|
||||
.def_readonly("sequential_download", &torrent_status::sequential_download)
|
||||
.def_readonly("is_seeding", &torrent_status::is_seeding)
|
||||
|
|
|
@ -267,6 +267,11 @@ namespace libtorrent
|
|||
// is passed in here as well as the .torrent file.
|
||||
flag_merge_resume_http_seeds = 0x2000,
|
||||
|
||||
// the stop when ready flag. Setting this flag is equivalent to calling
|
||||
// torrent_handle::stop_when_ready() immediately after the torrent is
|
||||
// added.
|
||||
flag_stop_when_ready = 0x4000,
|
||||
|
||||
// internal
|
||||
default_flags = flag_pinned | flag_update_subscribe
|
||||
| flag_auto_managed | flag_paused | flag_apply_ip_filter
|
||||
|
|
|
@ -478,6 +478,8 @@ namespace libtorrent
|
|||
void set_announce_to_trackers(bool b) { m_announce_to_trackers = b; }
|
||||
void set_announce_to_lsd(bool b) { m_announce_to_lsd = b; }
|
||||
|
||||
void stop_when_ready(bool b) { m_stop_when_ready = b; }
|
||||
|
||||
int started() const { return m_started; }
|
||||
void step_session_time(int seconds);
|
||||
void do_pause();
|
||||
|
@ -1700,6 +1702,10 @@ namespace libtorrent
|
|||
// file
|
||||
bool m_merge_resume_http_seeds:1;
|
||||
|
||||
// if this is set, whenever transitioning into a downloading/seeding state
|
||||
// from a non-downloading/seeding state, the torrent is paused.
|
||||
bool m_stop_when_ready:1;
|
||||
|
||||
#if TORRENT_USE_ASSERTS
|
||||
public:
|
||||
// set to false until we've loaded resume data
|
||||
|
|
|
@ -554,6 +554,19 @@ namespace libtorrent
|
|||
void pause(int flags = 0) const;
|
||||
void resume() const;
|
||||
|
||||
// set or clear the stop-when-ready flag. When this flag is set, the
|
||||
// torrent will *force stop* whenever it transitions from a
|
||||
// non-data-transferring state into a data-transferring state (referred to
|
||||
// as being ready to download or seed). This is useful for torrents that
|
||||
// should not start downloading or seeding yet, but what to be made ready
|
||||
// to do so. A torrent may need to have its files checked for instance, so
|
||||
// it needs to be started and possibly queued for checking (auto-managed
|
||||
// and started) but as soon as it's done, it should be stopped.
|
||||
//
|
||||
// *Force stopped* means auto-managed is set to false and it's paused. As
|
||||
// if auto_manage(false) and pause() were called on the torrent.
|
||||
void stop_when_ready(bool b) const;
|
||||
|
||||
// Explicitly sets the upload mode of the torrent. In upload mode, the
|
||||
// torrent will not request any pieces. If the torrent is auto managed,
|
||||
// it will automatically be taken out of upload mode periodically (see
|
||||
|
|
|
@ -485,6 +485,11 @@ namespace libtorrent
|
|||
bool announcing_to_lsd;
|
||||
bool announcing_to_dht;
|
||||
|
||||
// this reflects whether the ``stop_when_ready`` flag is currently enabled
|
||||
// on this torrent. For more information, see
|
||||
// torrent_handle::stop_when_ready().
|
||||
bool stop_when_ready;
|
||||
|
||||
// the info-hash for this torrent
|
||||
sha1_hash info_hash;
|
||||
};
|
||||
|
|
|
@ -349,7 +349,6 @@ TORRENT_TEST(seed_limit)
|
|||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
@ -439,7 +438,6 @@ TORRENT_TEST(download_limit)
|
|||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
@ -538,7 +536,6 @@ TORRENT_TEST(checking_announce)
|
|||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
@ -590,7 +587,6 @@ TORRENT_TEST(paused_checking)
|
|||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
@ -619,6 +615,71 @@ TORRENT_TEST(paused_checking)
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
// set the stop_when_ready flag and make sure we receive a paused alert *before*
|
||||
// a state_changed_alert
|
||||
TORRENT_TEST(stop_when_ready)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
lt::add_torrent_params params = create_torrent(0, true);
|
||||
// torrents are started and auto-managed
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_stop_when_ready;
|
||||
// we need this to get the tracker_announce_alert
|
||||
params.trackers.push_back("http://10.10.0.2/announce");
|
||||
ses.async_add_torrent(params);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_paused = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
|
||||
if (alert_cast<torrent_paused_alert>(a))
|
||||
{
|
||||
++num_paused;
|
||||
}
|
||||
|
||||
if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
|
||||
{
|
||||
if (sc->state == torrent_status::seeding)
|
||||
{
|
||||
// once we turn into beeing a seed. we should have been paused
|
||||
// already.
|
||||
TEST_EQUAL(num_paused, 1);
|
||||
}
|
||||
}
|
||||
// there should not have been any announces. the torrent should have
|
||||
// been stopped *before* announcing.
|
||||
TEST_EQUAL(alert_cast<tracker_announce_alert>(a), NULL);
|
||||
}
|
||||
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
// the torrent should have been force-stopped (after checking was
|
||||
// donw, because we set the stop_when_ready flag). Force stopped
|
||||
// means not auto-managed and paused.
|
||||
torrent_status st = h.status();
|
||||
TEST_CHECK(!st.auto_managed);
|
||||
TEST_EQUAL(st.paused, true);
|
||||
// it should be seeding. If it's not seeding it may not have had its
|
||||
// files checked.
|
||||
TEST_EQUAL(st.state, torrent_status::seeding);
|
||||
}
|
||||
});
|
||||
}
|
||||
// TODO: assert that the torrent_paused_alert is posted when pausing
|
||||
// downloading, seeding, checking torrents as well as the graceful pause
|
||||
// TODO: test limits of tracker, DHT and LSD announces
|
||||
|
|
|
@ -279,6 +279,7 @@ namespace libtorrent
|
|||
, m_pending_active_change(false)
|
||||
, m_use_resume_save_path(p.flags & add_torrent_params::flag_use_resume_save_path)
|
||||
, m_merge_resume_http_seeds(p.flags & add_torrent_params::flag_merge_resume_http_seeds)
|
||||
, m_stop_when_ready(p.flags & add_torrent_params::flag_stop_when_ready)
|
||||
{
|
||||
// we cannot log in the constructor, because it relies on shared_from_this
|
||||
// being initialized, which happens after the constructor returns.
|
||||
|
@ -11610,6 +11611,29 @@ namespace libtorrent
|
|||
if (m_peer_list) m_peer_list->clear_peer_prio();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool is_downloading_state(int st)
|
||||
{
|
||||
switch (st)
|
||||
{
|
||||
case torrent_status::checking_files:
|
||||
case torrent_status::allocating:
|
||||
case torrent_status::checking_resume_data:
|
||||
return false;
|
||||
case torrent_status::downloading_metadata:
|
||||
case torrent_status::downloading:
|
||||
case torrent_status::finished:
|
||||
case torrent_status::seeding:
|
||||
return true;
|
||||
default:
|
||||
// unexpected state
|
||||
TORRENT_ASSERT_VAL(false, st);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::set_state(torrent_status::state_t s)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
@ -11643,6 +11667,21 @@ namespace libtorrent
|
|||
get_handle());
|
||||
}
|
||||
|
||||
if (m_stop_when_ready
|
||||
&& !is_downloading_state(m_state)
|
||||
&& is_downloading_state(s))
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("stop_when_ready triggered");
|
||||
#endif
|
||||
// stop_when_ready is set, and we're transitioning from a downloading
|
||||
// state to a non-downloading state. pause the torrent. Note that
|
||||
// "downloading" is defined broadly to include any state where we
|
||||
// either upload or download (for the purpose of this flag).
|
||||
auto_managed(false);
|
||||
pause();
|
||||
}
|
||||
|
||||
m_state = s;
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
@ -11742,6 +11781,7 @@ namespace libtorrent
|
|||
st->announcing_to_trackers = m_announce_to_trackers;
|
||||
st->announcing_to_lsd = m_announce_to_lsd;
|
||||
st->announcing_to_dht = m_announce_to_dht;
|
||||
st->stop_when_ready = m_stop_when_ready;
|
||||
|
||||
st->added_time = m_added_time;
|
||||
st->completed_time = m_completed_time;
|
||||
|
|
|
@ -329,6 +329,11 @@ namespace libtorrent
|
|||
TORRENT_ASYNC_CALL1(pause, bool(flags & graceful_pause));
|
||||
}
|
||||
|
||||
void torrent_handle::stop_when_ready(bool b) const
|
||||
{
|
||||
TORRENT_ASYNC_CALL1(stop_when_ready, b);
|
||||
}
|
||||
|
||||
void torrent_handle::apply_ip_filter(bool b) const
|
||||
{
|
||||
TORRENT_ASYNC_CALL1(set_apply_ip_filter, b);
|
||||
|
|
Loading…
Reference in New Issue