diff --git a/src/choker.cpp b/src/choker.cpp index b21a7cb46..bcaff2c6c 100644 --- a/src/choker.cpp +++ b/src/choker.cpp @@ -42,29 +42,36 @@ using namespace std::placeholders; namespace libtorrent { - namespace { +namespace { - // 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 compare_peers(peer_connection const* lhs, peer_connection const* rhs) { // if one peer belongs to a higher priority torrent than the other one // that one should be unchoked. - std::shared_ptr t1 = lhs->associated_torrent().lock(); + std::shared_ptr const t1 = lhs->associated_torrent().lock(); + std::shared_ptr const t2 = rhs->associated_torrent().lock(); TORRENT_ASSERT(t1); - std::shared_ptr t2 = rhs->associated_torrent().lock(); TORRENT_ASSERT(t2); int const prio1 = lhs->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 - std::int64_t const d1 = lhs->downloaded_in_last_round(); - std::int64_t const d2 = rhs->downloaded_in_last_round(); + std::int64_t const c1 = lhs->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 @@ -78,6 +85,9 @@ namespace libtorrent { // peers that are unchoked, but have sent more than one quota // since they were unchoked, they get de-prioritized. + std::shared_ptr const t1 = lhs->associated_torrent().lock(); + std::shared_ptr const t2 = rhs->associated_torrent().lock(); + // 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 // 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 , peer_connection const* rhs) { - // if one peer belongs to a higher priority torrent than the other one - // that one should be unchoked. - std::shared_ptr t1 = lhs->associated_torrent().lock(); - TORRENT_ASSERT(t1); - std::shared_ptr 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; + int const cmp = compare_peers(lhs, rhs); + if (cmp != 0) return cmp > 0; // when seeding, prefer the peer we're uploading the fastest to - c1 = lhs->uploaded_in_last_round(); - c2 = rhs->uploaded_in_last_round(); + std::int64_t const c1 = lhs->uploaded_in_last_round(); + std::int64_t const c2 = rhs->uploaded_in_last_round(); - if (c1 > c2) return true; - if (c2 > c1) return false; + if (c1 != c2) return c1 > c2; // prioritize the one that has waited the longest to be unchoked // 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 , peer_connection const* rhs) { - // if one peer belongs to a higher priority torrent than the other one - // that one should be unchoked. - std::shared_ptr t1 = lhs->associated_torrent().lock(); - TORRENT_ASSERT(t1); - std::shared_ptr t2 = rhs->associated_torrent().lock(); - TORRENT_ASSERT(t2); + int const cmp = compare_peers(lhs, rhs); + if (cmp != 0) return cmp > 0; - 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; + std::shared_ptr const t1 = lhs->associated_torrent().lock(); + std::shared_ptr const t2 = rhs->associated_torrent().lock(); // the anti-leech seeding algorithm is based on the paper "Improving // BitTorrent: A Simple Approach" from Chow et. al. and ranks peers based @@ -195,14 +171,14 @@ namespace libtorrent { // | V | // +---------------------------+ // 0% num have pieces 100% - int t1_total = t1->torrent_file().num_pieces(); - int t2_total = t2->torrent_file().num_pieces(); - int score1 = (lhs->num_have_pieces() < t1_total / 2 + int const t1_total = t1->torrent_file().num_pieces(); + int const t2_total = t2->torrent_file().num_pieces(); + int const score1 = (lhs->num_have_pieces() < t1_total / 2 ? 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; - 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 // 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 , 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 - c1 *= lhs->get_priority(peer_connection::upload_channel); - c2 *= rhs->get_priority(peer_connection::upload_channel); + std::int64_t const c1 = lhs->uploaded_in_last_round() + * 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; } @@ -229,14 +201,12 @@ namespace libtorrent { bool bittyrant_unchoke_compare(peer_connection const* lhs , peer_connection const* rhs) { - std::int64_t d1, d2, u1, u2; - // first compare how many bytes they've sent us - d1 = lhs->downloaded_in_last_round(); - d2 = rhs->downloaded_in_last_round(); + std::int64_t d1 = lhs->downloaded_in_last_round(); + std::int64_t d2 = rhs->downloaded_in_last_round(); // divided by the number of bytes we've sent them - u1 = lhs->uploaded_in_last_round(); - u2 = rhs->uploaded_in_last_round(); + std::int64_t const u1 = lhs->uploaded_in_last_round(); + std::int64_t const u2 = rhs->uploaded_in_last_round(); // take torrent priority into account d1 *= lhs->get_priority(peer_connection::upload_channel); @@ -244,8 +214,7 @@ namespace libtorrent { d1 = d1 * 1000 / std::max(std::int64_t(1), u1); d2 = d2 * 1000 / std::max(std::int64_t(1), u2); - if (d1 > d2) return true; - if (d1 < d2) return false; + if (d1 != d2) return d1 > d2; // 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