diff --git a/bindings/python/src/session_settings.cpp b/bindings/python/src/session_settings.cpp index 5a5f94043..1a6951dd7 100644 --- a/bindings/python/src/session_settings.cpp +++ b/bindings/python/src/session_settings.cpp @@ -122,6 +122,7 @@ void bind_session_settings() .def_readwrite("decrease_est_reciprocation_rate", &session_settings::decrease_est_reciprocation_rate) .def_readwrite("incoming_starts_queued_torrents", &session_settings::incoming_starts_queued_torrents) .def_readwrite("report_true_downoaded", &session_settings::report_true_downloaded) + .def_readwrite("strict_end_game_mode", &session_settings::strict_end_game_mode) ; enum_("proxy_type") diff --git a/docs/manual.rst b/docs/manual.rst index 942ec0147..5c0753d77 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3773,6 +3773,7 @@ session_settings int decrease_est_reciprocation_rate; bool incoming_starts_queued_torrents; bool report_true_downloaded; + bool strict_end_game_mode; }; ``user_agent`` this is the client identification to the tracker. @@ -4348,6 +4349,15 @@ When ``report_true_downloaded`` is true, the ``&downloaded=`` argument sent to trackers will include redundant downloaded bytes. It defaults to ``false``, which means redundant bytes are not reported to the tracker. +``strict_end_game_mode`` defaults to true, and controls when a block +may be requested twice. If this is ``true``, a block may only be requested +twice when there's ay least one request to every piece that's left to +download in the torrent. This may slow down progress on some pieces +sometimes, but it may also avoid downloading a lot of redundant bytes. +If this is ``false``, libtorrent attempts to use each peer connection +to its max, by always requesting something, even if it means requesting +something that has been requested from another peer already. + pe_settings =========== diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 87173de18..7c2678b79 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -203,6 +203,7 @@ namespace libtorrent , decrease_est_reciprocation_rate(3) , incoming_starts_queued_torrents(false) , report_true_downloaded(false) + , strict_end_game_mode(true) {} // this is the user agent that will be sent to the tracker @@ -769,6 +770,10 @@ namespace libtorrent // including redundant bytes. If set to false, it will not include // any redundany bytes bool report_true_downloaded; + + // if set to true, libtorrent won't request a piece multiple times + // until every piece is requested + bool strict_end_game_mode; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/policy.cpp b/src/policy.cpp index 5fd1352aa..7bd75418b 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -275,6 +275,15 @@ namespace libtorrent return; } + // if the number of pieces we have + the number of pieces + // we're requesting from is less than the number of pieces + // in the torrent, there are still some unrequested pieces + // and we're not strictly speaking in end-game mode yet + if (t.settings().strict_end_game_mode + && p.num_have() + p.get_download_queue().size() + < t.torrent_file().num_pieces()) + return; + // if all blocks has the same number of peers on them // we want to pick a random block std::random_shuffle(busy_pieces.begin(), busy_pieces.end()); @@ -297,7 +306,7 @@ namespace libtorrent // don't re-request from a piece more often than once every 20 seconds // TODO: make configurable - if (now - last_request < seconds(20)) + if (now - last_request < seconds(5)) return; c.add_request(*i, peer_connection::req_busy);