added feature to set a separate global rate limit for local peers

This commit is contained in:
Arvid Norberg 2009-05-14 17:21:19 +00:00
parent 28c334fb35
commit 31c422df0a
7 changed files with 170 additions and 46 deletions

View File

@ -1,3 +1,4 @@
* added feature to set a separate global rate limit for local peers
* added preset settings for low memory environments and seed machines
min_memory_usage() and high_performance_seeder()
* optimized overall memory usage for DHT nodes and requests, peer

View File

@ -229,6 +229,11 @@ namespace libtorrent
int upload_rate_limit() const;
int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
void set_local_download_rate_limit(int bytes_per_second);
void set_local_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second);
@ -426,9 +431,18 @@ namespace libtorrent
bandwidth_manager<peer_connection> m_download_rate;
bandwidth_manager<peer_connection> m_upload_rate;
// the global rate limiter bandwidth channels
bandwidth_channel m_download_channel;
bandwidth_channel m_upload_channel;
// bandwidth channels for local peers when
// rate limits are ignored. They are only
// throttled by these global rate limiters
// and they don't have a rate limit set by
// default
bandwidth_channel m_local_download_channel;
bandwidth_channel m_local_upload_channel;
bandwidth_channel* m_bandwidth_channel[2];
tracker_manager m_tracker_manager;

View File

@ -634,6 +634,16 @@ namespace libtorrent
void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r);
void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request r, boost::shared_ptr<torrent> t);
void request_upload_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
void request_download_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
// keep the io_service running as long as we
// have peer connections

View File

@ -370,8 +370,12 @@ namespace libtorrent
int upload_rate_limit() const;
int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
int max_half_open_connections() const;
void set_local_upload_rate_limit(int bytes_per_second);
void set_local_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second);
void set_max_uploads(int limit);

View File

@ -3565,6 +3565,47 @@ namespace libtorrent
}
}
void peer_connection::request_upload_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2
, bandwidth_channel* bwc3
, bandwidth_channel* bwc4)
{
shared_ptr<torrent> t = m_torrent.lock();
int priority = 1 + is_interesting() * 2 + m_requests_in_buffer.size();
// peers that we are not interested in are non-prioritized
m_channel_state[upload_channel] = peer_info::bw_limit;
m_ses.m_upload_rate.request_bandwidth(self()
, m_send_buffer.size(), priority
, bwc1, bwc2, bwc3, bwc4);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"upload: " << m_send_buffer.size()
<< " prio: " << priority << "]\n";
#endif
}
void peer_connection::request_download_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2
, bandwidth_channel* bwc3
, bandwidth_channel* bwc4)
{
shared_ptr<torrent> t = m_torrent.lock();
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"download: " << (m_download_queue.size() * 16 * 1024 + 30)
<< " prio: " << m_priority << " ]\n";
#endif
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
TORRENT_ASSERT(m_outstanding_bytes >= 0);
m_channel_state[download_channel] = peer_info::bw_limit;
m_ses.m_download_rate.request_bandwidth(self()
, m_outstanding_bytes + 30, m_priority
, bwc1, bwc2, bwc3, bwc4);
}
void peer_connection::setup_send()
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -3576,26 +3617,27 @@ namespace libtorrent
if (m_quota[upload_channel] == 0
&& !m_send_buffer.empty()
&& !m_connecting
&& t
&& !m_ignore_bandwidth_limits)
&& t)
{
// in this case, we have data to send, but no
// bandwidth. So, we simply request bandwidth
// from the torrent
TORRENT_ASSERT(t);
int priority = 1 + is_interesting() * 2 + m_requests_in_buffer.size();
// peers that we are not interested in are non-prioritized
m_channel_state[upload_channel] = peer_info::bw_limit;
m_ses.m_upload_rate.request_bandwidth(self()
, m_send_buffer.size(), priority
, &m_ses.m_upload_channel
, &t->m_bandwidth_channel[upload_channel]
, &m_bandwidth_channel[upload_channel]);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"upload: " << m_send_buffer.size()
<< " prio: " << priority << "]\n";
#endif
if (!m_ignore_bandwidth_limits)
{
// in this case, we have data to send, but no
// bandwidth. So, we simply request bandwidth
// from the bandwidth manager
request_upload_bandwidth(
&m_ses.m_upload_channel
, &t->m_bandwidth_channel[upload_channel]
, &m_bandwidth_channel[upload_channel]);
}
else
{
// in this case, we're a local peer, and the settings
// are set to ignore rate limits for local peers. So,
// instead we rate limit ourself against the special
// global bandwidth channel for local peers, which defaults
// to unthrottled
request_upload_bandwidth(&m_ses.m_local_upload_channel);
}
return;
}
@ -3656,22 +3698,27 @@ namespace libtorrent
if (m_quota[download_channel] == 0
&& !m_connecting
&& t
&& !m_ignore_bandwidth_limits)
&& t)
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"download: " << (m_download_queue.size() * 16 * 1024 + 30)
<< " prio: " << m_priority << " ]\n";
#endif
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
TORRENT_ASSERT(m_outstanding_bytes >= 0);
m_channel_state[download_channel] = peer_info::bw_limit;
m_ses.m_download_rate.request_bandwidth(self()
, m_outstanding_bytes + 30, m_priority
, &m_ses.m_download_channel
, &t->m_bandwidth_channel[download_channel]
, &m_bandwidth_channel[download_channel]);
if (!m_ignore_bandwidth_limits)
{
// in this case, we have outstanding data to
// receive, but no bandwidth quota. So, we simply
// request bandwidth from the bandwidth manager
request_download_bandwidth(
&m_ses.m_download_channel
, &t->m_bandwidth_channel[download_channel]
, &m_bandwidth_channel[download_channel]);
}
else
{
// in this case, we're a local peer, and the settings
// are set to ignore rate limits for local peers. So,
// instead we rate limit ourself against the special
// global bandwidth channel for local peers, which defaults
// to unthrottled
request_download_bandwidth(&m_ses.m_local_download_channel);
}
return;
}

View File

@ -652,6 +652,16 @@ namespace libtorrent
m_impl->set_max_half_open_connections(limit);
}
int session::local_upload_rate_limit() const
{
return m_impl->local_upload_rate_limit();
}
int session::local_download_rate_limit() const
{
return m_impl->local_download_rate_limit();
}
int session::upload_rate_limit() const
{
return m_impl->upload_rate_limit();
@ -662,6 +672,16 @@ namespace libtorrent
return m_impl->download_rate_limit();
}
void session::set_local_upload_rate_limit(int bytes_per_second)
{
m_impl->set_local_upload_rate_limit(bytes_per_second);
}
void session::set_local_download_rate_limit(int bytes_per_second)
{
m_impl->set_local_download_rate_limit(bytes_per_second);
}
void session::set_upload_rate_limit(int bytes_per_second)
{
m_impl->set_upload_rate_limit(bytes_per_second);

View File

@ -1772,7 +1772,8 @@ namespace aux {
// assume a reasonable rate is 3 kB/s, unless there's an upload limit and
// a max number of slots, in which case we assume each upload slot gets
// roughly the same amount of bandwidth
if (m_upload_channel.throttle() != bandwidth_channel::inf && m_max_uploads > 0)
TORRENT_ASSERT(m_upload_channel.throttle() != bandwidth_channel::inf);
if (m_upload_channel.throttle() > 0 && m_max_uploads > 0)
rate = (std::max)(m_upload_channel.throttle() / m_max_uploads, 1);
// the time it takes to download one piece at this rate (in seconds)
@ -2665,14 +2666,34 @@ namespace aux {
m_half_open.limit(limit);
}
void session_impl::set_local_download_rate_limit(int bytes_per_second)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = 0;
m_local_download_channel.throttle(bytes_per_second);
}
void session_impl::set_local_upload_rate_limit(int bytes_per_second)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = 0;
m_local_upload_channel.throttle(bytes_per_second);
}
void session_impl::set_download_rate_limit(int bytes_per_second)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_channel::inf;
m_bandwidth_channel[peer_connection::download_channel]->throttle(bytes_per_second);
if (bytes_per_second <= 0) bytes_per_second = 0;
m_download_channel.throttle(bytes_per_second);
}
void session_impl::set_upload_rate_limit(int bytes_per_second)
@ -2681,8 +2702,8 @@ namespace aux {
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_channel::inf;
m_bandwidth_channel[peer_connection::upload_channel]->throttle(bytes_per_second);
if (bytes_per_second <= 0) bytes_per_second = 0;
m_upload_channel.throttle(bytes_per_second);
}
void session_impl::set_alert_dispatch(boost::function<void(alert const&)> const& fun)
@ -2720,21 +2741,28 @@ namespace aux {
return m_alerts.set_alert_queue_size_limit(queue_size_limit_);
}
int session_impl::local_upload_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
return m_local_upload_channel.throttle();
}
int session_impl::local_download_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
return m_local_download_channel.throttle();
}
int session_impl::upload_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
int ret = m_bandwidth_channel[peer_connection::upload_channel]->throttle();
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
return m_upload_channel.throttle();
}
int session_impl::download_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
int ret = m_bandwidth_channel[peer_connection::download_channel]->throttle();
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
return m_download_channel.throttle();
}
void session_impl::start_lsd()