mirror of
https://github.com/transmission/transmission
synced 2024-12-26 01:27:28 +00:00
refactor: add tr_peer.canRequest() (#3408)
This commit is contained in:
parent
513f4bc91b
commit
9dfb3bf3df
3 changed files with 79 additions and 46 deletions
|
@ -89,6 +89,19 @@ public:
|
|||
|
||||
virtual void requestBlocks(tr_block_span_t const* block_spans, size_t n_spans) = 0;
|
||||
|
||||
struct RequestLimit
|
||||
{
|
||||
// How many blocks we could request.
|
||||
size_t max_spans = 0;
|
||||
|
||||
// How many spans those blocks could be in.
|
||||
// This is for webseeds, which make parallel requests.
|
||||
size_t max_blocks = 0;
|
||||
};
|
||||
|
||||
// how many blocks could we request from this peer right now?
|
||||
[[nodiscard]] virtual RequestLimit canRequest() const noexcept = 0;
|
||||
|
||||
tr_session* const session;
|
||||
|
||||
tr_swarm* const swarm;
|
||||
|
|
|
@ -658,7 +658,47 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// how many blocks could we request from this peer right now?
|
||||
[[nodiscard]] RequestLimit canRequest() const noexcept override
|
||||
{
|
||||
auto const max_blocks = maxAvailableReqs();
|
||||
return RequestLimit{ max_blocks, max_blocks };
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] size_t maxAvailableReqs() const
|
||||
{
|
||||
if (torrent->isDone() || !torrent->hasMetainfo() || client_is_choked_ || !client_is_interested_)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the rate limit we should use.
|
||||
// TODO: this needs to consider all the other peers as well...
|
||||
uint64_t const now = tr_time_msec();
|
||||
auto rate_Bps = tr_peerGetPieceSpeed_Bps(this, now, TR_PEER_TO_CLIENT);
|
||||
if (tr_torrentUsesSpeedLimit(torrent, TR_PEER_TO_CLIENT))
|
||||
{
|
||||
rate_Bps = std::min(rate_Bps, torrent->speedLimitBps(TR_PEER_TO_CLIENT));
|
||||
}
|
||||
|
||||
// honor the session limits, if enabled
|
||||
auto irate_Bps = unsigned{};
|
||||
if (tr_torrentUsesSessionLimits(torrent) &&
|
||||
tr_sessionGetActiveSpeedLimit_Bps(torrent->session, TR_PEER_TO_CLIENT, &irate_Bps))
|
||||
{
|
||||
rate_Bps = std::min(rate_Bps, irate_Bps);
|
||||
}
|
||||
|
||||
// use this desired rate to figure out how
|
||||
// many requests we should send to this peer
|
||||
size_t constexpr Floor = 32;
|
||||
size_t constexpr Seconds = RequestBufSecs;
|
||||
size_t const estimated_blocks_in_period = (rate_Bps * Seconds) / tr_block_info::BlockSize;
|
||||
size_t const ceil = reqq ? *reqq : 250;
|
||||
return std::clamp(estimated_blocks_in_period, Floor, ceil);
|
||||
}
|
||||
|
||||
void protocolSendRequest(struct peer_request const& req)
|
||||
{
|
||||
TR_ASSERT(isValidRequest(req));
|
||||
|
@ -2088,40 +2128,7 @@ static ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
|
|||
|
||||
static void updateDesiredRequestCount(tr_peerMsgsImpl* msgs)
|
||||
{
|
||||
tr_torrent const* const torrent = msgs->torrent;
|
||||
|
||||
/* there are lots of reasons we might not want to request any blocks... */
|
||||
if (torrent->isDone() || !torrent->hasMetainfo() || msgs->client_is_choked_ || !msgs->client_is_interested_)
|
||||
{
|
||||
msgs->desired_request_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the rate limit we should use.
|
||||
* TODO: this needs to consider all the other peers as well... */
|
||||
uint64_t const now = tr_time_msec();
|
||||
auto rate_Bps = tr_peerGetPieceSpeed_Bps(msgs, now, TR_PEER_TO_CLIENT);
|
||||
if (tr_torrentUsesSpeedLimit(torrent, TR_PEER_TO_CLIENT))
|
||||
{
|
||||
rate_Bps = std::min(rate_Bps, torrent->speedLimitBps(TR_PEER_TO_CLIENT));
|
||||
}
|
||||
|
||||
/* honor the session limits, if enabled */
|
||||
auto irate_Bps = unsigned{};
|
||||
if (tr_torrentUsesSessionLimits(torrent) &&
|
||||
tr_sessionGetActiveSpeedLimit_Bps(torrent->session, TR_PEER_TO_CLIENT, &irate_Bps))
|
||||
{
|
||||
rate_Bps = std::min(rate_Bps, irate_Bps);
|
||||
}
|
||||
|
||||
/* use this desired rate to figure out how
|
||||
* many requests we should send to this peer */
|
||||
size_t constexpr Floor = 32;
|
||||
size_t constexpr Seconds = RequestBufSecs;
|
||||
size_t const estimated_blocks_in_period = (rate_Bps * Seconds) / tr_block_info::BlockSize;
|
||||
size_t const ceil = msgs->reqq ? *msgs->reqq : 250;
|
||||
msgs->desired_request_count = std::clamp(estimated_blocks_in_period, Floor, ceil);
|
||||
}
|
||||
msgs->desired_request_count = msgs->canRequest().max_blocks;
|
||||
}
|
||||
|
||||
static void updateMetadataRequests(tr_peerMsgsImpl* msgs, time_t now)
|
||||
|
|
|
@ -290,6 +290,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] RequestLimit canRequest() const noexcept override
|
||||
{
|
||||
auto const n_slots = connection_limiter.slotsAvailable();
|
||||
if (n_slots == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto* const tor = getTorrent(); tor == nullptr || !tor->isRunning || tor->isDone())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// Prefer to request large, contiguous chunks from webseeds.
|
||||
// The actual value of '64' is arbitrary here;
|
||||
// we could probably be smarter about this.
|
||||
auto constexpr PreferredBlocksPerTask = size_t{ 64 };
|
||||
return { n_slots, n_slots * PreferredBlocksPerTask };
|
||||
}
|
||||
|
||||
tr_torrent_id_t const torrent_id;
|
||||
std::string const base_url;
|
||||
tr_peer_callback const callback;
|
||||
|
@ -435,14 +455,8 @@ void onBufferGotData(evbuffer* /*buf*/, evbuffer_cb_info const* info, void* vtas
|
|||
|
||||
void on_idle(tr_webseed* webseed)
|
||||
{
|
||||
auto const slots_available = webseed->connection_limiter.slotsAvailable();
|
||||
if (slots_available == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* const tor = webseed->getTorrent();
|
||||
if (tor == nullptr || !tor->isRunning || tor->isDone())
|
||||
auto const [max_spans, max_blocks] = webseed->canRequest();
|
||||
if (max_spans == 0 || max_blocks == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -450,11 +464,10 @@ void on_idle(tr_webseed* webseed)
|
|||
// Prefer to request large, contiguous chunks from webseeds.
|
||||
// The actual value of '64' is arbitrary here; we could probably
|
||||
// be smarter about this.
|
||||
auto constexpr PreferredBlocksPerTask = size_t{ 64 };
|
||||
auto spans = tr_peerMgrGetNextRequests(tor, webseed, slots_available * PreferredBlocksPerTask);
|
||||
if (std::size(spans) > slots_available)
|
||||
auto spans = tr_peerMgrGetNextRequests(webseed->getTorrent(), webseed, max_blocks);
|
||||
if (std::size(spans) > max_spans)
|
||||
{
|
||||
spans.resize(slots_available);
|
||||
spans.resize(max_spans);
|
||||
}
|
||||
webseed->requestBlocks(std::data(spans), std::size(spans));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue