1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-21 23:32:35 +00:00

feat: configurable client reqq (#7030)

* chore: housekeeping

* refactor: raise client reqq value

* feat: allow configuring client reqq value

* feat: expose reqq config in RPC

* test: add new key

* code review: distinguish client vs peer

* docs: fix new config name

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
Yat Ho 2024-08-24 10:46:37 +08:00 committed by GitHub
parent b0a6bf964c
commit 62240393ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 39 additions and 14 deletions

View file

@ -101,6 +101,7 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
* **peer-limit-global:** Number (default = 200)
* **peer-limit-per-torrent:** Number (default = 50)
* **peer-socket-tos:** String (default = "le") Set the [DiffServ](https://en.wikipedia.org/wiki/Differentiated_services) parameter for outgoing packets. Allowed values are lowercase DSCP names. See the `tr_tos_t` class from `libtransmission/net.h` for the exact list of possible values.
* **reqq:** Number (default = 2000) The number of outstanding block requests a peer is allowed to queue in the client. The higher this number, the higher the max possible upload speed towards each peer.
#### Peer Port
* **peer-port:** Number (default = 51413)

View file

@ -554,6 +554,7 @@ Response arguments: `path`, `name`, and `id`, holding the torrent ID integer
| `queue-stalled-enabled` | boolean | whether or not to consider idle torrents as stalled
| `queue-stalled-minutes` | number | torrents that are idle for N minuets aren't counted toward seed-queue-size or download-queue-size
| `rename-partial-files` | boolean | true means append `.part` to incomplete files
| `reqq` | number | the number of outstanding block requests a peer is allowed to queue in the client
| `rpc-version-minimum` | number | the minimum RPC API version supported
| `rpc-version-semver` | string | the current RPC API version in a [semver](https://semver.org)-compatible string
| `rpc-version` | number | the current RPC API version

View file

@ -905,7 +905,7 @@ EXIT:
// ---
// number of bad pieces a peer is allowed to send before we ban them
static auto constexpr MaxBadPiecesPerPeer = 5;
static auto constexpr MaxBadPiecesPerPeer = 5U;
// how long we'll let requests we've made linger before we cancel them
static auto constexpr RequestTtlSecs = 90;

View file

@ -178,7 +178,7 @@ auto constexpr KeepaliveIntervalSecs = time_t{ 100 };
auto constexpr MetadataReqQ = size_t{ 64U };
auto constexpr ReqQ = 512;
auto constexpr PeerReqQDefault = 500U;
// when we're making requests from another peer,
// batch them together to send enough requests to
@ -571,6 +571,11 @@ private:
void update_block_requests();
[[nodiscard]] constexpr auto client_reqq() const noexcept
{
return session->reqq();
}
// ---
[[nodiscard]] std::optional<int64_t> pop_next_metadata_request()
@ -702,7 +707,7 @@ private:
// if the peer supports the Extension Protocol in BEP 10 and
// supplied a reqq argument, it's stored here.
std::optional<size_t> reqq_;
std::optional<size_t> peer_reqq_;
std::unique_ptr<libtransmission::Timer> pex_timer_;
@ -1131,9 +1136,8 @@ void tr_peerMsgsImpl::send_ltep_handshake()
// https://www.bittorrent.org/beps/bep_0010.html
// An integer, the number of outstanding request messages this
// client supports without dropping any. The default in in
// libtorrent is 250.
tr_variantDictAddInt(&val, TR_KEY_reqq, ReqQ);
// client supports without dropping any.
tr_variantDictAddInt(&val, TR_KEY_reqq, client_reqq());
// https://www.bittorrent.org/beps/bep_0010.html
// A string containing the compact representation of the ip address this peer sees
@ -1289,7 +1293,7 @@ void tr_peerMsgsImpl::parse_ltep_handshake(MessageReader& payload)
/* get peer's maximum request queue size */
if (auto reqq_in = int64_t{}; tr_variantDictFindInt(&*var, TR_KEY_reqq, &reqq_in))
{
reqq_ = reqq_in;
peer_reqq_ = reqq_in;
}
}
@ -1994,7 +1998,7 @@ bool tr_peerMsgsImpl::is_valid_request(peer_request const& req) const
return false;
}
if (std::size(peer_requested_) >= ReqQ)
if (std::size(peer_requested_) >= client_reqq())
{
logtrace(this, "rejecting request ... reqq is full");
return false;
@ -2045,7 +2049,7 @@ size_t tr_peerMsgsImpl::max_available_reqs() const
static auto constexpr Floor = size_t{ 32 };
static size_t constexpr Seconds = RequestBufSecs;
size_t const estimated_blocks_in_period = (rate.base_quantity() * Seconds) / tr_block_info::BlockSize;
auto const ceil = reqq_.value_or(250);
auto const ceil = peer_reqq_.value_or(PeerReqQDefault);
return std::clamp(estimated_blocks_in_period, Floor, ceil);
}

View file

@ -1695,6 +1695,11 @@ char const* sessionSet(tr_session* session, tr_variant::Map const& args_in, tr_v
tr_sessionSetPeerLimitPerTorrent(session, *val);
}
if (auto const val = args_in.value_if<int64_t>(TR_KEY_reqq); val && val > 0)
{
session->set_reqq(*val);
}
if (auto const val = args_in.value_if<bool>(TR_KEY_pex_enabled))
{
tr_sessionSetPexEnabled(session, *val);
@ -1955,6 +1960,7 @@ char const* sessionStats(tr_session* session, tr_variant::Map const& /*args_in*/
case TR_KEY_queue_stalled_enabled: return session.queueStalledEnabled();
case TR_KEY_queue_stalled_minutes: return session.queueStalledMinutes();
case TR_KEY_rename_partial_files: return session.isIncompleteFileNamingEnabled();
case TR_KEY_reqq: return session.reqq();
case TR_KEY_rpc_version: return RpcVersion;
case TR_KEY_rpc_version_minimum: return RpcVersionMin;
case TR_KEY_rpc_version_semver: return RpcVersionSemver;

View file

@ -398,6 +398,7 @@ public:
size_t peer_limit_global = TR_DEFAULT_PEER_LIMIT_GLOBAL;
size_t peer_limit_per_torrent = TR_DEFAULT_PEER_LIMIT_TORRENT;
size_t queue_stalled_minutes = 30U;
size_t reqq = 2000U;
size_t seed_queue_size = 10U;
size_t speed_limit_down = 100U;
size_t speed_limit_up = 100U;
@ -465,6 +466,7 @@ public:
{ TR_KEY_ratio_limit, &ratio_limit },
{ TR_KEY_ratio_limit_enabled, &ratio_limit_enabled },
{ TR_KEY_rename_partial_files, &is_incomplete_file_naming_enabled },
{ TR_KEY_reqq, &reqq },
{ TR_KEY_scrape_paused_torrents_enabled, &should_scrape_paused_torrents },
{ TR_KEY_script_torrent_added_enabled, &script_torrent_added_enabled },
{ TR_KEY_script_torrent_added_filename, &script_torrent_added_filename },
@ -693,6 +695,16 @@ public:
return settings().peer_limit_per_torrent;
}
[[nodiscard]] constexpr auto reqq() const noexcept
{
return settings().reqq;
}
constexpr void set_reqq(size_t reqq) noexcept
{
settings_.reqq = reqq;
}
// bandwidth
[[nodiscard]] tr_bandwidth& getBandwidthGroup(std::string_view name);

View file

@ -168,7 +168,7 @@ TEST_F(RpcTest, sessionGet)
EXPECT_TRUE(tr_variantDictFindDict(&response, TR_KEY_arguments, &args));
// what we expected
auto const expected_keys = std::array<tr_quark, 59>{
static auto constexpr ExpectedKeys = std::array{
TR_KEY_alt_speed_down,
TR_KEY_alt_speed_enabled,
TR_KEY_alt_speed_time_begin,
@ -204,6 +204,7 @@ TEST_F(RpcTest, sessionGet)
TR_KEY_queue_stalled_enabled,
TR_KEY_queue_stalled_minutes,
TR_KEY_rename_partial_files,
TR_KEY_reqq,
TR_KEY_rpc_version,
TR_KEY_rpc_version_minimum,
TR_KEY_rpc_version_semver,
@ -242,8 +243,8 @@ TEST_F(RpcTest, sessionGet)
auto missing_keys = std::vector<tr_quark>{};
std::set_difference(
std::begin(expected_keys),
std::end(expected_keys),
std::begin(ExpectedKeys),
std::end(ExpectedKeys),
std::begin(actual_keys),
std::end(actual_keys),
std::inserter(missing_keys, std::begin(missing_keys)));
@ -253,8 +254,8 @@ TEST_F(RpcTest, sessionGet)
std::set_difference(
std::begin(actual_keys),
std::end(actual_keys),
std::begin(expected_keys),
std::end(expected_keys),
std::begin(ExpectedKeys),
std::end(ExpectedKeys),
std::inserter(unexpected_keys, std::begin(unexpected_keys)));
EXPECT_EQ(decltype(unexpected_keys){}, unexpected_keys);