forked from premiere/premiere-libtorrent
fixed choke-unchoke problem in policy
This commit is contained in:
parent
df4466cb86
commit
356df1bd32
2
Jamfile
2
Jamfile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
// and let the next condiional block
|
|
||||||
// make sure another peer is choked.
|
|
||||||
// TODO: This rotation should happen
|
|
||||||
// far less frequent than this!
|
|
||||||
seed_unchoke_one_peer();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (m_num_unchoked > m_torrent->m_uploads_quota.given)
|
|
||||||
{
|
{
|
||||||
peer* p = find_seed_choke_candidate();
|
peer* p = find_seed_choke_candidate();
|
||||||
|
--m_num_unchoked;
|
||||||
assert(p != 0);
|
assert(p != 0);
|
||||||
|
if (p == 0) break;
|
||||||
|
|
||||||
assert(!p->connection->is_choked());
|
assert(!p->connection->is_choked());
|
||||||
p->connection->send_choke();
|
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
|
||||||
|
// TODO: This rotation should happen
|
||||||
|
// far less frequent than this!
|
||||||
|
assert(m_num_unchoked <= m_torrent->num_peers());
|
||||||
|
peer* p = find_seed_unchoke_candidate();
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
assert(p->connection->is_choked());
|
||||||
|
seed_choke_one_peer();
|
||||||
|
p->connection->send_unchoke();
|
||||||
|
++m_num_unchoked;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we have enough
|
// make sure we have enough
|
||||||
|
@ -770,7 +798,9 @@ 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)
|
||||||
|
{
|
||||||
|
do
|
||||||
{
|
{
|
||||||
peer* p = find_choke_candidate();
|
peer* p = find_choke_candidate();
|
||||||
if (!p) break;
|
if (!p) break;
|
||||||
|
@ -778,18 +808,23 @@ namespace libtorrent
|
||||||
assert(!p->connection->is_choked());
|
assert(!p->connection->is_choked());
|
||||||
p->connection->send_choke();
|
p->connection->send_choke();
|
||||||
--m_num_unchoked;
|
--m_num_unchoked;
|
||||||
|
} while (m_num_unchoked > m_torrent->m_uploads_quota.given);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// optimistic unchoke. trade the 'worst'
|
// optimistic unchoke. trade the 'worst'
|
||||||
// unchoked peer with one of the choked
|
// unchoked peer with one of the choked
|
||||||
|
// TODO: This rotation should happen
|
||||||
|
// far less frequent than this!
|
||||||
assert(m_num_unchoked <= m_torrent->num_peers());
|
assert(m_num_unchoked <= m_torrent->num_peers());
|
||||||
peer* p = find_choke_candidate();
|
peer* p = find_unchoke_candidate();
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
assert(!p->connection->is_choked());
|
assert(p->connection->is_choked());
|
||||||
p->connection->send_choke();
|
choke_one_peer();
|
||||||
--m_num_unchoked;
|
p->connection->send_unchoke();
|
||||||
unchoke_one_peer();
|
++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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue