merged some rate limiter polish from libtorrent_aio

This commit is contained in:
Arvid Norberg 2013-11-02 03:26:53 +00:00
parent dde078cdf7
commit 90e7a4c9e3
8 changed files with 54 additions and 14 deletions

View File

@ -90,6 +90,8 @@ struct TORRENT_EXTRA_EXPORT bandwidth_manager
void update_quotas(time_duration const& dt); void update_quotas(time_duration const& dt);
private:
// these are the consumers that want bandwidth // these are the consumers that want bandwidth
typedef std::vector<bw_request> queue_t; typedef std::vector<bw_request> queue_t;
queue_t m_queue; queue_t m_queue;

View File

@ -62,7 +62,9 @@ struct TORRENT_EXTRA_EXPORT bw_request
// from the most limiting one // from the most limiting one
int assign_bandwidth(); int assign_bandwidth();
bandwidth_channel* channel[5]; enum { max_bandwidth_channels = 5 };
// we don't actually support more than 5 channels per peer
bandwidth_channel* channel[max_bandwidth_channels];
}; };
} }

View File

@ -486,7 +486,7 @@ namespace libtorrent
void start_receive_piece(peer_request const& r); void start_receive_piece(peer_request const& r);
void incoming_cancel(peer_request const& r); void incoming_cancel(peer_request const& r);
bool can_disconnect(error_code const& ec); bool can_disconnect(error_code const& ec) const;
void incoming_dht_port(int listen_port); void incoming_dht_port(int listen_port);
void incoming_reject_request(peer_request const& r); void incoming_reject_request(peer_request const& r);

View File

@ -147,6 +147,8 @@ namespace libtorrent
std::vector<bandwidth_channel*> channels; std::vector<bandwidth_channel*> channels;
queue_t tm;
for (queue_t::iterator i = m_queue.begin(); for (queue_t::iterator i = m_queue.begin();
i != m_queue.end();) i != m_queue.end();)
{ {
@ -156,16 +158,18 @@ namespace libtorrent
// return all assigned quota to all the // return all assigned quota to all the
// bandwidth channels this peer belongs to // bandwidth channels this peer belongs to
for (int j = 0; j < 5 && i->channel[j]; ++j) for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
{ {
bandwidth_channel* bwc = i->channel[j]; bandwidth_channel* bwc = i->channel[j];
bwc->return_quota(i->assigned); bwc->return_quota(i->assigned);
} }
i->assigned = 0;
tm.push_back(*i);
i = m_queue.erase(i); i = m_queue.erase(i);
continue; continue;
} }
for (int j = 0; j < 5 && i->channel[j]; ++j) for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
{ {
bandwidth_channel* bwc = i->channel[j]; bandwidth_channel* bwc = i->channel[j];
bwc->tmp = 0; bwc->tmp = 0;
@ -176,7 +180,7 @@ namespace libtorrent
for (queue_t::iterator i = m_queue.begin() for (queue_t::iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i) , end(m_queue.end()); i != end; ++i)
{ {
for (int j = 0; j < 5 && i->channel[j]; ++j) for (int j = 0; j < bw_request::max_bandwidth_channels && i->channel[j]; ++j)
{ {
bandwidth_channel* bwc = i->channel[j]; bandwidth_channel* bwc = i->channel[j];
if (bwc->tmp == 0) channels.push_back(bwc); if (bwc->tmp == 0) channels.push_back(bwc);
@ -191,8 +195,6 @@ namespace libtorrent
(*i)->update_quota(dt_milliseconds); (*i)->update_quota(dt_milliseconds);
} }
queue_t tm;
for (queue_t::iterator i = m_queue.begin(); for (queue_t::iterator i = m_queue.begin();
i != m_queue.end();) i != m_queue.end();)
{ {

View File

@ -893,6 +893,9 @@ namespace libtorrent
} }
} }
disconnect_if_redundant();
if (is_disconnecting()) return;
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
peer_log("==> HAVE [ piece: %d ]", index); peer_log("==> HAVE [ piece: %d ]", index);
#endif #endif
@ -1896,10 +1899,10 @@ namespace libtorrent
} }
} }
bool peer_connection::can_disconnect(error_code const& ec) bool peer_connection::can_disconnect(error_code const& ec) const
{ {
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin() for (extension_list_t::const_iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i) , end(m_extensions.end()); i != end; ++i)
{ {
if (!(*i)->can_disconnect(ec)) return false; if (!(*i)->can_disconnect(ec)) return false;
@ -4637,10 +4640,16 @@ namespace libtorrent
, channel == upload_channel ? ">>>" : "<<<", amount); , channel == upload_channel ? ">>>" : "<<<", amount);
#endif #endif
TORRENT_ASSERT(amount > 0); TORRENT_ASSERT(amount > 0 || is_disconnecting());
m_quota[channel] += amount; m_quota[channel] += amount;
TORRENT_ASSERT(m_channel_state[channel] & peer_info::bw_limit); TORRENT_ASSERT(m_channel_state[channel] & peer_info::bw_limit);
m_channel_state[channel] &= ~peer_info::bw_limit; m_channel_state[channel] &= ~peer_info::bw_limit;
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
check_invariant();
#endif
if (is_disconnecting()) return;
if (channel == upload_channel) if (channel == upload_channel)
{ {
setup_send(); setup_send();
@ -4740,6 +4749,7 @@ namespace libtorrent
, bandwidth_channel* bwc3 , bandwidth_channel* bwc3
, bandwidth_channel* bwc4) , bandwidth_channel* bwc4)
{ {
INVARIANT_CHECK;
// we can only have one outstanding bandwidth request at a time // we can only have one outstanding bandwidth request at a time
if (m_channel_state[download_channel] & peer_info::bw_limit) return 0; if (m_channel_state[download_channel] & peer_info::bw_limit) return 0;
@ -5734,6 +5744,14 @@ namespace libtorrent
TORRENT_ASSERT(m_upload_limit >= 0); TORRENT_ASSERT(m_upload_limit >= 0);
TORRENT_ASSERT(m_download_limit >= 0); TORRENT_ASSERT(m_download_limit >= 0);
// TODO: why does this invariant not hold?
/*
if (m_channel_state[upload_channel] & peer_info::bw_limit)
TORRENT_ASSERT(m_ses.m_upload_rate.is_queued(this));
if (m_channel_state[download_channel] & peer_info::bw_limit)
TORRENT_ASSERT(m_ses.m_download_rate.is_queued(this));
*/
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
if (!m_disconnect_started && m_initialized) if (!m_disconnect_started && m_initialized)
@ -5829,11 +5847,20 @@ namespace libtorrent
// in share mode we don't close redundant connections // in share mode we don't close redundant connections
if (m_ses.settings().close_redundant_connections && !t->share_mode()) if (m_ses.settings().close_redundant_connections && !t->share_mode())
{ {
bool ok_to_disconnect =
can_disconnect(error_code(errors::upload_upload_connection, get_libtorrent_category()))
|| can_disconnect(error_code(errors::uninteresting_upload_peer, get_libtorrent_category()))
|| can_disconnect(error_code(errors::too_many_requests_when_choked, get_libtorrent_category()))
|| can_disconnect(error_code(errors::timed_out_no_interest, get_libtorrent_category()))
|| can_disconnect(error_code(errors::timed_out_no_request, get_libtorrent_category()))
|| can_disconnect(error_code(errors::timed_out_inactivity, get_libtorrent_category()));
// make sure upload only peers are disconnected // make sure upload only peers are disconnected
if (t->is_upload_only() if (t->is_upload_only()
&& m_upload_only && m_upload_only
&& t->valid_metadata() && t->valid_metadata()
&& has_metadata()) && has_metadata()
&& ok_to_disconnect)
TORRENT_ASSERT(m_disconnect_started || t->graceful_pause() || t->has_error()); TORRENT_ASSERT(m_disconnect_started || t->graceful_pause() || t->has_error());
if (m_upload_only if (m_upload_only
@ -5841,7 +5868,8 @@ namespace libtorrent
&& m_bitfield_received && m_bitfield_received
&& t->are_files_checked() && t->are_files_checked()
&& t->valid_metadata() && t->valid_metadata()
&& has_metadata()) && has_metadata()
&& ok_to_disconnect)
TORRENT_ASSERT(m_disconnect_started); TORRENT_ASSERT(m_disconnect_started);
} }

View File

@ -3040,6 +3040,7 @@ retry:
if (num_connections() >= m_settings.connections_limit) if (num_connections() >= m_settings.connections_limit)
c->peer_exceeds_limit(); c->peer_exceeds_limit();
TORRENT_ASSERT(!c->m_in_constructor);
m_connections.insert(c); m_connections.insert(c);
c->start(); c->start();
// update the next disk peer round-robin cursor // update the next disk peer round-robin cursor
@ -3360,8 +3361,8 @@ retry:
int total_peers = num_peers[0][i] + num_peers[1][i]; int total_peers = num_peers[0][i] + num_peers[1][i];
// this are 64 bits since it's multiplied by the number // this are 64 bits since it's multiplied by the number
// of peers, which otherwise might overflow an int // of peers, which otherwise might overflow an int
boost::uint64_t rate = (std::max)(stat_rate[i], lower_limit[i]); boost::uint64_t rate = stat_rate[i];
tcp_channel[i]->throttle(int(rate * num_peers[0][i] / total_peers)); tcp_channel[i]->throttle((std::max)(int(rate * num_peers[0][i] / total_peers), lower_limit[i]));
} }
} }
} }

View File

@ -4949,6 +4949,7 @@ namespace libtorrent
TORRENT_TRY TORRENT_TRY
{ {
TORRENT_ASSERT(!c->m_in_constructor);
// add the newly connected peer to this torrent's peer list // add the newly connected peer to this torrent's peer list
m_connections.insert(boost::get_pointer(c)); m_connections.insert(boost::get_pointer(c));
m_ses.m_connections.insert(c); m_ses.m_connections.insert(c);

View File

@ -490,6 +490,9 @@ namespace libtorrent
// if the status code is not one of the accepted ones, abort // if the status code is not one of the accepted ones, abort
if (!is_ok_status(m_parser.status_code())) if (!is_ok_status(m_parser.status_code()))
{ {
// TODO: 3 just make this peer not have the pieces
// associated with the file we just requested. Only
// when it doesn't have any of the file do the following
int retry_time = atoi(m_parser.header("retry-after").c_str()); int retry_time = atoi(m_parser.header("retry-after").c_str());
if (retry_time <= 0) retry_time = m_ses.settings().urlseed_wait_retry; if (retry_time <= 0) retry_time = m_ses.settings().urlseed_wait_retry;
// temporarily unavailable, retry later // temporarily unavailable, retry later
@ -540,6 +543,7 @@ namespace libtorrent
TORRENT_ASSERT(!m_file_requests.empty()); TORRENT_ASSERT(!m_file_requests.empty());
int file_index = m_file_requests.front(); int file_index = m_file_requests.front();
// TODO: 2 create a mapping of file-index to redirection URLs. Use that to form URLs instead. Support to reconnect to a new server without destructing this peer_connection
torrent_info const& info = t->torrent_file(); torrent_info const& info = t->torrent_file();
std::string path = info.orig_files().file_path(file_index); std::string path = info.orig_files().file_path(file_index);
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS