diff --git a/ChangeLog b/ChangeLog index 060a3879d..ccbd4d0e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -88,6 +88,8 @@ * resume data no longer has timestamps of files * require C++11 to build libtorrent + * improve connect-boost feature, to make new torrents quickly connect peers + 1.1.9 release * save both file and piece priorities in resume file diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index e762f941b..914a91d47 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -1444,6 +1444,7 @@ namespace libtorrent { // them starting up. The normal connect scheduler is run once every // second, this allows peers to be connected immediately instead of // waiting for the session tick to trigger connections. + // This may not be set higher than 255. torrent_connect_boost, // ``alert_queue_size`` is the maximum number of alerts queued up diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 8e6bc2aa6..2ca975db1 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -1568,13 +1568,6 @@ namespace libtorrent { // 1 bit here - // this is set to true when the torrent starts up - // The first tracker response, when this is true, - // will attempt to connect to a bunch of peers immediately - // and set this to false. We only do this once to get - // the torrent kick-started - bool m_need_connect_boost:1; - // rotating sequence number for LSD announces sent out. // used to only use IP broadcast for every 8th lsd announce std::uint8_t m_lsd_seq:3; @@ -1601,7 +1594,14 @@ namespace libtorrent { // the number of bytes of padding files std::uint32_t m_padding:24; - // TODO: gap of 8 bits available here + // this is set to the connect boost quota for this torrent. + // After having received this many priority peer connection attempts, it + // falls back onto the steady state peer connection logic, driven by the + // session tick. Each tracker response, as long as this is non-zero, will + // attempt to connect to peers immediately and decrement the counter. + // We give torrents a connect boost when they are first added and then + // every time they resume from being paused. + std::uint8_t m_connect_boost_counter; // ---- diff --git a/include/libtorrent/torrent_flags.hpp b/include/libtorrent/torrent_flags.hpp index 7dc7c85e1..d078bd1a3 100644 --- a/include/libtorrent/torrent_flags.hpp +++ b/include/libtorrent/torrent_flags.hpp @@ -175,6 +175,11 @@ namespace torrent_flags { // for the state_changed_alert and then call pause(). The download/seeding // will most likely start in between posting the alert and receiving the // call to pause. + // + // A downloading state is one where peers are being connected. Which means + // just downloading the metadata via the ``ut_metadata`` extension counts + // as a downloading state. In order to stop a torrent once the metadata + // has been downloaded, instead set all file priorities to dont_download constexpr torrent_flags_t stop_when_ready = 10_bit; // when this flag is set, the tracker list in the add_torrent_params diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 34520656b..86cf0a922 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -689,9 +689,8 @@ TORRENT_IPV6_NAMESPACE_END // extern int outstanding_resume_data; // global counter of outstanding resume data // std::vector handles = ses.get_torrents(); // ses.pause(); - // for (torrent_handle i : handles) + // for (torrent_handle const& h : handles) // { - // torrent_handle& h = *i; // if (!h.is_valid()) continue; // torrent_status s = h.status(); // if (!s.has_metadata || !s.need_save_resume_data()) continue; @@ -705,7 +704,7 @@ TORRENT_IPV6_NAMESPACE_END // alert const* a = ses.wait_for_alert(seconds(10)); // // // if we don't get an alert within 10 seconds, abort - // if (a == 0) break; + // if (a == nullptr) break; // // std::vector alerts; // ses.pop_alerts(&alerts); @@ -720,7 +719,7 @@ TORRENT_IPV6_NAMESPACE_END // } // // save_resume_data_alert const* rd = alert_cast(a); - // if (rd == 0) + // if (rd == nullptr) // { // process_alert(a); // continue; @@ -754,9 +753,10 @@ TORRENT_IPV6_NAMESPACE_END // time. // //.. note:: - // A torrent's resume data is considered saved as soon as the alert is - // posted. It is important to make sure this alert is received and - // handled in order for this function to be meaningful. + // A torrent's resume data is considered saved as soon as the + // save_resume_data_alert is posted. It is important to make sure this + // alert is received and handled in order for this function to be + // meaningful. bool need_save_resume_data() const; // Every torrent that is added is assigned a queue position exactly one diff --git a/simulation/test_swarm.cpp b/simulation/test_swarm.cpp index 6e0bd2b42..7f2f85518 100644 --- a/simulation/test_swarm.cpp +++ b/simulation/test_swarm.cpp @@ -299,7 +299,7 @@ void test_stop_start_download(swarm_test type, bool graceful) std::printf("tick: %d\n", ticks); - const int timeout = type == swarm_test::download ? 20 : 100; + const int timeout = type == swarm_test::download ? 21 : 100; if (ticks > timeout) { TEST_ERROR("timeout"); diff --git a/src/session.cpp b/src/session.cpp index ab733aa05..b02fcaedb 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -275,9 +275,7 @@ namespace { // number of disk threads for low level file operations set.set_int(settings_pack::aio_threads, 8); - // keep 5 MiB outstanding when checking hashes - // of a resumed file - set.set_int(settings_pack::checking_mem_usage, 320); + set.set_int(settings_pack::checking_mem_usage, 2048); return set; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index cf9e09522..aa0dead96 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -4085,16 +4085,14 @@ namespace aux { // attempt this tick int max_connections = m_settings.get_int(settings_pack::connection_speed); - // zero connections speeds are allowed, we just won't make any connections - if (max_connections <= 0) return; - // this loop will "hand out" connection_speed to the torrents, in a round // robin fashion, so that every torrent is equally likely to connect to a // peer // boost connections are connections made by torrent connection // boost, which are done immediately on a tracker response. These - // connections needs to be deducted from this second + // connections needs to be deducted from the regular connection attempt + // quota for this tick if (m_boost_connections > 0) { if (m_boost_connections > max_connections) @@ -4109,6 +4107,9 @@ namespace aux { } } + // zero connections speeds are allowed, we just won't make any connections + if (max_connections <= 0) return; + // TODO: use a lower limit than m_settings.connections_limit // to allocate the to 10% or so of connection slots for incoming // connections diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 0df55d41a..414ca52f2 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -233,7 +233,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0; SET(max_failcount, 3, &session_impl::update_max_failcount), SET(min_reconnect_time, 60, nullptr), SET(peer_connect_timeout, 15, nullptr), - SET(connection_speed, 10, &session_impl::update_connection_speed), + SET(connection_speed, 30, &session_impl::update_connection_speed), SET(inactivity_timeout, 600, nullptr), SET(unchoke_interval, 15, nullptr), SET(optimistic_unchoke_interval, 30, nullptr), @@ -313,7 +313,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0; SET(utp_loss_multiplier, 50, nullptr), SET(mixed_mode_algorithm, settings_pack::peer_proportional, nullptr), SET(listen_queue_size, 5, nullptr), - SET(torrent_connect_boost, 10, nullptr), + SET(torrent_connect_boost, 80, nullptr), SET(alert_queue_size, 1000, &session_impl::update_alert_queue_size), SET(max_metadata_size, 3 * 1024 * 10240, nullptr), DEPRECATED_SET(hashing_threads, 1, nullptr), diff --git a/src/storage.cpp b/src/storage.cpp index 40eaa4e5e..692d49579 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -139,7 +139,7 @@ namespace libtorrent { return; } - if (m_part_file) + if (m_part_file && use_partfile(i)) { m_part_file->export_file([&f, &ec](std::int64_t file_offset, span buf) { diff --git a/src/torrent.cpp b/src/torrent.cpp index da36bd584..d26833863 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -207,12 +207,12 @@ bool is_downloading_state(int const st) , m_max_uploads((1 << 24) - 1) , m_save_resume_flags() , m_num_uploads(0) - , m_need_connect_boost(true) , m_lsd_seq(0) , m_magnet_link(false) , m_apply_ip_filter(p.flags & torrent_flags::apply_ip_filter) , m_pending_active_change(false) , m_padding(0) + , m_connect_boost_counter(static_cast(settings().get_int(settings_pack::torrent_connect_boost))) , m_incomplete(0xffffff) , m_announce_to_dht(!(p.flags & torrent_flags::paused)) , m_ssl_torrent(false) @@ -3267,23 +3267,24 @@ bool is_downloading_state(int const st) void torrent::do_connect_boost() { - if (!m_need_connect_boost) return; + if (m_connect_boost_counter == 0) return; // this is the first tracker response for this torrent // instead of waiting one second for session_impl::on_tick() // to be called, connect to a few peers immediately - int conns = std::min( - settings().get_int(settings_pack::torrent_connect_boost) + int conns = std::min(int(m_connect_boost_counter) , settings().get_int(settings_pack::connections_limit) - m_ses.num_connections()); - if (conns > 0) m_need_connect_boost = false; + if (conns == 0) return; // if we don't know of any peers if (!m_peer_list) return; while (want_peers() && conns > 0) { + TORRENT_ASSERT(m_connect_boost_counter > 0); --conns; + --m_connect_boost_counter; torrent_state st = get_peer_list_state(); torrent_peer* p = m_peer_list->connect_one_peer(m_ses.session_time(), &st); peers_erased(st.erased); @@ -8496,7 +8497,8 @@ bool is_downloading_state(int const st) } #endif - m_need_connect_boost = true; + m_connect_boost_counter + = static_cast(settings().get_int(settings_pack::torrent_connect_boost)); m_inactive = false; update_state_list(); diff --git a/src/ut_pex.cpp b/src/ut_pex.cpp index e2f74fd9c..70559b3b0 100644 --- a/src/ut_pex.cpp +++ b/src/ut_pex.cpp @@ -321,6 +321,7 @@ namespace libtorrent { namespace { p = pex_msg.dict_find_string("added"); bdecode_node const pf = pex_msg.dict_find_string("added.f"); + bool peers_added = false; #ifndef TORRENT_DISABLE_LOGGING if (p) num_added += p.string_length() / 6; #endif @@ -347,6 +348,7 @@ namespace libtorrent { namespace { if (j != m_peers.end() && *j == v) continue; m_peers.insert(j, v); m_torrent.add_peer(adr, peer_info::pex, flags); + peers_added = true; } } @@ -398,6 +400,7 @@ namespace libtorrent { namespace { if (j != m_peers6.end() && *j == v) continue; m_peers6.insert(j, v); m_torrent.add_peer(adr, peer_info::pex, flags); + peers_added = true; } } #endif @@ -407,6 +410,8 @@ namespace libtorrent { namespace { #endif m_pc.stats_counters().inc_stats_counter(counters::num_incoming_pex); + + if (peers_added) m_torrent.do_connect_boost(); return true; } diff --git a/test/test_ssl.cpp b/test/test_ssl.cpp index 578cf99ca..f2f193aee 100644 --- a/test/test_ssl.cpp +++ b/test/test_ssl.cpp @@ -79,7 +79,7 @@ struct test_config_t int ssl_disconnects; }; -test_config_t test_config[] = +test_config_t const test_config[] = { // name sslport sd-cert dl-cert dl-port expect peer-error ssl-disconn {"nobody has a cert (connect to regular port)", false, false, false, true, false, 0, 1}, @@ -125,7 +125,7 @@ bool on_alert(alert const* a) return false; } -void test_ssl(int test_idx, bool use_utp) +void test_ssl(int const test_idx, bool const use_utp) { // these are declared before the session objects // so that they are destructed last. This enables @@ -289,10 +289,13 @@ void test_ssl(int test_idx, bool use_utp) std::printf("peer_errors: %d expected_errors: %d\n" , peer_errors, test.peer_errors); - TEST_EQUAL(peer_errors > 0, test.peer_errors > 0); std::printf("ssl_disconnects: %d expected: %d\n", ssl_peer_disconnects, test.ssl_disconnects); - TEST_EQUAL(ssl_peer_disconnects > 0, test.ssl_disconnects > 0); + if (!use_utp) + { + TEST_EQUAL(ssl_peer_disconnects > 0, test.ssl_disconnects > 0); + TEST_EQUAL(peer_errors > 0, test.peer_errors > 0); + } char const* now = time_now_string(); std::printf("%s: EXPECT: %s\n", now, test.expected_to_complete ? "SUCCEESS" : "FAILURE"); @@ -328,7 +331,7 @@ enum attack_flags_t valid_bittorrent_hash = 16, }; -attack_t attacks[] = +attack_t const attacks[] = { // positive test { valid_certificate | valid_sni_hash | valid_bittorrent_hash, true},