forked from premiere/premiere-libtorrent
factor out duplicate code in choker
This commit is contained in:
parent
69485558ef
commit
28d123ef23
117
src/choker.cpp
117
src/choker.cpp
|
@ -44,27 +44,34 @@ namespace libtorrent {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// return true if 'lhs' peer should be preferred to be unchoke over 'rhs'
|
int compare_peers(peer_connection const* lhs, peer_connection const* rhs)
|
||||||
bool unchoke_compare_rr(peer_connection const* lhs
|
|
||||||
, peer_connection const* rhs, int pieces)
|
|
||||||
{
|
{
|
||||||
// if one peer belongs to a higher priority torrent than the other one
|
// if one peer belongs to a higher priority torrent than the other one
|
||||||
// that one should be unchoked.
|
// that one should be unchoked.
|
||||||
std::shared_ptr<torrent> t1 = lhs->associated_torrent().lock();
|
std::shared_ptr<torrent> const t1 = lhs->associated_torrent().lock();
|
||||||
|
std::shared_ptr<torrent> const t2 = rhs->associated_torrent().lock();
|
||||||
TORRENT_ASSERT(t1);
|
TORRENT_ASSERT(t1);
|
||||||
std::shared_ptr<torrent> t2 = rhs->associated_torrent().lock();
|
|
||||||
TORRENT_ASSERT(t2);
|
TORRENT_ASSERT(t2);
|
||||||
|
|
||||||
int const prio1 = lhs->get_priority(peer_connection::upload_channel);
|
int const prio1 = lhs->get_priority(peer_connection::upload_channel);
|
||||||
int const prio2 = rhs->get_priority(peer_connection::upload_channel);
|
int const prio2 = rhs->get_priority(peer_connection::upload_channel);
|
||||||
|
|
||||||
if (prio1 != prio2) return prio1 > prio2;
|
if (prio1 != prio2) return prio1 > prio2 ? 1 : -1;
|
||||||
|
|
||||||
// compare how many bytes they've sent us
|
// compare how many bytes they've sent us
|
||||||
std::int64_t const d1 = lhs->downloaded_in_last_round();
|
std::int64_t const c1 = lhs->downloaded_in_last_round();
|
||||||
std::int64_t const d2 = rhs->downloaded_in_last_round();
|
std::int64_t const c2 = rhs->downloaded_in_last_round();
|
||||||
|
|
||||||
if (d1 != d2) return d1 > d2;
|
if (c1 != c2) return c1 > c2 ? 1 : -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if 'lhs' peer should be preferred to be unchoke over 'rhs'
|
||||||
|
bool unchoke_compare_rr(peer_connection const* lhs
|
||||||
|
, peer_connection const* rhs, int pieces)
|
||||||
|
{
|
||||||
|
int const cmp = compare_peers(lhs, rhs);
|
||||||
|
if (cmp != 0) return cmp > 0;
|
||||||
|
|
||||||
// when seeding, rotate which peer is unchoked in a round-robin fasion
|
// when seeding, rotate which peer is unchoked in a round-robin fasion
|
||||||
|
|
||||||
|
@ -78,6 +85,9 @@ namespace libtorrent {
|
||||||
// peers that are unchoked, but have sent more than one quota
|
// peers that are unchoked, but have sent more than one quota
|
||||||
// since they were unchoked, they get de-prioritized.
|
// since they were unchoked, they get de-prioritized.
|
||||||
|
|
||||||
|
std::shared_ptr<torrent> const t1 = lhs->associated_torrent().lock();
|
||||||
|
std::shared_ptr<torrent> const t2 = rhs->associated_torrent().lock();
|
||||||
|
|
||||||
// if a peer is already unchoked, the number of bytes sent since it was unchoked
|
// if a peer is already unchoked, the number of bytes sent since it was unchoked
|
||||||
// is greater than the send quanta, and it has been unchoked for at least one minute
|
// is greater than the send quanta, and it has been unchoked for at least one minute
|
||||||
// then it's done with its upload slot, and we can de-prioritize it
|
// then it's done with its upload slot, and we can de-prioritize it
|
||||||
|
@ -116,33 +126,14 @@ namespace libtorrent {
|
||||||
bool unchoke_compare_fastest_upload(peer_connection const* lhs
|
bool unchoke_compare_fastest_upload(peer_connection const* lhs
|
||||||
, peer_connection const* rhs)
|
, peer_connection const* rhs)
|
||||||
{
|
{
|
||||||
// if one peer belongs to a higher priority torrent than the other one
|
int const cmp = compare_peers(lhs, rhs);
|
||||||
// that one should be unchoked.
|
if (cmp != 0) return cmp > 0;
|
||||||
std::shared_ptr<torrent> t1 = lhs->associated_torrent().lock();
|
|
||||||
TORRENT_ASSERT(t1);
|
|
||||||
std::shared_ptr<torrent> t2 = rhs->associated_torrent().lock();
|
|
||||||
TORRENT_ASSERT(t2);
|
|
||||||
|
|
||||||
int prio1 = lhs->get_priority(peer_connection::upload_channel);
|
|
||||||
int prio2 = rhs->get_priority(peer_connection::upload_channel);
|
|
||||||
|
|
||||||
if (prio1 != prio2)
|
|
||||||
return prio1 > prio2;
|
|
||||||
|
|
||||||
// compare how many bytes they've sent us
|
|
||||||
std::int64_t c1;
|
|
||||||
std::int64_t c2;
|
|
||||||
c1 = lhs->downloaded_in_last_round();
|
|
||||||
c2 = rhs->downloaded_in_last_round();
|
|
||||||
|
|
||||||
if (c1 != c2) return c1 > c2;
|
|
||||||
|
|
||||||
// when seeding, prefer the peer we're uploading the fastest to
|
// when seeding, prefer the peer we're uploading the fastest to
|
||||||
c1 = lhs->uploaded_in_last_round();
|
std::int64_t const c1 = lhs->uploaded_in_last_round();
|
||||||
c2 = rhs->uploaded_in_last_round();
|
std::int64_t const c2 = rhs->uploaded_in_last_round();
|
||||||
|
|
||||||
if (c1 > c2) return true;
|
if (c1 != c2) return c1 > c2;
|
||||||
if (c2 > c1) return false;
|
|
||||||
|
|
||||||
// prioritize the one that has waited the longest to be unchoked
|
// prioritize the one that has waited the longest to be unchoked
|
||||||
// the round-robin unchoker relies on this logic. Don't change it
|
// the round-robin unchoker relies on this logic. Don't change it
|
||||||
|
@ -154,26 +145,11 @@ namespace libtorrent {
|
||||||
bool unchoke_compare_anti_leech(peer_connection const* lhs
|
bool unchoke_compare_anti_leech(peer_connection const* lhs
|
||||||
, peer_connection const* rhs)
|
, peer_connection const* rhs)
|
||||||
{
|
{
|
||||||
// if one peer belongs to a higher priority torrent than the other one
|
int const cmp = compare_peers(lhs, rhs);
|
||||||
// that one should be unchoked.
|
if (cmp != 0) return cmp > 0;
|
||||||
std::shared_ptr<torrent> t1 = lhs->associated_torrent().lock();
|
|
||||||
TORRENT_ASSERT(t1);
|
|
||||||
std::shared_ptr<torrent> t2 = rhs->associated_torrent().lock();
|
|
||||||
TORRENT_ASSERT(t2);
|
|
||||||
|
|
||||||
int prio1 = lhs->get_priority(peer_connection::upload_channel);
|
std::shared_ptr<torrent> const t1 = lhs->associated_torrent().lock();
|
||||||
int prio2 = rhs->get_priority(peer_connection::upload_channel);
|
std::shared_ptr<torrent> const t2 = rhs->associated_torrent().lock();
|
||||||
|
|
||||||
if (prio1 != prio2)
|
|
||||||
return prio1 > prio2;
|
|
||||||
|
|
||||||
// compare how many bytes they've sent us
|
|
||||||
std::int64_t c1;
|
|
||||||
std::int64_t c2;
|
|
||||||
c1 = lhs->downloaded_in_last_round();
|
|
||||||
c2 = rhs->downloaded_in_last_round();
|
|
||||||
|
|
||||||
if (c1 != c2) return c1 > c2;
|
|
||||||
|
|
||||||
// the anti-leech seeding algorithm is based on the paper "Improving
|
// the anti-leech seeding algorithm is based on the paper "Improving
|
||||||
// BitTorrent: A Simple Approach" from Chow et. al. and ranks peers based
|
// BitTorrent: A Simple Approach" from Chow et. al. and ranks peers based
|
||||||
|
@ -195,14 +171,14 @@ namespace libtorrent {
|
||||||
// | V |
|
// | V |
|
||||||
// +---------------------------+
|
// +---------------------------+
|
||||||
// 0% num have pieces 100%
|
// 0% num have pieces 100%
|
||||||
int t1_total = t1->torrent_file().num_pieces();
|
int const t1_total = t1->torrent_file().num_pieces();
|
||||||
int t2_total = t2->torrent_file().num_pieces();
|
int const t2_total = t2->torrent_file().num_pieces();
|
||||||
int score1 = (lhs->num_have_pieces() < t1_total / 2
|
int const score1 = (lhs->num_have_pieces() < t1_total / 2
|
||||||
? t1_total - lhs->num_have_pieces() : lhs->num_have_pieces()) * 1000 / t1_total;
|
? t1_total - lhs->num_have_pieces() : lhs->num_have_pieces()) * 1000 / t1_total;
|
||||||
int score2 = (rhs->num_have_pieces() < t2_total / 2
|
int const score2 = (rhs->num_have_pieces() < t2_total / 2
|
||||||
? t2_total - rhs->num_have_pieces() : rhs->num_have_pieces()) * 1000 / t2_total;
|
? t2_total - rhs->num_have_pieces() : rhs->num_have_pieces()) * 1000 / t2_total;
|
||||||
if (score1 > score2) return true;
|
|
||||||
if (score2 > score1) return false;
|
if (score1 != score2) return score1 > score2;
|
||||||
|
|
||||||
// prioritize the one that has waited the longest to be unchoked
|
// prioritize the one that has waited the longest to be unchoked
|
||||||
// the round-robin unchoker relies on this logic. Don't change it
|
// the round-robin unchoker relies on this logic. Don't change it
|
||||||
|
@ -213,15 +189,11 @@ namespace libtorrent {
|
||||||
bool upload_rate_compare(peer_connection const* lhs
|
bool upload_rate_compare(peer_connection const* lhs
|
||||||
, peer_connection const* rhs)
|
, peer_connection const* rhs)
|
||||||
{
|
{
|
||||||
std::int64_t c1;
|
|
||||||
std::int64_t c2;
|
|
||||||
|
|
||||||
c1 = lhs->uploaded_in_last_round();
|
|
||||||
c2 = rhs->uploaded_in_last_round();
|
|
||||||
|
|
||||||
// take torrent priority into account
|
// take torrent priority into account
|
||||||
c1 *= lhs->get_priority(peer_connection::upload_channel);
|
std::int64_t const c1 = lhs->uploaded_in_last_round()
|
||||||
c2 *= rhs->get_priority(peer_connection::upload_channel);
|
* lhs->get_priority(peer_connection::upload_channel);
|
||||||
|
std::int64_t const c2 = rhs->uploaded_in_last_round()
|
||||||
|
* rhs->get_priority(peer_connection::upload_channel);
|
||||||
|
|
||||||
return c1 > c2;
|
return c1 > c2;
|
||||||
}
|
}
|
||||||
|
@ -229,14 +201,12 @@ namespace libtorrent {
|
||||||
bool bittyrant_unchoke_compare(peer_connection const* lhs
|
bool bittyrant_unchoke_compare(peer_connection const* lhs
|
||||||
, peer_connection const* rhs)
|
, peer_connection const* rhs)
|
||||||
{
|
{
|
||||||
std::int64_t d1, d2, u1, u2;
|
|
||||||
|
|
||||||
// first compare how many bytes they've sent us
|
// first compare how many bytes they've sent us
|
||||||
d1 = lhs->downloaded_in_last_round();
|
std::int64_t d1 = lhs->downloaded_in_last_round();
|
||||||
d2 = rhs->downloaded_in_last_round();
|
std::int64_t d2 = rhs->downloaded_in_last_round();
|
||||||
// divided by the number of bytes we've sent them
|
// divided by the number of bytes we've sent them
|
||||||
u1 = lhs->uploaded_in_last_round();
|
std::int64_t const u1 = lhs->uploaded_in_last_round();
|
||||||
u2 = rhs->uploaded_in_last_round();
|
std::int64_t const u2 = rhs->uploaded_in_last_round();
|
||||||
|
|
||||||
// take torrent priority into account
|
// take torrent priority into account
|
||||||
d1 *= lhs->get_priority(peer_connection::upload_channel);
|
d1 *= lhs->get_priority(peer_connection::upload_channel);
|
||||||
|
@ -244,8 +214,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
d1 = d1 * 1000 / std::max(std::int64_t(1), u1);
|
d1 = d1 * 1000 / std::max(std::int64_t(1), u1);
|
||||||
d2 = d2 * 1000 / std::max(std::int64_t(1), u2);
|
d2 = d2 * 1000 / std::max(std::int64_t(1), u2);
|
||||||
if (d1 > d2) return true;
|
if (d1 != d2) return d1 > d2;
|
||||||
if (d1 < d2) return false;
|
|
||||||
|
|
||||||
// if both peers are still in their send quota or not in their send quota
|
// if both peers are still in their send quota or not in their send quota
|
||||||
// prioritize the one that has waited the longest to be unchoked
|
// prioritize the one that has waited the longest to be unchoked
|
||||||
|
|
Loading…
Reference in New Issue