mirror of
https://github.com/transmission/transmission
synced 2024-12-21 23:32:35 +00:00
refactor: remove prefetch (#6332)
This commit is contained in:
parent
0c51eb36d7
commit
3cd66899fe
14 changed files with 15 additions and 184 deletions
|
@ -81,7 +81,6 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
|
|||
* **message-level:** Number (0 = None, 1 = Critical, 2 = Error, 3 = Warn, 4 = Info, 5 = Debug, 6 = Trace; default = 2) Set verbosity of Transmission's log messages.
|
||||
* **pex-enabled:** Boolean (default = true) Enable [Peer Exchange (PEX)](https://en.wikipedia.org/wiki/Peer_exchange).
|
||||
* **pidfile:** String Path to file in which daemon PID will be stored (transmission-daemon only)
|
||||
* **prefetch-enabled:** Boolean (default = true). When enabled, Transmission will hint to the OS which piece data it's about to read from disk in order to satisfy requests from peers. On Linux, this is done by passing `POSIX_FADV_WILLNEED` to [posix_fadvise()](https://www.kernel.org/doc/man-pages/online/pages/man2/posix_fadvise.2.html). On macOS, this is done by passing `F_RDADVISE` to [fcntl()](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html).
|
||||
* **scrape-paused-torrents-enabled:** Boolean (default = true)
|
||||
* **script-torrent-added-enabled:** Boolean (default = false) Run a script when a torrent is added to Transmission. Environmental variables are passed in as detailed on the [Scripts](./Scripts.md) page
|
||||
* **script-torrent-added-filename:** String (default = "") Path to script.
|
||||
|
|
|
@ -185,16 +185,6 @@ int Cache::read_block(tr_torrent const& tor, tr_block_info::Location const& loc,
|
|||
return tr_ioRead(tor, loc, len, setme);
|
||||
}
|
||||
|
||||
int Cache::prefetch_block(tr_torrent const& tor, tr_block_info::Location const& loc, size_t len)
|
||||
{
|
||||
if (auto const iter = get_block(tor, loc); iter != std::end(blocks_))
|
||||
{
|
||||
return {}; // already have it
|
||||
}
|
||||
|
||||
return tr_ioPrefetch(tor, loc, len);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
int Cache::flush_span(CIter const begin, CIter const end)
|
||||
|
|
|
@ -39,7 +39,6 @@ public:
|
|||
int write_block(tr_torrent_id_t tor, tr_block_index_t block, std::unique_ptr<BlockData> writeme);
|
||||
|
||||
int read_block(tr_torrent const& tor, tr_block_info::Location const& loc, size_t len, uint8_t* setme);
|
||||
int prefetch_block(tr_torrent const& tor, tr_block_info::Location const& loc, size_t len);
|
||||
int flush_torrent(tr_torrent_id_t tor_id);
|
||||
int flush_file(tr_torrent const& tor, tr_file_index_t file);
|
||||
|
||||
|
|
|
@ -842,58 +842,6 @@ bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, tr_error* error)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_file_advise(
|
||||
[[maybe_unused]] tr_sys_file_t handle,
|
||||
[[maybe_unused]] uint64_t offset,
|
||||
[[maybe_unused]] uint64_t size,
|
||||
[[maybe_unused]] tr_sys_file_advice_t advice,
|
||||
[[maybe_unused]] tr_error* error)
|
||||
{
|
||||
TR_ASSERT(handle != TR_BAD_SYS_FILE);
|
||||
TR_ASSERT(size > 0);
|
||||
TR_ASSERT(advice == TR_SYS_FILE_ADVICE_WILL_NEED || advice == TR_SYS_FILE_ADVICE_DONT_NEED);
|
||||
|
||||
bool ret = true;
|
||||
|
||||
#if defined(HAVE_POSIX_FADVISE)
|
||||
|
||||
int const native_advice = advice == TR_SYS_FILE_ADVICE_WILL_NEED ?
|
||||
POSIX_FADV_WILLNEED :
|
||||
(advice == TR_SYS_FILE_ADVICE_DONT_NEED ? POSIX_FADV_DONTNEED : POSIX_FADV_NORMAL);
|
||||
|
||||
TR_ASSERT(native_advice != POSIX_FADV_NORMAL);
|
||||
|
||||
if (int const code = posix_fadvise(handle, offset, size, native_advice); code != 0)
|
||||
{
|
||||
if (error != nullptr)
|
||||
{
|
||||
error->set_from_errno(errno);
|
||||
}
|
||||
|
||||
ret = false;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
if (advice == TR_SYS_FILE_ADVICE_WILL_NEED)
|
||||
{
|
||||
auto radv = radvisory{};
|
||||
radv.ra_offset = offset;
|
||||
radv.ra_count = size;
|
||||
|
||||
ret = fcntl(handle, F_RDADVISE, &radv) != -1;
|
||||
|
||||
if (error != nullptr && !ret)
|
||||
{
|
||||
error->set_from_errno(errno);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace preallocate_helpers
|
||||
|
|
|
@ -1127,24 +1127,6 @@ bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, tr_error* error)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_file_advise(
|
||||
[[maybe_unused]] tr_sys_file_t handle,
|
||||
uint64_t /*offset*/,
|
||||
[[maybe_unused]] uint64_t size,
|
||||
[[maybe_unused]] tr_sys_file_advice_t advice,
|
||||
tr_error* /*error*/)
|
||||
{
|
||||
TR_ASSERT(handle != TR_BAD_SYS_FILE);
|
||||
TR_ASSERT(size > 0);
|
||||
TR_ASSERT(advice == TR_SYS_FILE_ADVICE_WILL_NEED || advice == TR_SYS_FILE_ADVICE_DONT_NEED);
|
||||
|
||||
bool ret = true;
|
||||
|
||||
/* ??? */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_file_preallocate(tr_sys_file_t handle, uint64_t size, int flags, tr_error* error)
|
||||
{
|
||||
TR_ASSERT(handle != TR_BAD_SYS_FILE);
|
||||
|
|
|
@ -75,12 +75,6 @@ enum tr_sys_path_get_info_flags_t
|
|||
TR_SYS_PATH_NO_FOLLOW = (1 << 0)
|
||||
};
|
||||
|
||||
enum tr_sys_file_advice_t
|
||||
{
|
||||
TR_SYS_FILE_ADVICE_WILL_NEED,
|
||||
TR_SYS_FILE_ADVICE_DONT_NEED
|
||||
};
|
||||
|
||||
enum tr_sys_file_preallocate_flags_t
|
||||
{
|
||||
TR_SYS_FILE_PREALLOC_SPARSE = (1 << 0)
|
||||
|
@ -469,24 +463,6 @@ bool tr_sys_file_flush_possible(tr_sys_file_t handle, tr_error* error = nullptr)
|
|||
*/
|
||||
bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, tr_error* error = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Tell system to prefetch or discard some part of file which is [not] to be read soon.
|
||||
*
|
||||
* @param[in] handle Valid file descriptor.
|
||||
* @param[in] offset Offset in file to prefetch from.
|
||||
* @param[in] size Number of bytes to prefetch.
|
||||
* @param[out] error Pointer to error object. Optional, pass `nullptr` if you
|
||||
* are not interested in error details.
|
||||
*
|
||||
* @return `True` on success, `false` otherwise (with `error` set accordingly).
|
||||
*/
|
||||
bool tr_sys_file_advise(
|
||||
tr_sys_file_t handle,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
tr_sys_file_advice_t advice,
|
||||
tr_error* error = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Preallocate file to specified size in full or sparse mode.
|
||||
*
|
||||
|
|
|
@ -123,18 +123,11 @@ bool write_entire_buf(tr_sys_file_t const fd, uint64_t file_offset, uint8_t cons
|
|||
return {};
|
||||
}
|
||||
|
||||
enum class IoMode
|
||||
{
|
||||
Read,
|
||||
Prefetch,
|
||||
Write
|
||||
};
|
||||
|
||||
void read_or_write_bytes(
|
||||
tr_session& session,
|
||||
tr_open_files& open_files,
|
||||
tr_torrent const& tor,
|
||||
IoMode const io_mode,
|
||||
bool const writable,
|
||||
tr_file_index_t const file_index,
|
||||
uint64_t const file_offset,
|
||||
uint8_t* const buf,
|
||||
|
@ -150,7 +143,6 @@ void read_or_write_bytes(
|
|||
return;
|
||||
}
|
||||
|
||||
auto const writable = io_mode == IoMode::Write;
|
||||
auto const fd = get_fd(session, open_files, tor, writable, file_index, error);
|
||||
if (!fd || error)
|
||||
{
|
||||
|
@ -158,21 +150,15 @@ void read_or_write_bytes(
|
|||
}
|
||||
|
||||
auto fmtstr = ""sv;
|
||||
switch (io_mode)
|
||||
if (writable)
|
||||
{
|
||||
case IoMode::Prefetch:
|
||||
tr_sys_file_advise(*fd, file_offset, buflen, TR_SYS_FILE_ADVICE_WILL_NEED);
|
||||
break;
|
||||
|
||||
case IoMode::Write:
|
||||
fmtstr = _("Couldn't save '{path}': {error} ({error_code})");
|
||||
write_entire_buf(*fd, file_offset, buf, buflen, error);
|
||||
break;
|
||||
|
||||
case IoMode::Read:
|
||||
}
|
||||
else
|
||||
{
|
||||
fmtstr = _("Couldn't read '{path}': {error} ({error_code})");
|
||||
read_entire_buf(*fd, file_offset, buf, buflen, error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (error)
|
||||
|
@ -189,7 +175,7 @@ void read_or_write_bytes(
|
|||
|
||||
void read_or_write_piece(
|
||||
tr_torrent const& tor,
|
||||
IoMode const io_mode,
|
||||
bool const writable,
|
||||
tr_block_info::Location const loc,
|
||||
uint8_t* buf,
|
||||
uint64_t buflen,
|
||||
|
@ -207,7 +193,7 @@ void read_or_write_piece(
|
|||
while (buflen != 0U && !error)
|
||||
{
|
||||
auto const bytes_this_pass = std::min(buflen, tor.file_size(file_index) - file_offset);
|
||||
read_or_write_bytes(session, open_files, tor, io_mode, file_index, file_offset, buf, bytes_this_pass, error);
|
||||
read_or_write_bytes(session, open_files, tor, writable, file_index, file_offset, buf, bytes_this_pass, error);
|
||||
if (buf != nullptr)
|
||||
{
|
||||
buf += bytes_this_pass;
|
||||
|
@ -264,21 +250,14 @@ std::optional<tr_sha1_digest_t> recalculate_hash(tr_torrent const& tor, tr_piece
|
|||
int tr_ioRead(tr_torrent const& tor, tr_block_info::Location const& loc, size_t const len, uint8_t* const setme)
|
||||
{
|
||||
auto error = tr_error{};
|
||||
read_or_write_piece(tor, IoMode::Read, loc, setme, len, error);
|
||||
return error.code();
|
||||
}
|
||||
|
||||
int tr_ioPrefetch(tr_torrent const& tor, tr_block_info::Location const& loc, size_t const len)
|
||||
{
|
||||
auto error = tr_error{};
|
||||
read_or_write_piece(tor, IoMode::Prefetch, loc, nullptr, len, error);
|
||||
read_or_write_piece(tor, false /*writable*/, loc, setme, len, error);
|
||||
return error.code();
|
||||
}
|
||||
|
||||
int tr_ioWrite(tr_torrent& tor, tr_block_info::Location const& loc, size_t const len, uint8_t const* const writeme)
|
||||
{
|
||||
auto error = tr_error{};
|
||||
read_or_write_piece(tor, IoMode::Write, loc, const_cast<uint8_t*>(writeme), len, error);
|
||||
read_or_write_piece(tor, true /*writable*/, loc, const_cast<uint8_t*>(writeme), len, error);
|
||||
|
||||
// if IO failed, set torrent's error if not already set
|
||||
if (error && tor.error().error_type() != TR_STAT_LOCAL_ERROR)
|
||||
|
|
|
@ -29,8 +29,6 @@ struct tr_torrent;
|
|||
*/
|
||||
[[nodiscard]] int tr_ioRead(tr_torrent const& tor, tr_block_info::Location const& loc, size_t len, uint8_t* setme);
|
||||
|
||||
int tr_ioPrefetch(tr_torrent const& tor, tr_block_info::Location const& loc, size_t len);
|
||||
|
||||
/**
|
||||
* Writes the block specified by the piece index, offset, and length.
|
||||
* @return 0 on success, or an errno value on failure.
|
||||
|
|
|
@ -183,9 +183,6 @@ auto constexpr ReqQ = int{ 512 };
|
|||
|
||||
// used in lowering the outMessages queue period
|
||||
|
||||
// how many blocks to keep prefetched per peer
|
||||
auto constexpr PrefetchMax = size_t{ 18 };
|
||||
|
||||
// when we're making requests from another peer,
|
||||
// batch them together to send enough requests to
|
||||
// meet our bandwidth goals for the next N seconds
|
||||
|
@ -635,17 +632,7 @@ public:
|
|||
|
||||
std::shared_ptr<tr_peerIo> const io;
|
||||
|
||||
struct QueuedPeerRequest : public peer_request
|
||||
{
|
||||
explicit QueuedPeerRequest(peer_request in) noexcept
|
||||
: peer_request{ in }
|
||||
{
|
||||
}
|
||||
|
||||
bool prefetched = false;
|
||||
};
|
||||
|
||||
std::vector<QueuedPeerRequest> peer_requested_;
|
||||
std::vector<peer_request> peer_requested_;
|
||||
|
||||
std::array<std::vector<tr_pex>, NUM_TR_AF_INET_TYPES> pex;
|
||||
|
||||
|
@ -897,15 +884,17 @@ std::optional<int> popNextMetadataRequest(tr_peerMsgsImpl* msgs)
|
|||
|
||||
void cancelAllRequestsToClient(tr_peerMsgsImpl* msgs)
|
||||
{
|
||||
auto& queue = msgs->peer_requested_;
|
||||
|
||||
if (auto const must_send_rej = msgs->io->supports_fext(); must_send_rej)
|
||||
{
|
||||
for (auto const& req : msgs->peer_requested_)
|
||||
for (auto const& req : queue)
|
||||
{
|
||||
protocolSendReject(msgs, &req);
|
||||
}
|
||||
}
|
||||
|
||||
msgs->peer_requested_.clear();
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
// ---
|
||||
|
@ -1257,25 +1246,6 @@ void parseLtep(tr_peerMsgsImpl* msgs, MessageReader& payload)
|
|||
|
||||
ReadResult process_peer_message(tr_peerMsgsImpl* msgs, uint8_t id, MessageReader& payload);
|
||||
|
||||
void prefetchPieces(tr_peerMsgsImpl* msgs)
|
||||
{
|
||||
if (!msgs->session->allowsPrefetch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure that the first `PrefetchMax` items in `msgs->peer_requested_` are prefetched.
|
||||
auto& requests = msgs->peer_requested_;
|
||||
for (size_t i = 0, n = std::min(PrefetchMax, std::size(requests)); i < n; ++i)
|
||||
{
|
||||
if (auto& req = requests[i]; !req.prefetched)
|
||||
{
|
||||
msgs->session->cache->prefetch_block(*msgs->torrent, msgs->torrent->piece_loc(req.index, req.offset), req.length);
|
||||
req.prefetched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canAddRequestFromPeer(tr_peerMsgsImpl const* const msgs, struct peer_request const& req)
|
||||
{
|
||||
if (msgs->peer_is_choked())
|
||||
|
@ -1310,7 +1280,6 @@ void peerMadeRequest(tr_peerMsgsImpl* msgs, struct peer_request const* req)
|
|||
if (canAddRequestFromPeer(msgs, *req))
|
||||
{
|
||||
msgs->peer_requested_.emplace_back(*req);
|
||||
prefetchPieces(msgs);
|
||||
}
|
||||
else if (msgs->io->supports_fext())
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ using namespace std::literals;
|
|||
namespace
|
||||
{
|
||||
|
||||
auto constexpr MyStatic = std::array<std::string_view, 406>{ ""sv,
|
||||
auto constexpr MyStatic = std::array<std::string_view, 405>{ ""sv,
|
||||
"activeTorrentCount"sv,
|
||||
"activity-date"sv,
|
||||
"activityDate"sv,
|
||||
|
@ -252,7 +252,6 @@ auto constexpr MyStatic = std::array<std::string_view, 406>{ ""sv,
|
|||
"port-is-open"sv,
|
||||
"preallocation"sv,
|
||||
"preferred-transport"sv,
|
||||
"prefetch-enabled"sv,
|
||||
"primary-mime-type"sv,
|
||||
"priorities"sv,
|
||||
"priority"sv,
|
||||
|
|
|
@ -254,7 +254,6 @@ enum
|
|||
TR_KEY_port_is_open,
|
||||
TR_KEY_preallocation,
|
||||
TR_KEY_preferred_transport,
|
||||
TR_KEY_prefetch_enabled,
|
||||
TR_KEY_primary_mime_type,
|
||||
TR_KEY_priorities,
|
||||
TR_KEY_priority,
|
||||
|
|
|
@ -53,7 +53,6 @@ struct tr_variant;
|
|||
V(TR_KEY_pex_enabled, pex_enabled, bool, true, "") \
|
||||
V(TR_KEY_port_forwarding_enabled, port_forwarding_enabled, bool, true, "") \
|
||||
V(TR_KEY_preallocation, preallocation_mode, tr_open_files::Preallocation, tr_open_files::Preallocation::Sparse, "") \
|
||||
V(TR_KEY_prefetch_enabled, is_prefetch_enabled, bool, true, "") \
|
||||
V(TR_KEY_queue_stalled_enabled, queue_stalled_enabled, bool, true, "") \
|
||||
V(TR_KEY_queue_stalled_minutes, queue_stalled_minutes, size_t, 30U, "") \
|
||||
V(TR_KEY_ratio_limit, ratio_limit, double, 2.0, "") \
|
||||
|
|
|
@ -786,11 +786,6 @@ public:
|
|||
return settings_.preferred_transport;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto allowsPrefetch() const noexcept
|
||||
{
|
||||
return settings_.is_prefetch_enabled;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto isIdleLimited() const noexcept
|
||||
{
|
||||
return settings_.idle_seeding_limit_enabled;
|
||||
|
|
|
@ -75,7 +75,6 @@ void tr_verify_worker::verify_torrent(Mediator& verify_mediator, bool const abor
|
|||
{
|
||||
bytes_this_pass = num_read;
|
||||
sha->add(std::data(buffer), bytes_this_pass);
|
||||
tr_sys_file_advise(fd, file_pos, bytes_this_pass, TR_SYS_FILE_ADVICE_DONT_NEED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue