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
|
||||
<define>BOOST_ALL_NO_LIB
|
||||
<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/date_time//boost_date_time/<link>static
|
||||
<link>static
|
||||
|
|
|
@ -273,12 +273,13 @@ namespace libtorrent
|
|||
resource_request m_ul_bandwidth_quota;
|
||||
resource_request m_dl_bandwidth_quota;
|
||||
|
||||
private:
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const;
|
||||
boost::posix_time::ptime m_last_choke;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
bool dispatch_message(int received);
|
||||
|
||||
// if we don't have all metadata
|
||||
|
|
|
@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/piece_picker.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/size_type.hpp"
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -170,12 +171,14 @@ namespace libtorrent
|
|||
private:
|
||||
|
||||
bool unchoke_one_peer();
|
||||
void choke_one_peer();
|
||||
peer* find_choke_candidate();
|
||||
peer* find_unchoke_candidate();
|
||||
|
||||
// the seed prefix means that the
|
||||
// function is used while seeding.
|
||||
bool seed_unchoke_one_peer();
|
||||
void seed_choke_one_peer();
|
||||
peer* find_seed_choke_candidate();
|
||||
peer* find_seed_unchoke_candidate();
|
||||
|
||||
|
|
|
@ -426,6 +426,10 @@ namespace libtorrent
|
|||
&& m_torrent->ratio() != 0) continue;
|
||||
if (c->statistics().download_rate() < max_down_speed) 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;
|
||||
max_down_speed = c->statistics().download_rate();
|
||||
|
@ -443,8 +447,7 @@ namespace libtorrent
|
|||
= second_clock::universal_time();
|
||||
|
||||
for (std::vector<peer>::iterator i = m_peers.begin();
|
||||
i != m_peers.end();
|
||||
++i)
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
peer_connection* c = i->connection;
|
||||
if(c == 0)
|
||||
|
@ -508,6 +511,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(m_num_unchoked > 0);
|
||||
// first choice candidate.
|
||||
// it is a candidate we owe nothing to and which has been unchoked
|
||||
// the longest.
|
||||
|
@ -585,6 +589,8 @@ namespace libtorrent
|
|||
|
||||
bool policy::seed_unchoke_one_peer()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
peer* p = find_seed_unchoke_candidate();
|
||||
if (p != 0)
|
||||
{
|
||||
|
@ -597,6 +603,19 @@ namespace libtorrent
|
|||
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()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -705,26 +724,35 @@ namespace libtorrent
|
|||
// ------------------------
|
||||
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
|
||||
// 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)
|
||||
do
|
||||
{
|
||||
peer* p = find_seed_choke_candidate();
|
||||
--m_num_unchoked;
|
||||
assert(p != 0);
|
||||
if (p == 0) break;
|
||||
|
||||
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
|
||||
// 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
|
||||
|
@ -770,7 +798,9 @@ namespace libtorrent
|
|||
|
||||
// make sure we don't have too many
|
||||
// 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();
|
||||
if (!p) break;
|
||||
|
@ -778,18 +808,23 @@ namespace libtorrent
|
|||
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
|
||||
// TODO: This rotation should happen
|
||||
// far less frequent than this!
|
||||
assert(m_num_unchoked <= m_torrent->num_peers());
|
||||
peer* p = find_choke_candidate();
|
||||
peer* p = find_unchoke_candidate();
|
||||
if (p)
|
||||
{
|
||||
assert(!p->connection->is_choked());
|
||||
p->connection->send_choke();
|
||||
--m_num_unchoked;
|
||||
unchoke_one_peer();
|
||||
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
|
||||
for (std::vector<peer>::iterator i = m_peers.begin();
|
||||
i != m_peers.end();
|
||||
++i)
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
if (i->connection == 0) continue;
|
||||
// if we're not interested, we will not become interested
|
||||
|
@ -1067,6 +1101,17 @@ namespace libtorrent
|
|||
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()
|
||||
{
|
||||
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
|
||||
void policy::connection_closed(const peer_connection& c)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
bool unchoked = false;
|
||||
|
||||
std::vector<peer>::iterator i = std::find_if(
|
||||
|
@ -1181,7 +1224,6 @@ namespace libtorrent
|
|||
void policy::check_invariant() const
|
||||
{
|
||||
if (m_torrent->is_aborted()) return;
|
||||
// assert(m_torrent->m_uploads_quota.given >= 2);
|
||||
int actual_unchoked = 0;
|
||||
for (std::vector<peer>::const_iterator i = m_peers.begin();
|
||||
i != m_peers.end(); ++i)
|
||||
|
@ -1234,3 +1276,4 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue