From 7e851818b1d50721b134830d415828d08b35bf66 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 29 Mar 2010 00:34:04 +0000 Subject: [PATCH] support more fine-grained torrent states between which peer sources it announces too --- ChangeLog | 2 + bindings/python/src/session_settings.cpp | 4 ++ docs/manual.rst | 17 ++++++ include/libtorrent/aux_/session_impl.hpp | 5 +- include/libtorrent/session_settings.hpp | 12 ++++ include/libtorrent/torrent.hpp | 22 ++++++- src/peer_connection.cpp | 6 +- src/session.cpp | 2 + src/session_impl.cpp | 30 +++++++--- src/torrent.cpp | 73 ++++++++++++++++++------ 10 files changed, 141 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 875dbde86..1659726ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * support more fine-grained torrent states between which peer sources it + announces to * supports calculating sha1 file-hashes when creating torrents * made the send_buffer_watermark performance warning more meaningful * supports complete_ago extension diff --git a/bindings/python/src/session_settings.cpp b/bindings/python/src/session_settings.cpp index 1a6951dd7..cb56ea6a7 100644 --- a/bindings/python/src/session_settings.cpp +++ b/bindings/python/src/session_settings.cpp @@ -67,6 +67,9 @@ void bind_session_settings() .def_readwrite("peer_tos", &session_settings::peer_tos) .def_readwrite("active_downloads", &session_settings::active_downloads) .def_readwrite("active_seeds", &session_settings::active_seeds) + .def_readwrite("active_dht_limit", &session_settings::active_dht_limit) + .def_readwrite("active_tracker_limit", &session_settings::active_tracker_limit) + .def_readwrite("active_lsd_limit", &session_settings::active_lsd_limit) .def_readwrite("active_limit", &session_settings::active_limit) .def_readwrite("auto_manage_prefer_seeds", &session_settings::auto_manage_prefer_seeds) .def_readwrite("dont_count_slow_torrents", &session_settings::dont_count_slow_torrents) @@ -123,6 +126,7 @@ void bind_session_settings() .def_readwrite("incoming_starts_queued_torrents", &session_settings::incoming_starts_queued_torrents) .def_readwrite("report_true_downoaded", &session_settings::report_true_downloaded) .def_readwrite("strict_end_game_mode", &session_settings::strict_end_game_mode) + .def_readwrite("broadcast_lsd", &session_settings::broadcast_lsd) ; enum_("proxy_type") diff --git a/docs/manual.rst b/docs/manual.rst index 6bbf36ede..1d8e1e89e 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3792,6 +3792,8 @@ session_settings int active_downloads; int active_seeds; + int active_dht_limit; + int active_tracker_limit; int active_limit; bool auto_manage_prefer_seeds; bool dont_count_slow_torrents; @@ -4205,6 +4207,21 @@ that don't transfer anything block the active slots. ``active_limit`` is a hard limit on the number of active torrents. This applies even to slow torrents. +``active_dht_limit`` is the max number of torrents to announce to the DHT. By default +this is set to 88, which is no more than one DHT announce every 10 seconds. + +``active_tracker_limit`` is the max number of torrents to announce to their trackers. +By default this is 360, which is no more than one announce every 5 seconds. + +``active_lsd_limit`` is the max number of torrents to announce to the local network +over the local service discovery protocol. By default this is 80, which is no more +than one announce every 5 seconds (assuming the default announce interval of 5 minutes). + +You can have more torrents *active*, even though they are not announced to the DHT, +lsd or their tracker. If some peer knows about you for any reason and tries to connect, +it will still be accepted, unless the torrent is paused, which means it won't accept +any connections. + ``auto_manage_interval`` is the number of seconds between the torrent queue is updated, and rotated. diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 54bf0b028..d228b1841 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -667,8 +667,9 @@ namespace libtorrent void on_disk_queue(); void on_tick(error_code const& e); - int auto_manage_torrents(std::vector& list - , int hard_limit, int type_limit); + void auto_manage_torrents(std::vector& list + , int& dht_limit, int& tracker_limit, int& lsd_limit + , int& hard_limit, int type_limit); void recalculate_auto_managed_torrents(); void recalculate_unchoke_slots(int congested_torrents , int uncongested_torrents); diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 6b0483b33..676dfb4fa 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -145,6 +145,9 @@ namespace libtorrent , peer_tos(0) , active_downloads(8) , active_seeds(5) + , active_dht_limit(88) // don't announce more than once every 40 seconds + , active_tracker_limit(360) // don't announce to trackers more than once every 5 seconds + , active_lsd_limit(60) // don't announce to local network more than once every 5 seconds , active_limit(15) , auto_manage_prefer_seeds(false) , dont_count_slow_torrents(true) @@ -502,8 +505,17 @@ namespace libtorrent // they are subject to. If there are too many torrents // some of the auto managed ones will be paused until // some slots free up. + // active_dht_limit and active_tracker_limit limits the + // number of torrents that will be active on the DHT + // versus the tracker. If the active limit is set higher + // than these numbers, some torrents will be "active" in + // the sense that they will accept incoming connections, + // but not announce on the DHT or the tracker int active_downloads; int active_seeds; + int active_dht_limit; + int active_tracker_limit; + int active_lsd_limit; int active_limit; // prefer seeding torrents when determining which torrents to give diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 0365d2d06..e94d24f67 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -252,13 +252,17 @@ namespace libtorrent void flush_cache(); void pause(); void resume(); + void set_announce_to_dht(bool b) { m_announce_to_dht = b; } + void set_announce_to_trackers(bool b) { m_announce_to_trackers = b; } + void set_announce_to_lsd(bool b) { m_announce_to_lsd = b; } ptime started() const { return m_started; } void do_pause(); void do_resume(); bool is_paused() const; - bool is_torrent_paused() const { return m_paused; } + bool allows_peers() const { return m_allow_peers; } + bool is_torrent_paused() const { return !m_allow_peers; } void force_recheck(); void save_resume_data(); @@ -1147,8 +1151,20 @@ namespace libtorrent // been aborted. bool m_abort:1; - // is true if this torrent has been paused - bool m_paused:1; + // true when the torrent should announce to + // the DHT + bool m_announce_to_dht:1; + + // true when this torrent should anncounce to + // trackers + bool m_announce_to_trackers:1; + + // true when this torrent should anncounce to + // the local network + bool m_announce_to_lsd:1; + + // is true if this torrent has allows having peers + bool m_allow_peers:1; // set to true when this torrent may not download anything bool m_upload_mode:1; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 64c4e8537..750ad6911 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1079,9 +1079,9 @@ namespace libtorrent return; } - if (t->is_paused() && (!t->is_auto_managed() - || !m_ses.m_settings.incoming_starts_queued_torrents - || t->has_error())) + if ((!t->allows_peers() && (!t->is_auto_managed() + || !m_ses.m_settings.incoming_starts_queued_torrents)) + || t->has_error()) { // paused torrents will not accept // incoming connections unless they are auto managed diff --git a/src/session.cpp b/src/session.cpp index 9cb36c7bf..08626dddb 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -202,6 +202,8 @@ namespace libtorrent set.inactivity_timeout = 20; set.active_limit = 2000; + set.active_tracker_limit = 2000; + set.active_dht_limit = 600; set.active_seeds = 2000; set.choking_algorithm = session_settings::fixed_slots_choker; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 9d72513fc..123d67ac6 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -246,6 +246,9 @@ namespace aux { TORRENT_SETTING(character, peer_tos) TORRENT_SETTING(integer, active_downloads) TORRENT_SETTING(integer, active_seeds) + TORRENT_SETTING(integer, active_dht_limit) + TORRENT_SETTING(integer, active_tracker_limit) + TORRENT_SETTING(integer, active_lsd_limit) TORRENT_SETTING(integer, active_limit) TORRENT_SETTING(boolean, auto_manage_prefer_seeds) TORRENT_SETTING(boolean, dont_count_slow_torrents) @@ -1622,7 +1625,7 @@ namespace aux { for (torrent_map::iterator i = m_torrents.begin() , end(m_torrents.end()); i != end; ++i) { - if (!i->second->is_paused()) + if (i->second->allows_peers()) { has_active_torrent = true; break; @@ -2351,8 +2354,9 @@ namespace aux { } } - int session_impl::auto_manage_torrents(std::vector& list - , int hard_limit, int type_limit) + void session_impl::auto_manage_torrents(std::vector& list + , int& dht_limit, int& tracker_limit, int& lsd_limit + , int& hard_limit, int type_limit) { for (std::vector::iterator i = list.begin() , end(list.end()); i != end; ++i) @@ -2369,6 +2373,10 @@ namespace aux { { --hard_limit; --type_limit; + --dht_limit; + --tracker_limit; + t->set_announce_to_dht(dht_limit >= 0); + t->set_announce_to_trackers(tracker_limit >= 0); if (t->is_paused()) t->resume(); } else @@ -2376,7 +2384,6 @@ namespace aux { if (!t->is_paused()) t->pause(); } } - return hard_limit; } void session_impl::recalculate_auto_managed_torrents() @@ -2391,6 +2398,9 @@ namespace aux { // of each kind we're allowed to have active int num_downloaders = settings().active_downloads; int num_seeds = settings().active_seeds; + int dht_limit = settings().active_dht_limit; + int tracker_limit = settings().active_tracker_limit; + int lsd_limit = settings().active_lsd_limit; int hard_limit = settings().active_limit; if (num_downloaders == -1) @@ -2448,13 +2458,17 @@ namespace aux { if (settings().auto_manage_prefer_seeds) { - hard_limit = auto_manage_torrents(seeds, hard_limit, num_seeds); - hard_limit = auto_manage_torrents(downloaders, hard_limit, num_downloaders); + auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit + , hard_limit, num_seeds); + auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit + , hard_limit, num_downloaders); } else { - hard_limit = auto_manage_torrents(downloaders, hard_limit, num_downloaders); - hard_limit = auto_manage_torrents(seeds, hard_limit, num_seeds); + auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit + , hard_limit, num_downloaders); + auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit + , hard_limit, num_seeds); } } diff --git a/src/torrent.cpp b/src/torrent.cpp index 7dd90fbad..42217e8bc 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -280,7 +280,10 @@ namespace libtorrent // PRINT_OFFSETOF(torrent, m_incomplete:24) // PRINT_OFFSETOF(torrent, m_progress_ppm:20) // PRINT_OFFSETOF(torrent, m_abort:1) -// PRINT_OFFSETOF(torrent, m_paused:1) +// PRINT_OFFSETOF(torrent, m_announce_to_dht:1) +// PRINT_OFFSETOF(torrent, m_announce_to_trackers:1) +// PRINT_OFFSETOF(torrent, m_announce_to_lsd:1) +// PRINT_OFFSETOF(torrent, m_allow_peers:1) // PRINT_OFFSETOF(torrent, m_upload_mode:1) // PRINT_OFFSETOF(torrent, m_auto_managed:1) PRINT_OFFSETOF(torrent, m_num_verified) @@ -368,7 +371,10 @@ namespace libtorrent , m_incomplete(0xffffff) , m_progress_ppm(0) , m_abort(false) - , m_paused(p.paused) + , m_announce_to_dht(!p.paused) + , m_announce_to_trackers(!p.paused) + , m_announce_to_lsd(!p.paused) + , m_allow_peers(!p.paused) , m_upload_mode(p.upload_mode) , m_auto_managed(p.auto_managed) , m_num_verified(0) @@ -454,6 +460,7 @@ namespace libtorrent if (!m_ses.m_dht) return false; if (m_torrent_file->is_valid() && !m_files_checked) return false; + if (!m_announce_to_dht) return false; // don't announce private torrents if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; @@ -1295,6 +1302,8 @@ namespace libtorrent // not ready for peers if (!m_files_checked) return; + if (!m_announce_to_lsd) return; + if (m_torrent_file->is_valid() && (m_torrent_file->priv() || (torrent_file().is_i2p() @@ -1311,13 +1320,11 @@ namespace libtorrent void torrent::dht_announce() { - if (m_torrent_file->is_valid() && m_torrent_file->priv()) - return; - - if (is_paused()) return; if (!m_ses.m_dht) return; if (!should_announce_dht()) return; + TORRENT_ASSERT(m_allow_peers); + boost::weak_ptr self(shared_from_this()); m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.listen_port() @@ -1361,6 +1368,12 @@ namespace libtorrent if (m_abort) e = tracker_request::stopped; + // if we're not announcing to trackers, only allow + // stopping + if (e != tracker_request::stopped && !m_announce_to_trackers) return; + + TORRENT_ASSERT(m_allow_peers || e == tracker_request::stopped); + tracker_request req; req.info_hash = m_torrent_file->info_hash(); req.pid = m_ses.get_peer_id(); @@ -3644,7 +3657,19 @@ namespace libtorrent if (!m_override_resume_data) { int paused_ = rd.dict_find_int_value("paused", -1); - if (paused_ != -1) m_paused = paused_; + if (paused_ != -1) + { + m_allow_peers = !paused_; + m_announce_to_dht = !paused_; + m_announce_to_trackers = !paused_; + m_announce_to_lsd = !paused_; + } + int dht_ = rd.dict_find_int_value("announce_to_dht", -1); + if (dht_ != -1) m_announce_to_dht = dht_; + int lsd_ = rd.dict_find_int_value("announce_to_lsd", -1); + if (lsd_ != -1) m_announce_to_lsd = lsd_; + int track_ = rd.dict_find_int_value("announce_to_trackers", -1); + if (track_ != -1) m_announce_to_trackers = track_; } lazy_entry const* trackers = rd.dict_find_list("trackers"); @@ -3968,7 +3993,10 @@ namespace libtorrent ret["download_rate_limit"] = download_limit(); ret["max_connections"] = max_connections(); ret["max_uploads"] = max_uploads(); - ret["paused"] = m_paused; + ret["paused"] = !m_allow_peers; + ret["announce_to_dht"] = m_announce_to_dht; + ret["announce_to_trackers"] = m_announce_to_trackers; + ret["announce_to_lsd"] = m_announce_to_lsd; ret["auto_managed"] = m_auto_managed; // write piece priorities @@ -4369,7 +4397,7 @@ namespace libtorrent void torrent::disconnect_all(error_code const& ec) { -// doesn't work with the m_paused -> m_num_peers == 0 condition +// doesn't work with the !m_allow_peers -> m_num_peers == 0 condition // INVARIANT_CHECK; while (!m_connections.empty()) @@ -5216,9 +5244,10 @@ namespace libtorrent bool torrent::should_check_files() const { + // #error should m_allow_peers really affect checking? return (m_state == torrent_status::checking_files || m_state == torrent_status::queued_for_checking) - && (!m_paused || m_auto_managed) + && (!m_allow_peers || m_auto_managed) && !has_error() && !m_abort; } @@ -5237,16 +5266,19 @@ namespace libtorrent bool torrent::is_paused() const { - return m_paused || m_ses.is_paused(); + return !m_allow_peers || m_ses.is_paused(); } void torrent::pause() { INVARIANT_CHECK; - if (m_paused) return; + if (!m_allow_peers) return; bool checking_files = should_check_files(); - m_paused = true; + m_allow_peers = false; + m_announce_to_dht = false; + m_announce_to_trackers = false; + m_announce_to_lsd = false; if (!m_ses.is_paused()) do_pause(); if (checking_files && !should_check_files()) @@ -5307,9 +5339,18 @@ namespace libtorrent { INVARIANT_CHECK; - if (!m_paused) return; + if (m_allow_peers + && m_announce_to_dht + && m_announce_to_trackers + && m_announce_to_lsd) return; bool checking_files = should_check_files(); - m_paused = false; + m_allow_peers = true; + if (!m_auto_managed) + { + m_announce_to_dht = true; + m_announce_to_trackers = true; + m_announce_to_lsd = true; + } do_resume(); if (!checking_files && should_check_files()) queue_torrent_check(); @@ -6169,7 +6210,7 @@ namespace libtorrent st.num_complete = (m_complete == 0xffffff) ? -1 : m_complete; st.num_incomplete = (m_incomplete == 0xffffff) ? -1 : m_incomplete; - st.paused = m_paused; + st.paused = !m_allow_peers; bytes_done(st, flags & torrent_handle::query_accurate_download_counters); TORRENT_ASSERT(st.total_wanted_done >= 0); TORRENT_ASSERT(st.total_done >= st.total_wanted_done);