From 5bc4a2089dba56a29d80f3af56bcd68d5849edb1 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 10 Dec 2008 23:07:44 +0000 Subject: [PATCH] fixed seeding choking algorithm to be more fair (proper round robin) --- include/libtorrent/peer_connection.hpp | 1 + include/libtorrent/session_settings.hpp | 7 ++++++- src/peer_connection.cpp | 26 ++++++++++++++++--------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index bb55b2eaf..c7794b860 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -646,6 +646,7 @@ namespace libtorrent // an unchoke cycle, to unchoke peers the more bytes // they sent us size_type m_downloaded_at_last_unchoke; + size_type m_uploaded_at_last_unchoke; #ifndef TORRENT_DISABLE_GEO_IP std::string m_inet_as_name; diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index d103befc2..0f8979643 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -103,7 +103,7 @@ namespace libtorrent , min_reconnect_time(60) , peer_connect_timeout(7) , ignore_limits_on_local_network(true) - , connection_speed(20) + , connection_speed(10) , send_redundant_have(false) , lazy_bitfields(true) , inactivity_timeout(600) @@ -147,6 +147,7 @@ namespace libtorrent , announce_to_all_trackers(false) , prefer_udp_trackers(true) , strict_super_seeding(false) + , seeding_piece_quota(3) {} // this is the user agent that will be sent to the tracker @@ -473,6 +474,10 @@ namespace libtorrent // when set to true, a piece has to have been forwarded // to a third peer before another one is handed out bool strict_super_seeding; + + // the number of pieces to send to each peer when seeding + // before rotating to a new peer + int seeding_piece_quota; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 96cbb3801..06f5826fc 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -78,7 +78,7 @@ namespace libtorrent , m_last_piece(time_now()) , m_last_request(time_now()) , m_last_incoming_request(min_time()) - , m_last_unchoke(min_time()) + , m_last_unchoke(time_now()) , m_last_receive(time_now()) , m_last_sent(time_now()) , m_requested(min_time()) @@ -89,6 +89,7 @@ namespace libtorrent , m_became_uninteresting(time_now()) , m_free_upload(0) , m_downloaded_at_last_unchoke(0) + , m_uploaded_at_last_unchoke(0) , m_disk_recv_buffer(ses, 0) , m_socket(s) , m_remote(endp) @@ -188,7 +189,7 @@ namespace libtorrent , m_last_piece(time_now()) , m_last_request(time_now()) , m_last_incoming_request(min_time()) - , m_last_unchoke(min_time()) + , m_last_unchoke(time_now()) , m_last_receive(time_now()) , m_last_sent(time_now()) , m_requested(min_time()) @@ -199,6 +200,7 @@ namespace libtorrent , m_became_uninteresting(time_now()) , m_free_upload(0) , m_downloaded_at_last_unchoke(0) + , m_uploaded_at_last_unchoke(0) , m_disk_recv_buffer(ses, 0) , m_socket(s) , m_remote(endp) @@ -297,10 +299,8 @@ namespace libtorrent if (c1 < c2) return false; // if they are equal, compare how much we have uploaded - if (m_peer_info) c1 = m_peer_info->total_upload(); - else c1 = m_statistics.total_payload_upload(); - if (rhs.m_peer_info) c2 = rhs.m_peer_info->total_upload(); - else c2 = rhs.m_statistics.total_payload_upload(); + c1 = m_statistics.total_payload_upload() - m_uploaded_at_last_unchoke; + c2 = rhs.m_statistics.total_payload_upload() - rhs.m_uploaded_at_last_unchoke; // in order to not switch back and forth too often, // unchoked peers must be at least one piece ahead @@ -309,10 +309,16 @@ namespace libtorrent TORRENT_ASSERT(t1); boost::shared_ptr t2 = rhs.associated_torrent().lock(); TORRENT_ASSERT(t2); - if (!is_choked()) c1 -= (std::max)(t1->torrent_file().piece_length(), 256 * 1024); - if (!rhs.is_choked()) c2 -= (std::max)(t2->torrent_file().piece_length(), 256 * 1024); + int pieces = m_ses.settings().seeding_piece_quota; + bool c1_done = is_choked() || c1 > (std::max)(t1->torrent_file().piece_length() * pieces, 256 * 1024); + bool c2_done = rhs.is_choked() || c2 > (std::max)(t2->torrent_file().piece_length() * pieces, 256 * 1024); + + if (!c1_done && c2_done) return true; + if (c1_done && !c2_done) return false; - return c1 < c2; + // if both peers have are still in their send quota or not in their send quota + // prioritize the one that has waited the longest to be unchoked + return m_last_unchoke < rhs.m_last_unchoke; } void peer_connection::reset_choke_counters() @@ -2350,6 +2356,8 @@ namespace libtorrent write_unchoke(); m_choked = false; + m_uploaded_at_last_unchoke = m_statistics.total_payload_upload(); + #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " ==> UNCHOKE\n"; #endif