add asynchronous overload of torrent_handle::add_piece()

This commit is contained in:
arvidn
2022-05-24 13:01:06 +02:00
committed by Arvid Norberg
parent be8313e35e
commit 5b9578785b
8 changed files with 50 additions and 11 deletions

View File

@ -1,4 +1,5 @@
* add asynchronous overload of torrent_handle::add_piece()
* default to a single hashing thread, for full checks
* Fix bug when checking files and the first piece is invalid

View File

@ -462,6 +462,7 @@ namespace libtorrent {
int seed_rank(aux::session_settings const& s) const;
void add_piece(piece_index_t piece, char const* data, add_piece_flags_t flags);
void add_piece_async(piece_index_t piece, std::vector<char> data, add_piece_flags_t flags);
void on_disk_write_complete(storage_error const& error
, peer_request const& p);

View File

@ -268,10 +268,7 @@ namespace aux {
static constexpr add_piece_flags_t overwrite_existing = 0_bit;
// This function will write ``data`` to the storage as piece ``piece``,
// as if it had been downloaded from a peer. ``data`` is expected to
// point to a buffer of as many bytes as the size of the specified piece.
// The data in the buffer is copied and passed on to the disk IO thread
// to be written at a later point.
// as if it had been downloaded from a peer.
//
// By default, data that's already been downloaded is not overwritten by
// this buffer. If you trust this data to be correct (and pass the piece
@ -285,7 +282,20 @@ namespace aux {
//
// Adding pieces while the torrent is being checked (i.e. in
// torrent_status::checking_files state) is not supported.
//
// The overload taking a raw pointer to the data is a blocking call. It
// won't return until the libtorrent thread has copied the data into its
// disk write buffer. ``data`` is expected to point to a buffer of as
// many bytes as the size of the specified piece. See
// file_storage::piece_size().
//
// The data in the buffer is copied and passed on to the disk IO thread
// to be written at a later point.
//
// The overload taking a ``std::vector<char>`` is not blocking, it will
// send the buffer to the main thread and return immediately.
void add_piece(piece_index_t piece, char const* data, add_piece_flags_t flags = {}) const;
void add_piece(piece_index_t piece, std::vector<char> data, add_piece_flags_t flags = {}) const;
// This function starts an asynchronous read operation of the specified
// piece from this torrent. You must have completed the download of the

View File

@ -1258,12 +1258,33 @@ bool is_downloading_state(int const st)
piece_index_t m_piece;
};
void torrent::add_piece_async(piece_index_t const piece
, std::vector<char> data, add_piece_flags_t const flags)
{
TORRENT_ASSERT(is_single_thread());
// make sure the piece index is correct
if (piece >= torrent_file().end_piece())
return;
// make sure the piece size is correct
if (data.size() != std::size_t(m_torrent_file->piece_size(piece)))
return;
add_piece(piece, data.data(), flags);
}
// TODO: 3 there's some duplication between this function and
// peer_connection::incoming_piece(). is there a way to merge something?
void torrent::add_piece(piece_index_t const piece, char const* data
, add_piece_flags_t const flags)
{
TORRENT_ASSERT(is_single_thread());
// make sure the piece index is correct
if (piece >= torrent_file().end_piece())
return;
int const piece_size = m_torrent_file->piece_size(piece);
int const blocks_in_piece = (piece_size + block_size() - 1) / block_size();

View File

@ -121,7 +121,7 @@ namespace libtorrent {
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
(t.get()->*f)(a...);
(t.get()->*f)(std::move(a)...);
#ifndef BOOST_NO_EXCEPTIONS
} catch (system_error const& e) {
ses.alerts().emplace_alert<torrent_error_alert>(torrent_handle(m_torrent)
@ -153,7 +153,7 @@ namespace libtorrent {
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
(t.get()->*f)(a...);
(t.get()->*f)(std::move(a)...);
#ifndef BOOST_NO_EXCEPTIONS
} catch (...) {
ex = std::current_exception();
@ -189,7 +189,7 @@ namespace libtorrent {
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
r = (t.get()->*f)(a...);
r = (t.get()->*f)(std::move(a)...);
#ifndef BOOST_NO_EXCEPTIONS
} catch (...) {
ex = std::current_exception();
@ -698,6 +698,12 @@ namespace libtorrent {
sync_call(&torrent::add_piece, piece, data, flags);
}
void torrent_handle::add_piece(piece_index_t piece, std::vector<char> data
, add_piece_flags_t const flags) const
{
async_call(&torrent::add_piece_async, piece, std::move(data), flags);
}
void torrent_handle::read_piece(piece_index_t piece) const
{
async_call(&torrent::read_piece, piece);

View File

@ -117,7 +117,7 @@ void test_remap_files(storage_mode_t storage_mode = storage_mode_sparse)
for (auto const i : fs.piece_range())
{
std::vector<char> const piece = generate_piece(i, fs.piece_size(i));
tor1.add_piece(i, piece.data());
tor1.add_piece(i, std::move(piece));
}
// read pieces

View File

@ -1801,7 +1801,7 @@ TORRENT_TEST(resume_data_have_pieces)
atp.save_path = ".";
auto h = ses.add_torrent(atp);
wait_for_downloading(ses, "");
h.add_piece(0_piece, piece_data.data());
h.add_piece(0_piece, std::move(piece_data));
h.save_resume_data();
ses.pause();

View File

@ -875,10 +875,10 @@ TORRENT_TEST(redundant_add_piece)
auto h = ses.add_torrent(atp);
wait_for_downloading(ses, "");
h.add_piece(0_piece, piece_data.data());
h.add_piece(0_piece, piece_data);
h.set_piece_deadline(0_piece, 0, torrent_handle::alert_when_available);
h.prioritize_pieces(std::vector<lt::download_priority_t>(std::size_t(ti->num_pieces()), lt::dont_download));
h.add_piece(0_piece, piece_data.data());
h.add_piece(0_piece, std::move(piece_data));
std::this_thread::sleep_for(lt::seconds(2));
}