fixed bug with inactivity timer

This commit is contained in:
Arvid Norberg 2014-10-05 22:30:09 +00:00
parent 9b137ba3b5
commit 30d7b9e3c3
6 changed files with 229 additions and 274 deletions

File diff suppressed because one or more lines are too long

View File

@ -672,6 +672,7 @@ namespace libtorrent
void update_natpmp();
void update_lsd();
void update_dht();
void update_count_slow();
void on_trigger_auto_manage();

View File

@ -838,6 +838,14 @@ namespace libtorrent
, std::vector<address> const& addrs
, std::list<web_seed_entry>::iterator web, int port);
// re-evaluates whether this torrent should be considered inactive or not
void on_inactivity_tick(error_code const& ec);
// calculate the instantaneuos inactive state (the externally facing
// inactive state is not instantaneous, but low-pass filtered)
bool is_inactive_internal() const;
// remove a web seed, or schedule it for removal in case there
// are outstanding operations on it
void remove_web_seed(std::list<web_seed_entry>::iterator web);
@ -1188,6 +1196,10 @@ namespace libtorrent
// used for tracker announces
deadline_timer m_tracker_timer;
// used to detect when we are active or inactive for long enough
// to trigger the auto-manage logic
deadline_timer m_inactivity_timer;
// this is the upload and download statistics for the whole torrent.
// it's updated from all its peers once every second.
libtorrent::stat m_stat;
@ -1634,12 +1646,10 @@ namespace libtorrent
// millionths of completeness)
unsigned int m_progress_ppm:20;
// the number of seconds this torrent has been under the inactive
// threshold in terms of sending and receiving data. When this counter
// reaches the settings.inactive_torrent_timeout it will be considered
// inactive and possibly open up another queue slot, to start another,
// queued, torrent. Every second it's above the threshold
boost::int16_t m_inactive_counter;
// this is a timestamp of the last time this torrent changed its
// m_inactive state. The inactive state is set when transfer rates are
// below the active threshold. It's specified in session time unit.
boost::int16_t m_last_active_change;
// if this is set, accept the save path saved in the resume data, if
// present

View File

@ -6147,6 +6147,16 @@ retry:
#endif
}
void session_impl::update_count_slow()
{
error_code ec;
for (torrent_map::const_iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i)
{
i->second->on_inactivity_tick(ec);
}
}
address session_impl::listen_address() const
{
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()

View File

@ -146,7 +146,7 @@ namespace libtorrent
SET(coalesce_reads, false, 0),
SET(coalesce_writes, false, 0),
SET(auto_manage_prefer_seeds, false, 0),
SET(dont_count_slow_torrents, true, 0),
SET(dont_count_slow_torrents, true, &session_impl::update_count_slow),
SET(close_redundant_connections, true, 0),
SET(prioritize_partial_pieces, false, 0),
SET(rate_limit_ip_overhead, true, 0),

View File

@ -152,6 +152,7 @@ namespace libtorrent
, m_total_uploaded(0)
, m_total_downloaded(0)
, m_tracker_timer(ses.get_io_service())
, m_inactivity_timer(ses.get_io_service())
, m_trackerid(p.trackerid)
, m_save_path(complete(p.save_path))
, m_url(p.url)
@ -233,7 +234,6 @@ namespace libtorrent
, m_downloaded(0xffffff)
, m_last_scrape(0)
, m_progress_ppm(0)
, m_inactive_counter(0)
, m_use_resume_save_path(p.flags & add_torrent_params::flag_use_resume_save_path)
{
if (m_pinned)
@ -4659,9 +4659,10 @@ namespace libtorrent
// if the torrent is paused, it doesn't need
// to announce with even=stopped again.
if (!is_paused())
{
stop_announcing();
}
error_code ec;
m_inactivity_timer.cancel(ec);
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING || defined TORRENT_LOGGING
log_to_all_peers("ABORTING TORRENT");
@ -7765,7 +7766,8 @@ namespace libtorrent
void torrent::update_want_scrape()
{
update_list(aux::session_interface::torrent_want_scrape, !m_allow_peers && m_auto_managed && !m_abort);
update_list(aux::session_interface::torrent_want_scrape
, !m_allow_peers && m_auto_managed && !m_abort);
}
void torrent::update_list(int list, bool in)
@ -7782,7 +7784,6 @@ namespace libtorrent
if (!l.in_list()) return;
l.unlink(v, list);
}
}
void torrent::disconnect_all(error_code const& ec, peer_connection_interface::operation_t op)
@ -9624,61 +9625,48 @@ namespace libtorrent
if (m_stat.low_pass_upload_rate() > 0 || m_stat.low_pass_download_rate() > 0)
state_updated();
// TODO: 4 this logic doesn't work for seeding torrents that are not ticked
// once a torrent is inactive, it may not be ticked anymore, which may
// prevent it from ever have m_inactive be set, because there's a delay
// deom becoming inactive and trigger auto-manage.
// this section determines whether the torrent is active or not. When it
// changes state, it may also trigger the auto-manage logic to reconsider
// which torrents should be queued and started. There is a low pass
// filter in order to avoid flapping (auto_manage_startup).
bool is_inactive = false;
if (is_finished())
is_inactive = m_stat.upload_payload_rate() < m_ses.settings().get_int(settings_pack::inactive_up_rate);
else
is_inactive = m_stat.download_payload_rate() < m_ses.settings().get_int(settings_pack::inactive_down_rate);
bool is_inactive = is_inactive_internal();
if (is_inactive)
if (is_inactive != m_inactive
&& m_ses.settings().get_bool(settings_pack::dont_count_slow_torrents))
{
if (m_inactive_counter < 0) m_inactive_counter = 0;
if (m_inactive_counter < INT16_MAX)
{
++m_inactive_counter;
// if this torrent was just considered inactive, we may want
// to dequeue some other torrent
if (m_inactive == false
&& m_inactive_counter >= m_ses.settings().get_int(settings_pack::auto_manage_startup))
{
m_inactive = true;
if (m_ses.settings().get_bool(settings_pack::dont_count_slow_torrents))
m_ses.trigger_auto_manage();
}
}
}
else
{
if (m_inactive_counter > 0) m_inactive_counter = 0;
if (m_inactive_counter > INT16_MIN)
{
--m_inactive_counter;
// if this torrent was just considered active, we may want
// to queue some other torrent
if (m_inactive == true
&& m_inactive_counter <= -m_ses.settings().get_int(settings_pack::auto_manage_startup))
{
m_inactive = false;
if (m_ses.settings().get_bool(settings_pack::dont_count_slow_torrents))
m_ses.trigger_auto_manage();
}
}
m_last_active_change = m_ses.session_time();
int delay = m_ses.settings().get_int(settings_pack::auto_manage_startup);
m_inactivity_timer.expires_from_now(seconds(delay));
m_inactivity_timer.async_wait(boost::bind(&torrent::on_inactivity_tick
, shared_from_this(), _1));
}
update_want_tick();
}
bool torrent::is_inactive_internal() const
{
if (is_finished())
return m_stat.upload_payload_rate()
< m_ses.settings().get_int(settings_pack::inactive_up_rate);
else
return m_stat.download_payload_rate()
< m_ses.settings().get_int(settings_pack::inactive_down_rate);
}
void torrent::on_inactivity_tick(error_code const& ec)
{
if (ec) return;
int now = m_ses.session_time();
int delay = m_ses.settings().get_int(settings_pack::auto_manage_startup);
if (now - m_last_active_change < delay) return;
m_inactive = is_inactive_internal();
if (m_ses.settings().get_bool(settings_pack::dont_count_slow_torrents))
m_ses.trigger_auto_manage();
}
void torrent::maybe_connect_web_seeds()
{
if (m_abort) return;