From 9a985d197f6dad0e5f7b08b37e69c9fea5ecfaad Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 24 Sep 2014 09:03:57 +0000 Subject: [PATCH] optimize num_seeds() and num_downloaders() to not count the peers every time --- include/libtorrent/torrent.hpp | 14 +++---- src/peer_connection.cpp | 1 - src/policy.cpp | 27 +++++++++++--- src/torrent.cpp | 67 +++++++++++++++++++++++++--------- 4 files changed, 78 insertions(+), 31 deletions(-) diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index c08761e57..07bb67f2f 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -1577,7 +1577,13 @@ namespace libtorrent // specified in session_time boost::uint16_t m_last_download; - // TODO: There are 8 bits free here + // the number of peer connections to seeds. This should be the same as + // counting the peer connections that say true for is_seed() + boost::uint16_t m_num_seeds; + + // the timestamp of the last byte uploaded from this torrent + // specified in session_time + boost::uint16_t m_last_upload; // this is a second count-down to when we should tick the // storage for this torrent. Ticking the storage is used @@ -1589,12 +1595,6 @@ namespace libtorrent // ---- - // the timestamp of the last byte uploaded from this torrent - // specified in session_time - boost::uint16_t m_last_upload; - - // TODO: There are 8 bits here - // if this is true, libtorrent may pause and resume // this torrent depending on queuing rules. Torrents // started with auto_managed flag set may be added in diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 8046e6062..c4892d400 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -2184,7 +2184,6 @@ namespace libtorrent peer_log("*** THIS IS A SEED [ p: %p ]", m_peer_info); #endif - // if this is a web seed. we don't have a peer_info struct t->set_seed(m_peer_info, true); m_upload_only = true; diff --git a/src/policy.cpp b/src/policy.cpp index 8eb91dd5f..798d3bb82 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -270,7 +270,11 @@ namespace libtorrent TORRENT_ASSERT(m_locked_peer != *i); state->erased.push_back(*i); - if ((*i)->seed) --m_num_seeds; + if ((*i)->seed) + { + TORRENT_ASSERT(m_num_seeds > 0); + --m_num_seeds; + } if (is_connect_candidate(**i)) update_connect_candidates(-1); TORRENT_ASSERT(m_num_connect_candidates < int(m_peers.size())); @@ -861,10 +865,16 @@ namespace libtorrent update_connect_candidates(-1); if (p->web_seed) return; - if (s) ++m_num_seeds; - else --m_num_seeds; - TORRENT_ASSERT(m_num_seeds >= 0); - TORRENT_ASSERT(m_num_seeds <= int(m_peers.size())); + if (s) + { + TORRENT_ASSERT(m_num_seeds < int(m_peers.size())); + ++m_num_seeds; + } + else + { + TORRENT_ASSERT(m_num_seeds > 0); + --m_num_seeds; + } } // this is an internal function @@ -911,6 +921,7 @@ namespace libtorrent if (flags & flag_seed) { p->seed = true; + TORRENT_ASSERT(m_num_seeds < int(m_peers.size())); ++m_num_seeds; } if (flags & flag_utp) @@ -948,7 +959,11 @@ namespace libtorrent // so we don't have to trust this source if ((flags & flag_seed) && !p->connection) { - if (!p->seed) ++m_num_seeds; + if (!p->seed) + { + TORRENT_ASSERT(m_num_seeds < int(m_peers.size())); + ++m_num_seeds; + } p->seed = true; } if (flags & flag_utp) diff --git a/src/torrent.cpp b/src/torrent.cpp index 88cf45f0a..5e2c08792 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -224,8 +224,9 @@ namespace libtorrent , m_pinned(p.flags & add_torrent_params::flag_pinned) , m_should_be_loaded(true) , m_last_download(0) - , m_storage_tick(0) + , m_num_seeds(0) , m_last_upload(0) + , m_storage_tick(0) , m_auto_managed(p.flags & add_torrent_params::flag_auto_managed) , m_current_gauge_state(no_gauge_state) , m_moving_storage(false) @@ -5764,8 +5765,6 @@ namespace libtorrent void torrent::remove_peer(peer_connection* p) { - INVARIANT_CHECK; - TORRENT_ASSERT(p != 0); TORRENT_ASSERT(is_single_thread()); @@ -5820,6 +5819,12 @@ namespace libtorrent TORRENT_ASSERT(pp->prev_amount_download == 0); pp->prev_amount_download += p->statistics().total_payload_download() >> 10; pp->prev_amount_upload += p->statistics().total_payload_upload() >> 10; + + if (pp->seed) + { + TORRENT_ASSERT(m_num_seeds > 0); + --m_num_seeds; + } } torrent_state st = get_policy_state(); @@ -6140,6 +6145,8 @@ namespace libtorrent void torrent::connect_web_seed(std::list::iterator web, tcp::endpoint a) { + INVARIANT_CHECK; + TORRENT_ASSERT(is_single_thread()); if (m_abort) return; @@ -6275,6 +6282,12 @@ namespace libtorrent update_want_tick(); m_ses.insert_peer(c); + if (web->peer_info.seed) + { + TORRENT_ASSERT(m_num_seeds < 0xffff); + ++m_num_seeds; + } + TORRENT_ASSERT(!web->peer_info.connection); web->peer_info.connection = c.get(); #if TORRENT_USE_ASSERTS @@ -7287,6 +7300,11 @@ namespace libtorrent m_ses.insert_peer(c); need_policy(); m_policy->set_connection(peerinfo, c.get()); + if (peerinfo->seed) + { + TORRENT_ASSERT(m_num_seeds < 0xffff); + ++m_num_seeds; + } update_want_peers(); update_want_tick(); c->start(); @@ -7617,6 +7635,12 @@ namespace libtorrent update_want_peers(); update_want_tick(); + if (p->peer_info_struct() && p->peer_info_struct()->seed) + { + TORRENT_ASSERT(m_num_seeds < 0xffff); + ++m_num_seeds; + } + #if defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING debug_log("incoming peer (%d)", int(m_connections.size())); #endif @@ -8326,6 +8350,7 @@ namespace libtorrent TORRENT_ASSERT(!m_resume_data || m_resume_data->entry.type() == lazy_entry::dict_t || m_resume_data->entry.type() == lazy_entry::none_t); + int seeds = 0; int num_uploads = 0; std::map num_requests; for (const_peer_iterator i = this->begin(); i != this->end(); ++i) @@ -8335,6 +8360,10 @@ namespace libtorrent TORRENT_ASSERT(m_ses.has_peer(*i)); #endif peer_connection const& p = *(*i); + + if (p.peer_info_struct() && p.peer_info_struct()->seed) + ++seeds; + for (std::vector::const_iterator i = p.request_queue().begin() , end(p.request_queue().end()); i != end; ++i) if (!i->not_wanted && !i->timed_out) ++num_requests[i->block]; @@ -8347,6 +8376,7 @@ namespace libtorrent TORRENT_ASSERT(false); } TORRENT_ASSERT(num_uploads == int(m_num_uploads)); + TORRENT_ASSERT(seeds == int(m_num_seeds)); if (has_picker()) { @@ -10682,6 +10712,20 @@ namespace libtorrent void torrent::set_seed(torrent_peer* p, bool s) { + if (p->seed != s) + { + if (s) + { + TORRENT_ASSERT(m_num_seeds < 0xffff); + ++m_num_seeds; + } + else + { + TORRENT_ASSERT(m_num_seeds > 0); + --m_num_seeds; + } + } + need_policy(); m_policy->set_seed(p, s); update_auto_sequential(); @@ -11350,32 +11394,21 @@ namespace libtorrent m_stats_counters.inc_stats_counter(counters::recv_failed_bytes, b); } - // TODO: 3 make this a gauge that's kept up to date rather than counting - // every time int torrent::num_seeds() const { TORRENT_ASSERT(is_single_thread()); INVARIANT_CHECK; - int ret = 0; - for (const_peer_iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - if ((*i)->is_seed()) ++ret; - return ret; + return m_num_seeds; } - // TODO: 3 make this a gauge that's kept up to date rather than counting - // every time int torrent::num_downloaders() const { TORRENT_ASSERT(is_single_thread()); INVARIANT_CHECK; - int ret = 0; - for (const_peer_iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - if ((*i)->is_connected() && !(*i)->is_seed()) ++ret; - return ret; + TORRENT_ASSERT(m_connections.size() >= m_num_seeds); + return m_connections.size() - m_num_seeds; } void torrent::tracker_request_error(tracker_request const& r