diff --git a/include/libtorrent/alert.hpp b/include/libtorrent/alert.hpp index 29844ca11..d977091b8 100644 --- a/include/libtorrent/alert.hpp +++ b/include/libtorrent/alert.hpp @@ -54,8 +54,8 @@ POSSIBILITY OF SUCH DAMAGE. // alerts (warnings, messages and errors from libtorrent). If no alerts have // been posted by libtorrent pop_alerts() will return an empty list. // -// By default, only errors are reported. set_alert_mask() can be used to -// specify which kinds of events should be reported. The alert mask is +// By default, only errors are reported. session_settings::alert_mask can be +// used to specify which kinds of events should be reported. The alert mask is // comprised by bits from the category_t enum. // // Every alert belongs to one or more category. There is a cost associated with @@ -105,7 +105,8 @@ namespace libtorrent { enum severity_t { debug, info, warning, critical, fatal, none }; #endif - // these are bits for the alert_mask used by the session. See set_alert_mask(). + // these are bits for the alert_mask used by the session. See + // settings_pack::alert_mask. enum category_t { // Enables alerts that report an error. This includes: diff --git a/simulation/swarm_suite.cpp b/simulation/swarm_suite.cpp index 4c3342c02..1a7b0b527 100644 --- a/simulation/swarm_suite.cpp +++ b/simulation/swarm_suite.cpp @@ -50,13 +50,101 @@ struct test_swarm_config : swarm_config test_swarm_config(int flags) : swarm_config() , m_flags(flags) + , m_paused_once(false) + , m_resumed_once(false) {} virtual void on_exit(std::vector const& torrents) override { swarm_config::on_exit(torrents); - TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2100)); + // if we stopped and started again, we loose some time and need a bit + // more slack for completion + if (m_flags & stop_start_seed) + { + TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(4700)); + } + else if (m_flags & stop_start_download) + { + TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2800)); + } + else + { + TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2100)); + } + } + + virtual bool on_alert(libtorrent::alert const* alert + , int session_idx + , std::vector const& torrents + , libtorrent::session& ses) override + { + if (((m_flags & stop_start_download) + || (m_flags & stop_start_seed)) + && m_paused_once == false) + { + torrent_status st_seed = torrents[0].status(); + torrent_status st_dl = torrents[1].status(); + + int flags = 0; + if (m_flags & graceful_pause) + flags = torrent_handle::graceful_pause; + + if (m_flags & stop_start_download) + { + if (st_dl.total_wanted_done > st_dl.total_wanted / 2 + && st_dl.paused == false) + { + m_paused_once = true; + torrents[1].auto_managed(false); + torrents[1].pause(flags); + } + } + + if (m_flags & stop_start_seed) + { + if (st_dl.total_wanted_done > st_dl.total_wanted / 2 + && st_seed.paused == false) + { + m_paused_once = true; + torrents[0].auto_managed(false); + torrents[0].pause(flags); + } + } + } + + if (alert_cast(alert)) + { + TEST_EQUAL(m_resumed_once, false); + + if (m_flags & stop_start_download) + { + torrents[1].resume(); + m_resumed_once = true; + } + + if (m_flags & stop_start_seed) + { + torrents[0].resume(); + m_resumed_once = true; + } + } + + return swarm_config::on_alert(alert, session_idx, torrents, ses); + } + + virtual void on_torrent_added(int session_index, torrent_handle h) override + { + if (m_flags & add_extra_peers) + { + for (int i = 0; i < 30; ++i) + { + char ep[30]; + snprintf(ep, sizeof(ep), "60.0.0.%d", i + 1); + h.connect_peer(lt::tcp::endpoint( + lt::address_v4::from_string(ep), 6881)); + } + } } // called for every torrent that's added (and every session that's started). @@ -112,16 +200,19 @@ struct test_swarm_config : swarm_config pack.set_bool(settings_pack::enable_outgoing_tcp, true); } + pack.set_int(settings_pack::alert_mask, alert::all_categories); return pack; } private: int m_flags; + bool m_paused_once; + bool m_resumed_once; }; void simulate_swarm(int flags) { - fprintf(stderr, "\n\n ==== TEST SWARM === %s%s%s%s%s%s%s ===\n\n\n" + fprintf(stderr, "\n\n ==== TEST SWARM === %s%s%s%s%s%s%s%s%s%s===\n\n\n" , (flags & super_seeding) ? "super-seeding ": "" , (flags & strict_super_seeding) ? "strict-super-seeding ": "" , (flags & seed_mode) ? "seed-mode ": "" @@ -129,6 +220,9 @@ void simulate_swarm(int flags) , (flags & suggest_read_cache) ? "suggest-read-cache ": "" , (flags & explicit_cache) ? "explicit-cache ": "" , (flags & utp_only) ? "utp-only": "" + , (flags & stop_start_download) ? "stop-start-download ": "" + , (flags & stop_start_seed) ? "stop-start-seed ": "" + , (flags & stop_start_seed) ? "graceful-pause ": "" ); test_swarm_config cfg(flags); diff --git a/simulation/swarm_suite.hpp b/simulation/swarm_suite.hpp index 76bd88bac..0021c89ca 100644 --- a/simulation/swarm_suite.hpp +++ b/simulation/swarm_suite.hpp @@ -40,7 +40,11 @@ enum test_flags_t time_critical = 8, suggest_read_cache = 16, explicit_cache = 32, - utp_only = 64 + utp_only = 64, + stop_start_download = 128, + stop_start_seed = 256, + graceful_pause = 1024, + add_extra_peers = 2048 }; void EXPORT simulate_swarm(int flags = 0); diff --git a/simulation/test_swarm.cpp b/simulation/test_swarm.cpp index 8b53569e8..3548ab590 100644 --- a/simulation/test_swarm.cpp +++ b/simulation/test_swarm.cpp @@ -54,6 +54,26 @@ TORRENT_TEST(utp) { simulate_swarm(utp_only); } + +TORRENT_TEST(stop_start_download) +{ + simulate_swarm(stop_start_download | add_extra_peers); +} +TORRENT_TEST(stop_start_download_graceful) +{ + simulate_swarm(stop_start_download | graceful_pause | add_extra_peers); +} + +TORRENT_TEST(stop_start_seed) +{ + simulate_swarm(stop_start_seed | add_extra_peers); +} + +TORRENT_TEST(stop_start_seed_graceful) +{ + simulate_swarm(stop_start_seed | graceful_pause | add_extra_peers); +} + TORRENT_TEST(explicit_cache) { // test explicit cache diff --git a/src/torrent.cpp b/src/torrent.cpp index 1837d47d8..d2d14a75a 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -6086,6 +6086,16 @@ namespace libtorrent p->set_peer_info(0); TORRENT_ASSERT(i != m_connections.end()); m_connections.erase(i); + + if (m_graceful_pause_mode && m_connections.empty()) + { + // we're in graceful pause mode and this was the last peer we + // disconnected. This will clear the graceful_pause_mode and post the + // torrent_paused_alert. + TORRENT_ASSERT(is_paused()); + set_allow_peers(false); + } + update_want_peers(); update_want_tick(); }