diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 02babcfc8..c37982e5d 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -219,6 +219,7 @@ namespace libtorrent #endif ); virtual ~session_impl(); + void update_dht_announce_interval(); void init(); void start_session(); @@ -884,6 +885,14 @@ namespace libtorrent // this announce timer is used // by the DHT. deadline_timer m_dht_announce_timer; + + // the number of torrents there were when the + // update_dht_announce_interval() was last called. + // if the number of torrents changes significantly + // compared to this number, the DHT announce interval + // is updated again. This especially matters for + // small numbers. + int m_dht_interval_update_torrents; #endif bool incoming_packet(error_code const& ec @@ -937,6 +946,14 @@ namespace libtorrent // within the DHT announce interval (which defaults to // 15 minutes) torrent_map::iterator m_next_dht_torrent; + + // torrents that don't have any peers + // when added should be announced to the DHT + // as soon as possible. Such torrents are put + // in this queue and get announced the next time + // the timer fires, instead of the next one in + // the round-robin sequence. + std::deque > m_dht_torrents; #endif // this announce timer is used diff --git a/src/session_impl.cpp b/src/session_impl.cpp index ee3d04226..ffba48dbe 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -641,6 +641,7 @@ namespace aux { , m_next_rss_update(min_time()) #ifndef TORRENT_DISABLE_DHT , m_dht_announce_timer(m_io_service) + , m_dht_interval_update_torrents(0) #endif , m_external_udp_port(0) , m_udp_socket(m_io_service, m_half_open) @@ -1295,6 +1296,24 @@ namespace aux { m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this))); } + void session_impl::update_dht_announce_interval() + { +#ifndef TORRENT_DISABLE_DHT + +#if defined TORRENT_ASIO_DEBUGGING + add_outstanding_async("session_impl::on_dht_announce"); +#endif + m_dht_interval_update_torrents = m_torrents.size(); + error_code ec; + int delay = (std::max)(m_settings.dht_announce_interval + / (std::max)(int(m_torrents.size()), 1), 1); + m_dht_announce_timer.expires_from_now(seconds(delay), ec); + m_dht_announce_timer.async_wait( + boost::bind(&session_impl::on_dht_announce, this, _1)); + TORRENT_ASSERT(!ec); +#endif + } + void session_impl::init() { #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING @@ -1323,16 +1342,7 @@ namespace aux { TORRENT_ASSERT(!ec); #ifndef TORRENT_DISABLE_DHT - -#if defined TORRENT_ASIO_DEBUGGING - add_outstanding_async("session_impl::on_dht_announce"); -#endif - delay = (std::max)(m_settings.dht_announce_interval - / (std::max)(int(m_torrents.size()), 1), 1); - m_dht_announce_timer.expires_from_now(seconds(delay), ec); - m_dht_announce_timer.async_wait( - boost::bind(&session_impl::on_dht_announce, this, _1)); - TORRENT_ASSERT(!ec); + update_dht_announce_interval(); #endif #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING @@ -3010,6 +3020,12 @@ namespace aux { // only tick the following once per second if (now - m_last_second_tick < seconds(1)) return; +#ifndef TORRENT_DISABLE_DHT + if (m_dht_interval_update_torrents < 40 + && m_dht_interval_update_torrents != m_torrents.size()) + update_dht_announce_interval(); +#endif + int tick_interval_ms = total_milliseconds(now - m_last_second_tick); m_last_second_tick = now; m_tick_residual += tick_interval_ms - 1000; @@ -3950,11 +3966,27 @@ namespace aux { m_dht_announce_timer.async_wait( bind(&session_impl::on_dht_announce, this, _1)); + if (!m_dht_torrents.empty()) + { + boost::shared_ptr t; + do + { + t = m_dht_torrents.front().lock(); + m_dht_torrents.pop_front(); + } + while (!t && !m_dht_torrents.empty()); + if (t) + { + t->dht_announce(); + return; + } + } if (m_torrents.empty()) return; if (m_next_dht_torrent == m_torrents.end()) m_next_dht_torrent = m_torrents.begin(); m_next_dht_torrent->second->dht_announce(); + // TODO: make a list for torrents that want to be announced on the DHT ++m_next_dht_torrent; if (m_next_dht_torrent == m_torrents.end()) m_next_dht_torrent = m_torrents.begin(); @@ -5365,13 +5397,6 @@ namespace aux { m_dht->start(startup_state); m_udp_socket.subscribe(m_dht.get()); - - // announce all torrents we have to the DHT - for (torrent_map::const_iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - i->second->dht_announce(); - } } void session_impl::stop_dht() diff --git a/src/torrent.cpp b/src/torrent.cpp index fb265d6c0..2a03fcd84 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -7325,6 +7325,15 @@ namespace libtorrent m_announcing = true; +#ifndef TORRENT_DISABLE_DHT + if (m_policy.num_peers() == 0 && m_ses.m_dht) + { + // we don't have any peers, prioritize + // announcing this torrent with the DHT + m_ses.m_dht_torrents.push_back(shared_from_this()); + } +#endif + if (!m_trackers.empty()) { // tell the tracker that we're back @@ -7348,10 +7357,6 @@ namespace libtorrent || settings().allow_i2p_mixed))) { if (m_ses.m_lsd) lsd_announce(); - -#ifndef TORRENT_DISABLE_DHT - if (m_ses.m_dht) dht_announce(); -#endif } }