keep counters of the number of active downloading and finished torrents in order to have a cheap way of prioritizing peer connections for downloading torrents over finished ones

This commit is contained in:
Arvid Norberg 2012-06-21 03:51:39 +00:00
parent 342a0b9306
commit 3c0e7e0a4a
4 changed files with 89 additions and 10 deletions

View File

@ -515,6 +515,19 @@ namespace libtorrent
--m_disk_queues[channel];
}
void inc_active_downloading() { ++m_num_active_downloading; }
void dec_active_downloading()
{
TORRENT_ASSERT(m_num_active_downloading > 0);
--m_num_active_downloading;
}
void inc_active_finished() { ++m_num_active_finished; }
void dec_active_finished()
{
TORRENT_ASSERT(m_num_active_finished > 0);
--m_num_active_finished;
}
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool in_state_updates(boost::shared_ptr<torrent> t)
{
@ -681,6 +694,13 @@ namespace libtorrent
torrent_map m_torrents;
std::map<std::string, boost::shared_ptr<torrent> > m_uuids;
// counters of how many of the active (non-paused) torrents
// are finished and downloading. This is used to weigh the
// priority of downloading and finished torrents when connecting
// more peers.
int m_num_active_downloading;
int m_num_active_finished;
typedef std::list<boost::shared_ptr<torrent> > check_queue_t;
// this has all torrents that wants to be checked in it

View File

@ -260,6 +260,20 @@ namespace libtorrent
void force_recheck();
void save_resume_data(int flags);
bool is_active_download() const
{
return (m_state == torrent_status::downloading
|| m_state == torrent_status::downloading_metadata)
&& m_allow_peers;
}
bool is_active_finished() const
{
return (m_state == torrent_status::finished
|| m_state == torrent_status::seeding)
&& m_allow_peers;
}
bool need_save_resume_data() const
{
// save resume data every 15 minutes regardless, just to

View File

@ -610,6 +610,8 @@ namespace aux {
, m_upload_rate(peer_connection::upload_channel)
#endif
, m_tracker_manager(*this, m_proxy)
, m_num_active_downloading(0)
, m_num_active_finished(0)
, m_listen_port_retries(listen_port_range.second - listen_port_range.first)
#if TORRENT_USE_I2P
, m_i2p_conn(m_io_service)
@ -3430,16 +3432,17 @@ namespace aux {
torrent& t = *m_next_connect_torrent->second;
if (t.want_more_peers())
{
TORRENT_ASSERT(t.allows_peers());
// have a bias to give more connection attempts
// to downloading torrents than seed, and even
// more to downloading torrents with less than
// average number of connections
int num_attempts = 1;
if (!t.is_seed())
if (!t.is_finished())
{
++num_attempts;
if (t.num_peers() < average_peers)
++num_attempts;
// TODO: make this bias configurable
TORRENT_ASSERT(m_num_active_downloading > 0);
num_attempts += m_num_active_finished / m_num_active_downloading;
}
for (int i = 0; i < num_attempts; ++i)
{
@ -4209,6 +4212,8 @@ namespace aux {
void session_impl::recalculate_auto_managed_torrents()
{
INVARIANT_CHECK;
// these vectors are filled with auto managed torrents
std::vector<torrent*> downloaders;
downloaders.reserve(m_torrents.size());
@ -4301,7 +4306,6 @@ namespace aux {
auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit
, hard_limit, num_seeds);
}
}
void session_impl::recalculate_optimistic_unchoke_slots()
@ -4996,6 +5000,8 @@ namespace aux {
void session_impl::remove_torrent(const torrent_handle& h, int options)
{
INVARIANT_CHECK;
boost::shared_ptr<torrent> tptr = h.m_torrent.lock();
if (!tptr) return;
@ -5037,6 +5043,13 @@ namespace aux {
if (options & session::delete_files)
t.delete_files();
bool is_active_download = tptr->is_active_download();
bool is_active_finished = tptr->is_active_finished();
// update finished and downloading counters
if (is_active_download) dec_active_downloading();
if (is_active_finished) dec_active_finished();
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
sha1_hash i_hash = t.torrent_file().info_hash();
#endif
@ -6064,20 +6077,29 @@ namespace aux {
// TORRENT_ASSERT(m_queued_for_checking.size() == num_queued_for_checking);
std::set<int> unique;
int num_active_downloading = 0;
int num_active_finished = 0;
int total_downloaders = 0;
for (torrent_map::const_iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i)
{
int pos = i->second->queue_position();
boost::shared_ptr<torrent> t = i->second;
if (t->is_active_download()) ++num_active_downloading;
else if (t->is_active_finished()) ++num_active_finished;
int pos = t->queue_position();
if (pos < 0)
{
TORRENT_ASSERT(pos == -1);
continue;
}
++total_downloaders;
unique.insert(i->second->queue_position());
unique.insert(t->queue_position());
}
TORRENT_ASSERT(int(unique.size()) == total_downloaders);
TORRENT_ASSERT(num_active_downloading == m_num_active_downloading);
TORRENT_ASSERT(num_active_finished == m_num_active_finished);
std::set<peer_connection*> unique_peers;
TORRENT_ASSERT(m_settings.connections_limit > 0);

View File

@ -441,6 +441,10 @@ namespace libtorrent
if (!m_apply_ip_filter) ++m_ses.m_non_filtered_torrents;
// update finished and downloading counters
if (is_active_download()) m_ses.inc_active_downloading();
if (is_active_finished()) m_ses.inc_active_finished();
if (!p.ti || !p.ti->is_valid())
{
// we don't have metadata for this torrent. We'll download
@ -5059,7 +5063,7 @@ namespace libtorrent
int paused_ = rd.dict_find_int_value("paused", -1);
if (paused_ != -1)
{
m_allow_peers = !paused_;
set_allow_peers(!paused_);
m_announce_to_dht = !paused_;
m_announce_to_trackers = !paused_;
m_announce_to_lsd = !paused_;
@ -7002,7 +7006,7 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_allow_peers) return;
if (!graceful) m_allow_peers = false;
if (!graceful) set_allow_peers(false);
m_announce_to_dht = false;
m_announce_to_trackers = false;
m_announce_to_lsd = false;
@ -7134,10 +7138,19 @@ namespace libtorrent
if (m_allow_peers == b
&& m_graceful_pause_mode == graceful) return;
bool was_active_download = is_active_download();
bool was_active_finished = is_active_finished();
m_allow_peers = b;
if (!m_ses.is_paused())
m_graceful_pause_mode = graceful;
// update finished and downloading counters
if (was_active_download && !is_active_download()) m_ses.dec_active_downloading();
else if (!was_active_download && is_active_download()) m_ses.inc_active_downloading();
if (was_active_finished && !is_active_finished()) m_ses.dec_active_finished();
else if (!was_active_finished && is_active_finished()) m_ses.inc_active_finished();
if (!b)
{
m_announce_to_dht = false;
@ -7160,7 +7173,7 @@ namespace libtorrent
&& m_announce_to_dht
&& m_announce_to_trackers
&& m_announce_to_lsd) return;
m_allow_peers = true;
set_allow_peers(true);
m_announce_to_dht = true;
m_announce_to_trackers = true;
m_announce_to_lsd = true;
@ -8244,8 +8257,18 @@ namespace libtorrent
if (int(m_state) == s) return;
if (m_ses.m_alerts.should_post<state_changed_alert>())
m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s, (torrent_status::state_t)m_state));
bool was_active_download = is_active_download();
bool was_active_finished = is_active_finished();
m_state = s;
// update finished and downloading counters
if (was_active_download && !is_active_download()) m_ses.dec_active_downloading();
else if (!was_active_download && is_active_download()) m_ses.inc_active_downloading();
if (was_active_finished && !is_active_finished()) m_ses.dec_active_finished();
else if (!was_active_finished && is_active_finished()) m_ses.inc_active_finished();
state_updated();
#ifndef TORRENT_DISABLE_EXTENSIONS