fixed choke-unchoke problem in policy

This commit is contained in:
Arvid Norberg 2005-08-18 20:38:03 +00:00
parent df4466cb86
commit 356df1bd32
4 changed files with 91 additions and 44 deletions

View File

@ -28,7 +28,7 @@ project torrent
<variant>release:<define>NDEBUG <variant>release:<define>NDEBUG
<define>BOOST_ALL_NO_LIB <define>BOOST_ALL_NO_LIB
<define>_FILE_OFFSET_BITS=64 <define>_FILE_OFFSET_BITS=64
<library>/boost/thread//boost_thread/<link>shared <library>/boost/thread//boost_thread/<link>static
<library>/boost/filesystem//boost_filesystem/<link>static <library>/boost/filesystem//boost_filesystem/<link>static
<library>/boost/date_time//boost_date_time/<link>static <library>/boost/date_time//boost_date_time/<link>static
<link>static <link>static

View File

@ -273,12 +273,13 @@ namespace libtorrent
resource_request m_ul_bandwidth_quota; resource_request m_ul_bandwidth_quota;
resource_request m_dl_bandwidth_quota; resource_request m_dl_bandwidth_quota;
private:
#ifndef NDEBUG #ifndef NDEBUG
void check_invariant() const; void check_invariant() const;
boost::posix_time::ptime m_last_choke;
#endif #endif
private:
bool dispatch_message(int received); bool dispatch_message(int received);
// if we don't have all metadata // if we don't have all metadata

View File

@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -170,12 +171,14 @@ namespace libtorrent
private: private:
bool unchoke_one_peer(); bool unchoke_one_peer();
void choke_one_peer();
peer* find_choke_candidate(); peer* find_choke_candidate();
peer* find_unchoke_candidate(); peer* find_unchoke_candidate();
// the seed prefix means that the // the seed prefix means that the
// function is used while seeding. // function is used while seeding.
bool seed_unchoke_one_peer(); bool seed_unchoke_one_peer();
void seed_choke_one_peer();
peer* find_seed_choke_candidate(); peer* find_seed_choke_candidate();
peer* find_seed_unchoke_candidate(); peer* find_seed_unchoke_candidate();

View File

@ -426,6 +426,10 @@ namespace libtorrent
&& m_torrent->ratio() != 0) continue; && m_torrent->ratio() != 0) continue;
if (c->statistics().download_rate() < max_down_speed) continue; if (c->statistics().download_rate() < max_down_speed) continue;
// if (i->last_optimistically_unchoked > min_time) continue; // if (i->last_optimistically_unchoked > min_time) continue;
#ifndef NDEBUG
using namespace boost::posix_time;
assert(second_clock::universal_time() - c->m_last_choke > seconds(9));
#endif
min_time = i->last_optimistically_unchoked; min_time = i->last_optimistically_unchoked;
max_down_speed = c->statistics().download_rate(); max_down_speed = c->statistics().download_rate();
@ -443,8 +447,7 @@ namespace libtorrent
= second_clock::universal_time(); = second_clock::universal_time();
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); i != m_peers.end(); ++i)
++i)
{ {
peer_connection* c = i->connection; peer_connection* c = i->connection;
if(c == 0) if(c == 0)
@ -508,6 +511,7 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
assert(m_num_unchoked > 0);
// first choice candidate. // first choice candidate.
// it is a candidate we owe nothing to and which has been unchoked // it is a candidate we owe nothing to and which has been unchoked
// the longest. // the longest.
@ -585,6 +589,8 @@ namespace libtorrent
bool policy::seed_unchoke_one_peer() bool policy::seed_unchoke_one_peer()
{ {
INVARIANT_CHECK;
peer* p = find_seed_unchoke_candidate(); peer* p = find_seed_unchoke_candidate();
if (p != 0) if (p != 0)
{ {
@ -597,6 +603,19 @@ namespace libtorrent
return p != 0; return p != 0;
} }
void policy::seed_choke_one_peer()
{
INVARIANT_CHECK;
peer* p = find_seed_choke_candidate();
if (p != 0)
{
assert(!p->connection->is_choked());
p->connection->send_choke();
--m_num_unchoked;
}
}
void policy::pulse() void policy::pulse()
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -705,26 +724,35 @@ namespace libtorrent
// ------------------------ // ------------------------
if (m_torrent->is_seed()) if (m_torrent->is_seed())
{ {
if (num_connected_peers > m_torrent->m_uploads_quota.given) if (m_num_unchoked > m_torrent->m_uploads_quota.given)
{ {
// this means there are some peers that do
// are choked. To have the choked peers {
// rotate, unchoke one peer here peer* p = find_seed_choke_candidate();
// and let the next condiional block --m_num_unchoked;
// make sure another peer is choked. assert(p != 0);
if (p == 0) break;
assert(!p->connection->is_choked());
p->connection->send_choke();
} while (m_num_unchoked > m_torrent->m_uploads_quota.given);
}
else
{
// optimistic unchoke. trade the 'worst'
// unchoked peer with one of the choked
// TODO: This rotation should happen // TODO: This rotation should happen
// far less frequent than this! // far less frequent than this!
seed_unchoke_one_peer(); assert(m_num_unchoked <= m_torrent->num_peers());
} peer* p = find_seed_unchoke_candidate();
if (p)
while (m_num_unchoked > m_torrent->m_uploads_quota.given) {
{ assert(p->connection->is_choked());
peer* p = find_seed_choke_candidate(); seed_choke_one_peer();
assert(p != 0); p->connection->send_unchoke();
++m_num_unchoked;
assert(!p->connection->is_choked()); }
p->connection->send_choke();
--m_num_unchoked;
} }
// make sure we have enough // make sure we have enough
@ -770,26 +798,33 @@ namespace libtorrent
// make sure we don't have too many // make sure we don't have too many
// unchoked peers // unchoked peers
while (m_num_unchoked > m_torrent->m_uploads_quota.given) if (m_num_unchoked > m_torrent->m_uploads_quota.given)
{ {
peer* p = find_choke_candidate(); do
if (!p) break; {
assert(p); peer* p = find_choke_candidate();
assert(!p->connection->is_choked()); if (!p) break;
p->connection->send_choke(); assert(p);
--m_num_unchoked; assert(!p->connection->is_choked());
p->connection->send_choke();
--m_num_unchoked;
} while (m_num_unchoked > m_torrent->m_uploads_quota.given);
} }
else
// optimistic unchoke. trade the 'worst'
// unchoked peer with one of the choked
assert(m_num_unchoked <= m_torrent->num_peers());
peer* p = find_choke_candidate();
if (p)
{ {
assert(!p->connection->is_choked()); // optimistic unchoke. trade the 'worst'
p->connection->send_choke(); // unchoked peer with one of the choked
--m_num_unchoked; // TODO: This rotation should happen
unchoke_one_peer(); // far less frequent than this!
assert(m_num_unchoked <= m_torrent->num_peers());
peer* p = find_unchoke_candidate();
if (p)
{
assert(p->connection->is_choked());
choke_one_peer();
p->connection->send_unchoke();
++m_num_unchoked;
}
} }
} }
@ -958,8 +993,7 @@ namespace libtorrent
{ {
// have all peers update their interested-flag // have all peers update their interested-flag
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); i != m_peers.end(); ++i)
++i)
{ {
if (i->connection == 0) continue; if (i->connection == 0) continue;
// if we're not interested, we will not become interested // if we're not interested, we will not become interested
@ -1067,6 +1101,17 @@ namespace libtorrent
return true; return true;
} }
void policy::choke_one_peer()
{
peer* p = find_choke_candidate();
if (p == 0) return;
assert(p->connection);
assert(!p->connection->is_disconnecting());
assert(!p->connection->is_choked());
p->connection->send_choke();
--m_num_unchoked;
}
bool policy::connect_one_peer() bool policy::connect_one_peer()
{ {
if(m_torrent->num_peers() >= m_torrent->m_connections_quota.given) if(m_torrent->num_peers() >= m_torrent->m_connections_quota.given)
@ -1113,8 +1158,6 @@ namespace libtorrent
// this is called whenever a peer connection is closed // this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c) void policy::connection_closed(const peer_connection& c)
{ {
INVARIANT_CHECK;
bool unchoked = false; bool unchoked = false;
std::vector<peer>::iterator i = std::find_if( std::vector<peer>::iterator i = std::find_if(
@ -1181,7 +1224,6 @@ namespace libtorrent
void policy::check_invariant() const void policy::check_invariant() const
{ {
if (m_torrent->is_aborted()) return; if (m_torrent->is_aborted()) return;
// assert(m_torrent->m_uploads_quota.given >= 2);
int actual_unchoked = 0; int actual_unchoked = 0;
for (std::vector<peer>::const_iterator i = m_peers.begin(); for (std::vector<peer>::const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
@ -1234,3 +1276,4 @@ namespace libtorrent
} }
} }
} }