fixed per torrent unchoke limit

This commit is contained in:
Arvid Norberg 2007-08-17 07:37:08 +00:00
parent 834873a15e
commit 3d3df51d45
4 changed files with 86 additions and 17 deletions

View File

@ -282,7 +282,9 @@ namespace libtorrent
void unchoke_peer(peer_connection& c) void unchoke_peer(peer_connection& c)
{ {
c.send_unchoke(); torrent* t = c.associated_torrent().lock().get();
assert(t);
t->unchoke_peer(c);
++m_num_unchoked; ++m_num_unchoked;
} }

View File

@ -249,6 +249,13 @@ namespace libtorrent
void remove_url_seed(std::string const& url) void remove_url_seed(std::string const& url)
{ m_web_seeds.erase(url); } { m_web_seeds.erase(url); }
bool free_upload_slots() const
{ return m_num_uploads < m_max_uploads; }
void choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c);
// used by peer_connection to attach itself to a torrent // used by peer_connection to attach itself to a torrent
// since incoming connections don't know what torrent // since incoming connections don't know what torrent
// they're a part of until they have received an info_hash. // they're a part of until they have received an info_hash.
@ -770,6 +777,9 @@ namespace libtorrent
// the maximum number of uploads for this torrent // the maximum number of uploads for this torrent
int m_max_uploads; int m_max_uploads;
// the number of unchoked peers in this torrent
int m_num_uploads;
// the maximum number of connections for this torrent // the maximum number of connections for this torrent
int m_max_connections; int m_max_connections;

View File

@ -1046,14 +1046,15 @@ namespace detail
peer_connection* p = i->second.get(); peer_connection* p = i->second.get();
torrent* t = p->associated_torrent().lock().get(); torrent* t = p->associated_torrent().lock().get();
if (!p->peer_info_struct() if (!p->peer_info_struct()
|| t == 0
|| !p->is_peer_interested() || !p->is_peer_interested()
|| p->is_disconnecting() || p->is_disconnecting()
|| p->is_connecting() || p->is_connecting()
|| (p->share_diff() < -free_upload_amount || (p->share_diff() < -free_upload_amount
&& t && !t->is_seed())) && !t->is_seed()))
{ {
if (!i->second->is_choked()) if (!i->second->is_choked() && t)
i->second->send_choke(); t->choke_peer(*i->second);
continue; continue;
} }
peers.push_back(i->second.get()); peers.push_back(i->second.get());
@ -1082,9 +1083,24 @@ namespace detail
{ {
peer_connection* p = *i; peer_connection* p = *i;
assert(p); assert(p);
torrent* t = p->associated_torrent().lock().get();
assert(t);
if (unchoke_set_size > 0) if (unchoke_set_size > 0)
{ {
if (p->is_choked()) p->send_unchoke(); if (p->is_choked())
{
if (t->unchoke_peer(*p))
{
--unchoke_set_size;
++m_num_unchoked;
}
}
else
{
--unchoke_set_size;
++m_num_unchoked;
}
assert(p->peer_info_struct()); assert(p->peer_info_struct());
if (p->peer_info_struct()->optimistically_unchoked) if (p->peer_info_struct()->optimistically_unchoked)
{ {
@ -1092,13 +1108,11 @@ namespace detail
m_optimistic_unchoke_time_scaler = 0; m_optimistic_unchoke_time_scaler = 0;
p->peer_info_struct()->optimistically_unchoked = false; p->peer_info_struct()->optimistically_unchoked = false;
} }
--unchoke_set_size;
++m_num_unchoked;
} }
else else
{ {
if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked) if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
p->send_choke(); t->choke_peer(*p);
} }
} }
@ -1121,15 +1135,21 @@ namespace detail
assert(p); assert(p);
policy::peer* pi = p->peer_info_struct(); policy::peer* pi = p->peer_info_struct();
if (!pi) continue; if (!pi) continue;
torrent* t = p->associated_torrent().lock().get();
if (!t) continue;
if (pi->optimistically_unchoked) if (pi->optimistically_unchoked)
{ {
assert(current_optimistic_unchoke == m_connections.end()); assert(current_optimistic_unchoke == m_connections.end());
current_optimistic_unchoke = i; current_optimistic_unchoke = i;
} }
if (pi->last_optimistically_unchoked < last_unchoke if (pi->last_optimistically_unchoked < last_unchoke
&& !p->is_connecting() && !p->is_connecting()
&& !p->is_disconnecting() && !p->is_disconnecting()
&& p->is_peer_interested()) && p->is_peer_interested()
&& t->free_upload_slots()
&& p->is_choked())
{ {
last_unchoke = pi->last_optimistically_unchoked; last_unchoke = pi->last_optimistically_unchoked;
optimistic_unchoke_candidate = i; optimistic_unchoke_candidate = i;
@ -1141,11 +1161,16 @@ namespace detail
{ {
if (current_optimistic_unchoke != m_connections.end()) if (current_optimistic_unchoke != m_connections.end())
{ {
current_optimistic_unchoke->second->send_choke(); torrent* t = current_optimistic_unchoke->second->associated_torrent().lock().get();
assert(t);
t->choke_peer(*current_optimistic_unchoke->second);
current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false; current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false;
} }
optimistic_unchoke_candidate->second->send_unchoke(); torrent* t = optimistic_unchoke_candidate->second->associated_torrent().lock().get();
assert(t);
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->second);
assert(ret);
optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true; optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true;
} }
@ -2090,6 +2115,8 @@ namespace detail
#ifndef NDEBUG #ifndef NDEBUG
void session_impl::check_invariant(const char *place) void session_impl::check_invariant(const char *place)
{ {
assert(m_max_connections > 0);
assert(m_max_uploads > 0);
assert(place); assert(place);
int unchokes = 0; int unchokes = 0;
int num_optimistic = 0; int num_optimistic = 0;

View File

@ -200,6 +200,7 @@ namespace libtorrent
, m_settings(s) , m_settings(s)
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_max_uploads(std::numeric_limits<int>::max()) , m_max_uploads(std::numeric_limits<int>::max())
, m_num_uploads(0)
, m_max_connections(std::numeric_limits<int>::max()) , m_max_connections(std::numeric_limits<int>::max())
{ {
#ifndef NDEBUG #ifndef NDEBUG
@ -208,7 +209,6 @@ namespace libtorrent
m_policy.reset(new policy(this)); m_policy.reset(new policy(this));
} }
torrent::torrent( torrent::torrent(
session_impl& ses session_impl& ses
, aux::checker_impl& checker , aux::checker_impl& checker
@ -262,6 +262,9 @@ namespace libtorrent
, m_connections_initialized(false) , m_connections_initialized(false)
, m_settings(s) , m_settings(s)
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_max_uploads(std::numeric_limits<int>::max())
, m_num_uploads(0)
, m_max_connections(std::numeric_limits<int>::max())
{ {
#ifndef NDEBUG #ifndef NDEBUG
m_initial_done = 0; m_initial_done = 0;
@ -1387,6 +1390,27 @@ namespace libtorrent
return req; return req;
} }
void torrent::choke_peer(peer_connection& c)
{
INVARIANT_CHECK;
assert(!c.is_choked());
assert(m_num_uploads > 0);
c.send_choke();
--m_num_uploads;
}
bool torrent::unchoke_peer(peer_connection& c)
{
INVARIANT_CHECK;
assert(c.is_choked());
if (m_num_uploads >= m_max_uploads) return false;
c.send_unchoke();
++m_num_uploads;
return true;
}
void torrent::cancel_block(piece_block block) void torrent::cancel_block(piece_block block)
{ {
for (peer_iterator i = m_connections.begin() for (peer_iterator i = m_connections.begin()
@ -1437,6 +1461,9 @@ namespace libtorrent
} }
} }
if (!p->is_choked())
--m_num_uploads;
m_policy->connection_closed(*p); m_policy->connection_closed(*p);
p->set_peer_info(0); p->set_peer_info(0);
m_connections.erase(i); m_connections.erase(i);
@ -2358,6 +2385,7 @@ namespace libtorrent
// size_type download = m_stat.total_payload_download(); // size_type download = m_stat.total_payload_download();
// size_type done = boost::get<0>(bytes_done()); // size_type done = boost::get<0>(bytes_done());
// assert(download >= done - m_initial_done); // assert(download >= done - m_initial_done);
int num_uploads = 0;
std::map<piece_block, int> num_requests; std::map<piece_block, int> num_requests;
for (const_peer_iterator i = begin(); i != end(); ++i) for (const_peer_iterator i = begin(); i != end(); ++i)
{ {
@ -2368,10 +2396,12 @@ namespace libtorrent
for (std::deque<piece_block>::const_iterator i = p.download_queue().begin() for (std::deque<piece_block>::const_iterator i = p.download_queue().begin()
, end(p.download_queue().end()); i != end; ++i) , end(p.download_queue().end()); i != end; ++i)
++num_requests[*i]; ++num_requests[*i];
if (!p.is_choked()) ++num_uploads;
torrent* associated_torrent = p.associated_torrent().lock().get(); torrent* associated_torrent = p.associated_torrent().lock().get();
if (associated_torrent != this) if (associated_torrent != this)
assert(false); assert(false);
} }
assert(num_uploads == m_num_uploads);
if (has_picker()) if (has_picker())
{ {
@ -2429,14 +2459,14 @@ namespace libtorrent
void torrent::set_max_uploads(int limit) void torrent::set_max_uploads(int limit)
{ {
assert(limit >= -1); assert(limit >= -1);
if (limit < 0) limit = std::numeric_limits<int>::max(); if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_uploads = limit; m_max_uploads = limit;
} }
void torrent::set_max_connections(int limit) void torrent::set_max_connections(int limit)
{ {
assert(limit >= -1); assert(limit >= -1);
if (limit < -1) limit = std::numeric_limits<int>::max(); if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_connections = limit; m_max_connections = limit;
} }
@ -2459,7 +2489,7 @@ namespace libtorrent
void torrent::set_upload_limit(int limit) void torrent::set_upload_limit(int limit)
{ {
assert(limit >= -1); assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max(); if (limit <= 0) limit = std::numeric_limits<int>::max();
if (limit < num_peers() * 10) limit = num_peers() * 10; if (limit < num_peers() * 10) limit = num_peers() * 10;
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit); m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
} }
@ -2474,7 +2504,7 @@ namespace libtorrent
void torrent::set_download_limit(int limit) void torrent::set_download_limit(int limit)
{ {
assert(limit >= -1); assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max(); if (limit <= 0) limit = std::numeric_limits<int>::max();
if (limit < num_peers() * 10) limit = num_peers() * 10; if (limit < num_peers() * 10) limit = num_peers() * 10;
m_bandwidth_limit[peer_connection::download_channel].throttle(limit); m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
} }
@ -2759,7 +2789,7 @@ namespace libtorrent
= m_trackers[m_last_working_tracker].url; = m_trackers[m_last_working_tracker].url;
} }
st.num_uploads = -1; st.num_uploads = m_num_uploads;
st.uploads_limit = m_max_uploads; st.uploads_limit = m_max_uploads;
st.num_connections = int(m_connections.size()); st.num_connections = int(m_connections.size());
st.connections_limit = m_max_connections; st.connections_limit = m_max_connections;