From f5366bd816594c6a3b00ca50189513acbed19ac2 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Wed, 26 Oct 2016 17:40:56 -0700 Subject: [PATCH] use span for scatter/gather lists (#1260) use span for gather/scatter buffers. remove explicit size parameter from file_op --- include/libtorrent/block_cache.hpp | 4 +- include/libtorrent/disk_buffer_pool.hpp | 4 +- include/libtorrent/disk_io_thread.hpp | 4 +- include/libtorrent/file.hpp | 7 +- include/libtorrent/part_file.hpp | 4 +- include/libtorrent/storage.hpp | 10 +- src/block_cache.cpp | 8 +- src/disk_buffer_pool.cpp | 21 ++-- src/disk_io_thread.cpp | 34 +++--- src/file.cpp | 149 +++++++++++------------- src/part_file.cpp | 16 +-- src/storage.cpp | 87 ++++++-------- src/torrent_info.cpp | 2 +- test/setup_transfer.cpp | 4 +- test/test_block_cache.cpp | 16 +-- test/test_file.cpp | 14 +-- test/test_http_connection.cpp | 2 +- test/test_part_file.cpp | 8 +- test/test_storage.cpp | 50 ++++---- test/test_web_seed_redirect.cpp | 2 +- 20 files changed, 214 insertions(+), 232 deletions(-) diff --git a/include/libtorrent/block_cache.hpp b/include/libtorrent/block_cache.hpp index b07c03a60..ab3c4f01b 100644 --- a/include/libtorrent/block_cache.hpp +++ b/include/libtorrent/block_cache.hpp @@ -430,8 +430,8 @@ namespace libtorrent cached_piece_entry* add_dirty_block(disk_io_job* j); enum { blocks_inc_refcount = 1 }; - void insert_blocks(cached_piece_entry* pe, int block, file::iovec_t *iov - , int iov_len, disk_io_job* j, int flags = 0); + void insert_blocks(cached_piece_entry* pe, int block, span iov + , disk_io_job* j, int flags = 0); #if TORRENT_USE_INVARIANT_CHECKS void check_invariant() const; diff --git a/include/libtorrent/disk_buffer_pool.hpp b/include/libtorrent/disk_buffer_pool.hpp index 820061dac..95a12b534 100644 --- a/include/libtorrent/disk_buffer_pool.hpp +++ b/include/libtorrent/disk_buffer_pool.hpp @@ -80,8 +80,8 @@ namespace libtorrent void free_buffer(char* buf); void free_multiple_buffers(span bufvec); - int allocate_iovec(file::iovec_t* iov, int iov_len); - void free_iovec(file::iovec_t* iov, int iov_len); + int allocate_iovec(span iov); + void free_iovec(span iov); int block_size() const { return m_block_size; } diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 1a3970d5b..a1c76fbb2 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -487,8 +487,8 @@ namespace libtorrent // low level flush operations, used by flush_range int build_iovec(cached_piece_entry* pe, int start, int end - , file::iovec_t* iov, int* flushing, int block_base_index = 0); - void flush_iovec(cached_piece_entry* pe, file::iovec_t const* iov, int const* flushing + , span iov, span flushing, int block_base_index = 0); + void flush_iovec(cached_piece_entry* pe, span iov, span flushing , int num_blocks, storage_error& error); void iovec_flushed(cached_piece_entry* pe , int* flushing, int num_blocks, int block_offset diff --git a/include/libtorrent/file.hpp b/include/libtorrent/file.hpp index 7e4ba26f6..7cab161f7 100644 --- a/include/libtorrent/file.hpp +++ b/include/libtorrent/file.hpp @@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/string_view.hpp" +#include "libtorrent/span.hpp" #include "libtorrent/aux_/disable_warnings_push.hpp" @@ -314,9 +315,9 @@ namespace libtorrent int open_mode() const { return m_open_mode; } - std::int64_t writev(std::int64_t file_offset, iovec_t const* bufs, int num_bufs + std::int64_t writev(std::int64_t file_offset, span bufs , error_code& ec, int flags = 0); - std::int64_t readv(std::int64_t file_offset, iovec_t const* bufs, int num_bufs + std::int64_t readv(std::int64_t file_offset, span bufs , error_code& ec, int flags = 0); std::int64_t get_size(error_code& ec) const; @@ -352,7 +353,7 @@ namespace libtorrent #endif }; - TORRENT_EXTRA_EXPORT int bufs_size(file::iovec_t const* bufs, int num_bufs); + TORRENT_EXTRA_EXPORT int bufs_size(span bufs); } diff --git a/include/libtorrent/part_file.hpp b/include/libtorrent/part_file.hpp index 388ddcb88..8cbb9203b 100644 --- a/include/libtorrent/part_file.hpp +++ b/include/libtorrent/part_file.hpp @@ -49,8 +49,8 @@ namespace libtorrent part_file(std::string const& path, std::string const& name, int num_pieces, int piece_size); ~part_file(); - int writev(file::iovec_t const* bufs, int num_bufs, int piece, int offset, error_code& ec); - int readv(file::iovec_t const* bufs, int num_bufs, int piece, int offset, error_code& ec); + int writev(span bufs, int piece, int offset, error_code& ec); + int readv(span bufs, int piece, int offset, error_code& ec); // free the slot the given piece is stored in. We no longer need to store this // piece in the part file diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 89596feca..a56d61796 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -148,9 +148,9 @@ namespace libtorrent struct cached_piece_entry; struct add_torrent_params; - TORRENT_EXTRA_EXPORT int copy_bufs(file::iovec_t const* bufs, int bytes, file::iovec_t* target); + TORRENT_EXTRA_EXPORT int copy_bufs(span bufs, int bytes, span target); TORRENT_EXTRA_EXPORT span advance_bufs(span bufs, int bytes); - TORRENT_EXTRA_EXPORT void clear_bufs(file::iovec_t const* bufs, int num_bufs); + TORRENT_EXTRA_EXPORT void clear_bufs(span bufs); // flags for async_move_storage enum move_flags_t @@ -612,15 +612,15 @@ namespace libtorrent // what to do when it's actually touching the file struct fileop { - virtual int file_op(int const file_index, std::int64_t const file_offset, int const size - , file::iovec_t const* bufs, storage_error& ec) = 0; + virtual int file_op(int const file_index, std::int64_t const file_offset + , span bufs, storage_error& ec) = 0; }; // this function is responsible for turning read and write operations in the // torrent space (pieces) into read and write operations in the filesystem // space (files on disk). TORRENT_EXTRA_EXPORT int readwritev(file_storage const& files - , file::iovec_t const* bufs, int piece, int offset, int num_bufs + , span bufs, int piece, int offset , fileop& op, storage_error& ec); } diff --git a/src/block_cache.cpp b/src/block_cache.cpp index 1d0bcbdd0..44bad570e 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -1291,8 +1291,8 @@ int block_cache::pad_job(disk_io_job const* j, int blocks_in_piece return end - start; } -void block_cache::insert_blocks(cached_piece_entry* pe, int block, file::iovec_t *iov - , int iov_len, disk_io_job* j, int flags) +void block_cache::insert_blocks(cached_piece_entry* pe, int block, span iov + , disk_io_job* j, int flags) { #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS INVARIANT_CHECK; @@ -1300,7 +1300,7 @@ void block_cache::insert_blocks(cached_piece_entry* pe, int block, file::iovec_t TORRENT_ASSERT(pe); TORRENT_ASSERT(pe->in_use); - TORRENT_PIECE_ASSERT(iov_len > 0, pe); + TORRENT_PIECE_ASSERT(iov.size() > 0, pe); #if TORRENT_USE_ASSERTS // we're not allowed to add dirty blocks @@ -1314,7 +1314,7 @@ void block_cache::insert_blocks(cached_piece_entry* pe, int block, file::iovec_t TORRENT_ASSERT(pe->in_use); - for (int i = 0; i < iov_len; ++i, ++block) + for (int i = 0; i < iov.size(); ++i, ++block) { // each iovec buffer has to be the size of a block (or the size of the last block) TORRENT_PIECE_ASSERT(iov[i].iov_len == (std::min)(block_size() diff --git a/src/disk_buffer_pool.cpp b/src/disk_buffer_pool.cpp index 9f9518335..bde036c39 100644 --- a/src/disk_buffer_pool.cpp +++ b/src/disk_buffer_pool.cpp @@ -219,21 +219,22 @@ namespace libtorrent // this function allocates buffers and // fills in the iovec array with the buffers - int disk_buffer_pool::allocate_iovec(file::iovec_t* iov, int iov_len) + int disk_buffer_pool::allocate_iovec(span iov) { std::unique_lock l(m_pool_mutex); - for (int i = 0; i < iov_len; ++i) + for (auto& i : iov) { - iov[i].iov_base = allocate_buffer_impl(l, "pending read"); - iov[i].iov_len = block_size(); - if (iov[i].iov_base == nullptr) + i.iov_base = allocate_buffer_impl(l, "pending read"); + i.iov_len = block_size(); + if (i.iov_base == nullptr) { // uh oh. We failed to allocate the buffer! // we need to roll back and free all the buffers // we've already allocated - for (int j = 0; j < i; ++j) + for (auto j : iov) { - char* buf = static_cast(iov[j].iov_base); + if (j.iov_base == nullptr) break; + char* buf = static_cast(j.iov_base); TORRENT_ASSERT(is_disk_buffer(buf, l)); free_buffer_impl(buf, l); remove_buffer_in_use(buf); @@ -244,13 +245,13 @@ namespace libtorrent return 0; } - void disk_buffer_pool::free_iovec(file::iovec_t* iov, int iov_len) + void disk_buffer_pool::free_iovec(span iov) { // TODO: perhaps we should sort the buffers here? std::unique_lock l(m_pool_mutex); - for (int i = 0; i < iov_len; ++i) + for (auto i : iov) { - char* buf = static_cast(iov[i].iov_base); + char* buf = static_cast(i.iov_base); TORRENT_ASSERT(is_disk_buffer(buf, l)); free_buffer_impl(buf, l); remove_buffer_in_use(buf); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index c0c790e0e..f60137f6a 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -445,9 +445,9 @@ namespace libtorrent // we keep the indices in the iovec_offset array cont_pieces = range_end - range_start; - - TORRENT_ALLOCA(iov, file::iovec_t, p->blocks_in_piece * cont_pieces); - TORRENT_ALLOCA(flushing, int, p->blocks_in_piece * cont_pieces); + int blocks_to_flush = p->blocks_in_piece * cont_pieces; + TORRENT_ALLOCA(iov, file::iovec_t, blocks_to_flush); + TORRENT_ALLOCA(flushing, int, blocks_to_flush); // this is the offset into iov and flushing for each piece TORRENT_ALLOCA(iovec_offset, int, cont_pieces + 1); int iov_len = 0; @@ -479,7 +479,7 @@ namespace libtorrent ++pe->piece_refcount; iov_len += build_iovec(pe, 0, p->blocks_in_piece - , iov.subspan(iov_len).data(), flushing.subspan(iov_len).data(), block_start); + , iov.subspan(iov_len), flushing.subspan(iov_len), block_start); block_start += p->blocks_in_piece; } @@ -504,7 +504,7 @@ namespace libtorrent // unlock while we're performing the actual disk I/O // then lock again auto unlock = scoped_unlock(l); - flush_iovec(first_piece, iov.data(), flushing.data(), iov_len, error); + flush_iovec(first_piece, iov, flushing, iov_len, error); } block_start = 0; @@ -552,7 +552,7 @@ namespace libtorrent // multiple pieces, the subsequent pieces after the first one, must have // their block indices start where the previous one left off int disk_io_thread::build_iovec(cached_piece_entry* pe, int start, int end - , file::iovec_t* iov, int* flushing, int block_base_index) + , span iov, span flushing, int block_base_index) { INVARIANT_CHECK; @@ -616,7 +616,7 @@ namespace libtorrent // the cached_piece_entry is supposed to point to the // first piece, if the iovec spans multiple pieces void disk_io_thread::flush_iovec(cached_piece_entry* pe - , file::iovec_t const* iov, int const* flushing + , span iov, span flushing , int num_blocks, storage_error& error) { TORRENT_PIECE_ASSERT(!error, pe); @@ -637,7 +637,7 @@ namespace libtorrent ? file::coalesce_buffers : 0; // issue the actual write operation - file::iovec_t const* iov_start = iov; + auto iov_start = iov; int flushing_start = 0; int piece = pe->piece; int blocks_in_piece = pe->blocks_in_piece; @@ -646,12 +646,12 @@ namespace libtorrent { if (i < num_blocks && flushing[i] == flushing[i - 1] + 1) continue; int ret = pe->storage->get_storage_impl()->writev( - {iov_start, size_t(i - flushing_start)} + iov_start.first(i - flushing_start) , piece + flushing[flushing_start] / blocks_in_piece , (flushing[flushing_start] % blocks_in_piece) * block_size , file_flags, error); if (ret < 0 || error) failed = true; - iov_start = &iov[i]; + iov_start = iov.subspan(i); flushing_start = i; } @@ -745,7 +745,7 @@ namespace libtorrent TORRENT_ALLOCA(iov, file::iovec_t, pe->blocks_in_piece); TORRENT_ALLOCA(flushing, int, pe->blocks_in_piece); - int iov_len = build_iovec(pe, start, end, iov.data(), flushing.data(), 0); + int iov_len = build_iovec(pe, start, end, iov, flushing, 0); if (iov_len == 0) return 0; TORRENT_PIECE_ASSERT(pe->cache_state <= cached_piece_entry::read_lru1 || pe->cache_state == cached_piece_entry::read_lru2, pe); @@ -758,7 +758,7 @@ namespace libtorrent piece_refcount_holder refcount_holder(pe); auto unlocker = scoped_unlock(l); - flush_iovec(pe, iov.data(), flushing.data(), iov_len, error); + flush_iovec(pe, iov, flushing, iov_len, error); } iovec_flushed(pe, flushing.data(), iov_len, 0, error, completed_jobs); @@ -1252,7 +1252,7 @@ namespace libtorrent l.unlock(); // then we'll actually allocate the buffers - int ret = m_disk_cache.allocate_iovec(iov.data(), iov_len); + int ret = m_disk_cache.allocate_iovec(iov); if (ret < 0) { @@ -1301,7 +1301,7 @@ namespace libtorrent if (ret < 0) { // read failed. free buffers and return error - m_disk_cache.free_iovec(iov.data(), iov_len); + m_disk_cache.free_iovec(iov); pe = m_disk_cache.find_piece(j); if (pe == nullptr) @@ -1331,7 +1331,7 @@ namespace libtorrent // as soon we insert the blocks they may be evicted // (if using purgeable memory). In order to prevent that // until we can read from them, increment the refcounts - m_disk_cache.insert_blocks(pe, block, iov.data(), iov_len, j, block_cache::blocks_inc_refcount); + m_disk_cache.insert_blocks(pe, block, iov, j, block_cache::blocks_inc_refcount); TORRENT_ASSERT(pe->blocks[block].buf); @@ -2403,7 +2403,7 @@ namespace libtorrent ph->h.update({static_cast(iov.iov_base), iov.iov_len}); l.lock(); - m_disk_cache.insert_blocks(pe, i, &iov, 1, j); + m_disk_cache.insert_blocks(pe, i, iov, j); l.unlock(); } } @@ -2623,7 +2623,7 @@ namespace libtorrent offset += block_size; l.lock(); - m_disk_cache.insert_blocks(pe, i, &iov, 1, j); + m_disk_cache.insert_blocks(pe, i, iov, j); } refcount_holder.release(); diff --git a/src/file.cpp b/src/file.cpp index 9ef0a7772..e8d7101db 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -209,21 +209,21 @@ namespace } } - if (wait_for_multiple_objects(num_bufs, h.data()) == WAIT_FAILED) + if (wait_for_multiple_objects(int(h.size()), h.data()) == WAIT_FAILED) { ret = -1; goto done; } - for (int i = 0; i < num_bufs; ++i) + for (auto& o : ol) { - if (WaitForSingleObject(ol[i].hEvent, INFINITE) == WAIT_FAILED) + if (WaitForSingleObject(o.hEvent, INFINITE) == WAIT_FAILED) { ret = -1; break; } DWORD num_read; - if (GetOverlappedResult(fd, &ol[i], &num_read, FALSE) == FALSE) + if (GetOverlappedResult(fd, &o, &num_read, FALSE) == FALSE) { #ifdef ERROR_CANT_WAIT TORRENT_ASSERT(GetLastError() != ERROR_CANT_WAIT); @@ -235,8 +235,8 @@ namespace } done: - for (int i = 0; i < num_bufs; ++i) - CloseHandle(h[i]); + for (auto hnd : h) + CloseHandle(hnd); return ret; } @@ -279,21 +279,21 @@ done: } } - if (wait_for_multiple_objects(num_bufs, h.data()) == WAIT_FAILED) + if (wait_for_multiple_objects(int(h.size()), h.data()) == WAIT_FAILED) { ret = -1; goto done; } - for (int i = 0; i < num_bufs; ++i) + for (auto& o : ol) { - if (WaitForSingleObject(ol[i].hEvent, INFINITE) == WAIT_FAILED) + if (WaitForSingleObject(o.hEvent, INFINITE) == WAIT_FAILED) { ret = -1; break; } DWORD num_written; - if (GetOverlappedResult(fd, &ol[i], &num_written, FALSE) == FALSE) + if (GetOverlappedResult(fd, &o, &num_written, FALSE) == FALSE) { #ifdef ERROR_CANT_WAIT TORRENT_ASSERT(GetLastError() != ERROR_CANT_WAIT); @@ -305,8 +305,8 @@ done: } done: - for (int i = 0; i < num_bufs; ++i) - CloseHandle(h[i]); + for (auto hnd : h) + CloseHandle(hnd); return ret; } @@ -336,11 +336,11 @@ static_assert((libtorrent::file::sparse & libtorrent::file::attribute_mask) == 0 namespace libtorrent { - int bufs_size(file::iovec_t const* bufs, int num_bufs) + int bufs_size(span bufs) { std::size_t size = 0; - for (file::iovec_t const* i = bufs, *end(bufs + num_bufs); i < end; ++i) - size += i->iov_len; + for (auto buf : bufs) + size += buf.iov_len; return int(size); } @@ -1676,81 +1676,76 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { namespace { #if !TORRENT_USE_PREADV - void gather_copy(file::iovec_t const* bufs, int num_bufs, char* dst) + void gather_copy(span bufs, char* dst) { std::size_t offset = 0; - for (int i = 0; i < num_bufs; ++i) + for (auto buf : bufs) { - std::memcpy(dst + offset, bufs[i].iov_base, bufs[i].iov_len); - offset += bufs[i].iov_len; + std::memcpy(dst + offset, buf.iov_base, buf.iov_len); + offset += buf.iov_len; } } - void scatter_copy(file::iovec_t const* bufs, int num_bufs, char const* src) + void scatter_copy(span bufs, char const* src) { std::size_t offset = 0; - for (int i = 0; i < num_bufs; ++i) + for (auto buf : bufs) { - std::memcpy(bufs[i].iov_base, src + offset, bufs[i].iov_len); - offset += bufs[i].iov_len; + std::memcpy(buf.iov_base, src + offset, buf.iov_len); + offset += buf.iov_len; } } - bool coalesce_read_buffers(file::iovec_t const*& bufs, int& num_bufs - , file::iovec_t* tmp) + bool coalesce_read_buffers(span& bufs + , file::iovec_t& tmp) { - int const buf_size = bufs_size(bufs, num_bufs); + int const buf_size = bufs_size(bufs); char* buf = static_cast(std::malloc(buf_size)); if (!buf) return false; - tmp->iov_base = buf; - tmp->iov_len = buf_size; - bufs = tmp; - num_bufs = 1; + tmp.iov_base = buf; + tmp.iov_len = buf_size; + bufs = span(tmp); return true; } - void coalesce_read_buffers_end(file::iovec_t const* bufs, int const num_bufs + void coalesce_read_buffers_end(span bufs , char* const buf, bool const copy) { - if (copy) scatter_copy(bufs, num_bufs, buf); + if (copy) scatter_copy(bufs, buf); std::free(buf); } - bool coalesce_write_buffers(file::iovec_t const*& bufs, int& num_bufs - , file::iovec_t* tmp) + bool coalesce_write_buffers(span& bufs + , file::iovec_t& tmp) { - int const buf_size = bufs_size(bufs, num_bufs); + int const buf_size = bufs_size(bufs); char* buf = static_cast(std::malloc(buf_size)); if (!buf) return false; - gather_copy(bufs, num_bufs, buf); - tmp->iov_base = buf; - tmp->iov_len = buf_size; - bufs = tmp; - num_bufs = 1; + gather_copy(bufs, buf); + tmp.iov_base = buf; + tmp.iov_len = buf_size; + bufs = span(tmp); return true; } #endif // TORRENT_USE_PREADV template - std::int64_t iov(Fun f, handle_type fd, std::int64_t file_offset, file::iovec_t const* bufs_in - , int num_bufs_in, error_code& ec) + std::int64_t iov(Fun f, handle_type fd, std::int64_t file_offset + , span bufs, error_code& ec) { - file::iovec_t const* bufs = bufs_in; - int num_bufs = num_bufs_in; - #if TORRENT_USE_PREADV int ret = 0; - while (num_bufs > 0) + while (!bufs.empty()) { #ifdef IOV_MAX - int const nbufs = (std::min)(num_bufs, IOV_MAX); + auto const nbufs = bufs.first((std::min)(int(bufs.size()), IOV_MAX)); #else - int const nbufs = num_bufs; + auto const nbufs = bufs; #endif int tmp_ret = 0; - tmp_ret = f(fd, bufs, nbufs, file_offset); + tmp_ret = f(fd, nbufs.data(), int(nbufs.size()), file_offset); if (tmp_ret < 0) { #ifdef TORRENT_WINDOWS @@ -1767,20 +1762,19 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { // just need to issue the read/write operation again. In either case, // punt that to the upper layer, as reissuing the operations is // complicated here - const int expected_len = bufs_size(bufs, nbufs); + const int expected_len = bufs_size(nbufs); if (tmp_ret < expected_len) break; - num_bufs -= nbufs; - bufs += nbufs; + bufs = bufs.subspan(nbufs.size()); } return ret; #elif TORRENT_USE_PREAD int ret = 0; - for (file::iovec_t const* i = bufs, *end(bufs + num_bufs); i < end; ++i) + for (auto i : bufs) { - int tmp_ret = f(fd, i->iov_base, i->iov_len, file_offset); + int tmp_ret = f(fd, i.iov_base, i.iov_len, file_offset); if (tmp_ret < 0) { #ifdef TORRENT_WINDOWS @@ -1792,7 +1786,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { } file_offset += tmp_ret; ret += tmp_ret; - if (tmp_ret < int(i->iov_len)) break; + if (tmp_ret < int(i.iov_len)) break; } return ret; @@ -1815,9 +1809,9 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { } #endif - for (file::iovec_t const* i = bufs, *end(bufs + num_bufs); i < end; ++i) + for (auto i : bufs) { - int tmp_ret = f(fd, i->iov_base, i->iov_len); + int tmp_ret = f(fd, i.iov_base, i.iov_len); if (tmp_ret < 0) { #ifdef TORRENT_WINDOWS @@ -1829,7 +1823,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { } file_offset += tmp_ret; ret += tmp_ret; - if (tmp_ret < int(i->iov_len)) break; + if (tmp_ret < int(i.iov_len)) break; } return ret; @@ -1841,7 +1835,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { // this has to be thread safe and atomic. i.e. on posix systems it has to be // turned into a series of pread() calls - std::int64_t file::readv(std::int64_t file_offset, iovec_t const* bufs, int num_bufs + std::int64_t file::readv(std::int64_t file_offset, span bufs , error_code& ec, int flags) { if (m_file_handle == INVALID_HANDLE_VALUE) @@ -1854,40 +1848,38 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { return -1; } TORRENT_ASSERT((m_open_mode & rw_mask) == read_only || (m_open_mode & rw_mask) == read_write); - TORRENT_ASSERT(bufs); - TORRENT_ASSERT(num_bufs > 0); + TORRENT_ASSERT(!bufs.empty()); TORRENT_ASSERT(is_open()); #if TORRENT_USE_PREADV TORRENT_UNUSED(flags); - int ret = iov(&::preadv, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::preadv, native_handle(), file_offset, bufs, ec); #else // there's no point in coalescing single buffer writes - if (num_bufs == 1) + if (bufs.size() == 1) { flags &= ~file::coalesce_buffers; } - file::iovec_t tmp; - file::iovec_t const* const orig_bufs = bufs; - int const orig_num_bufs = num_bufs; + iovec_t tmp; + span tmp_bufs = bufs; if ((flags & file::coalesce_buffers)) { - if (!coalesce_read_buffers(bufs, num_bufs, &tmp)) + if (!coalesce_read_buffers(tmp_bufs, tmp)) // ok, that failed, don't coalesce this read flags &= ~file::coalesce_buffers; } #if TORRENT_USE_PREAD - int ret = iov(&::pread, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::pread, native_handle(), file_offset, tmp_bufs, ec); #else - int ret = iov(&::read, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec); #endif if ((flags & file::coalesce_buffers)) - coalesce_read_buffers_end(orig_bufs, orig_num_bufs + coalesce_read_buffers_end(bufs , static_cast(tmp.iov_base), !ec); #endif @@ -1897,7 +1889,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { // This has to be thread safe, i.e. atomic. // that means, on posix this has to be turned into a series of // pwrite() calls - std::int64_t file::writev(std::int64_t file_offset, iovec_t const* bufs, int num_bufs + std::int64_t file::writev(std::int64_t file_offset, span bufs , error_code& ec, int flags) { if (m_file_handle == INVALID_HANDLE_VALUE) @@ -1910,8 +1902,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { return -1; } TORRENT_ASSERT((m_open_mode & rw_mask) == write_only || (m_open_mode & rw_mask) == read_write); - TORRENT_ASSERT(bufs); - TORRENT_ASSERT(num_bufs > 0); + TORRENT_ASSERT(!bufs.empty()); TORRENT_ASSERT(is_open()); ec.clear(); @@ -1919,27 +1910,27 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { #if TORRENT_USE_PREADV TORRENT_UNUSED(flags); - int ret = iov(&::pwritev, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::pwritev, native_handle(), file_offset, bufs, ec); #else // there's no point in coalescing single buffer writes - if (num_bufs == 1) + if (bufs.size() == 1) { flags &= ~file::coalesce_buffers; } - file::iovec_t tmp; + iovec_t tmp; if (flags & file::coalesce_buffers) { - if (!coalesce_write_buffers(bufs, num_bufs, &tmp)) + if (!coalesce_write_buffers(bufs, tmp)) // ok, that failed, don't coalesce writes flags &= ~file::coalesce_buffers; } #if TORRENT_USE_PREAD - int ret = iov(&::pwrite, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::pwrite, native_handle(), file_offset, bufs, ec); #else - int ret = iov(&::write, native_handle(), file_offset, bufs, num_bufs, ec); + int ret = iov(&::write, native_handle(), file_offset, bufs, ec); #endif if (flags & file::coalesce_buffers) diff --git a/src/part_file.cpp b/src/part_file.cpp index e1795e4e9..1ab3d5265 100644 --- a/src/part_file.cpp +++ b/src/part_file.cpp @@ -95,7 +95,7 @@ namespace libtorrent // parse header std::unique_ptr header(new std::uint32_t[m_header_size]); file::iovec_t b = {header.get(), size_t(m_header_size) }; - int n = m_file.readv(0, &b, 1, ec); + int n = m_file.readv(0, b, ec); if (ec) return; // we don't have a full header. consider the file empty @@ -170,7 +170,7 @@ namespace libtorrent return slot; } - int part_file::writev(file::iovec_t const* bufs, int num_bufs, int piece, int offset, error_code& ec) + int part_file::writev(span bufs, int piece, int offset, error_code& ec) { TORRENT_ASSERT(offset >= 0); std::unique_lock l(m_mutex); @@ -188,10 +188,10 @@ namespace libtorrent l.unlock(); std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(slot) * m_piece_size; - return m_file.writev(slot_offset + offset, bufs, num_bufs, ec); + return m_file.writev(slot_offset + offset, bufs, ec); } - int part_file::readv(file::iovec_t const* bufs, int num_bufs + int part_file::readv(span bufs , int piece, int offset, error_code& ec) { TORRENT_ASSERT(offset >= 0); @@ -213,7 +213,7 @@ namespace libtorrent l.unlock(); std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(slot) * m_piece_size; - return m_file.readv(slot_offset + offset, bufs, num_bufs, ec); + return m_file.readv(slot_offset + offset, bufs, ec); } void part_file::open_file(int mode, error_code& ec) @@ -326,11 +326,11 @@ namespace libtorrent l.unlock(); file::iovec_t v = { buf.get(), size_t(block_to_copy) }; - v.iov_len = m_file.readv(slot_offset + piece_offset, &v, 1, ec); + v.iov_len = m_file.readv(slot_offset + piece_offset, v, ec); TORRENT_ASSERT(!ec); if (ec || v.iov_len == 0) return; - std::int64_t ret = f.writev(file_offset, &v, 1, ec); + std::int64_t ret = f.writev(file_offset, v, ec); TORRENT_ASSERT(ec || ret == v.iov_len); if (ec || ret != v.iov_len) return; @@ -412,7 +412,7 @@ namespace libtorrent std::memset(ptr, 0, m_header_size - (ptr - reinterpret_cast(header.get()))); file::iovec_t b = {header.get(), size_t(m_header_size) }; - m_file.writev(0, &b, 1, ec); + m_file.writev(0, b, ec); if (ec) return; } } diff --git a/src/storage.cpp b/src/storage.cpp index df707d08a..bf9342c0e 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -115,22 +115,18 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - int copy_bufs(file::iovec_t const* bufs, int bytes, file::iovec_t* target) + int copy_bufs(span bufs, int bytes, span target) { int size = 0; - int ret = 1; - for (;;) + for (int i = 0;; i++) { - *target = *bufs; - size += int(bufs->iov_len); + target[i] = bufs[i]; + size += int(bufs[i].iov_len); if (size >= bytes) { - target->iov_len -= size - bytes; - return ret; + target[i].iov_len -= size - bytes; + return i + 1; } - ++bufs; - ++target; - ++ret; } } @@ -151,20 +147,20 @@ namespace libtorrent } } - void clear_bufs(file::iovec_t const* bufs, int num_bufs) + void clear_bufs(span bufs) { - for (file::iovec_t const* i = bufs, *end(bufs + num_bufs); i < end; ++i) - std::memset(i->iov_base, 0, i->iov_len); + for (auto buf : bufs) + std::memset(buf.iov_base, 0, buf.iov_len); } namespace { - int count_bufs(file::iovec_t const* bufs, int bytes) + int count_bufs(span bufs, int bytes) { int size = 0; int count = 1; if (bytes == 0) return 0; - for (file::iovec_t const* i = bufs;; ++i, ++count) + for (auto i = bufs.begin();; ++i, ++count) { size += int(i->iov_len); if (size >= bytes) return count; @@ -225,18 +221,15 @@ namespace libtorrent int file_op(int const file_index , std::int64_t const file_offset - , int const size - , file::iovec_t const* bufs, storage_error& ec) + , span bufs, storage_error& ec) final { if (m_storage.files().pad_file_at(file_index)) { // writing to a pad-file is a no-op - return size; + return bufs_size(bufs); } - int num_bufs = count_bufs(bufs, size); - if (file_index < int(m_storage.m_file_priority.size()) && m_storage.m_file_priority[file_index] == 0) { @@ -245,7 +238,7 @@ namespace libtorrent error_code e; peer_request map = m_storage.files().map_file(file_index , file_offset, 0); - int ret = m_storage.m_part_file->writev(bufs, num_bufs + int ret = m_storage.m_part_file->writev(bufs , map.piece, map.start, e); if (e) @@ -279,7 +272,7 @@ namespace libtorrent error_code e; int ret = handle->writev(adjusted_offset - , bufs, num_bufs, e, m_flags); + , bufs, e, m_flags); // set this unconditionally in case the upper layer would like to treat // short reads as errors @@ -291,7 +284,7 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS write_access_log(adjusted_offset + ret , handle->file_id(), op_end | op_write, clock_type::now()); #endif - TORRENT_ASSERT(ret <= bufs_size(bufs, num_bufs)); + TORRENT_ASSERT(ret <= bufs_size(bufs)); if (e) { @@ -316,17 +309,14 @@ namespace libtorrent int file_op(int const file_index , std::int64_t const file_offset - , int const size - , file::iovec_t const* bufs, storage_error& ec) + , span bufs, storage_error& ec) final { - int num_bufs = count_bufs(bufs, size); - if (m_storage.files().pad_file_at(file_index)) { // reading from a pad file yields zeroes - clear_bufs(bufs, num_bufs); - return size; + clear_bufs(bufs); + return bufs_size(bufs); } if (file_index < int(m_storage.m_file_priority.size()) @@ -337,7 +327,7 @@ namespace libtorrent error_code e; peer_request map = m_storage.files().map_file(file_index , file_offset, 0); - int ret = m_storage.m_part_file->readv(bufs, num_bufs + int ret = m_storage.m_part_file->readv(bufs , map.piece, map.start, e); if (e) @@ -367,7 +357,7 @@ namespace libtorrent error_code e; int ret = handle->readv(adjusted_offset - , bufs, num_bufs, e, m_flags); + , bufs, e, m_flags); // set this unconditionally in case the upper layer would like to treat // short reads as errors @@ -379,7 +369,7 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS write_access_log(adjusted_offset + ret , handle->file_id(), op_end | op_read, clock_type::now()); #endif - TORRENT_ASSERT(ret <= bufs_size(bufs, num_bufs)); + TORRENT_ASSERT(ret <= bufs_size(bufs)); if (e) { @@ -1104,31 +1094,30 @@ namespace libtorrent #ifdef TORRENT_SIMULATE_SLOW_READ std::this_thread::sleep_for(seconds(1)); #endif - return readwritev(files(), bufs.data(), piece, offset, int(bufs.size()), op, ec); + return readwritev(files(), bufs, piece, offset, op, ec); } int default_storage::writev(span bufs , int piece, int offset, int flags, storage_error& ec) { write_fileop op(*this, flags); - return readwritev(files(), bufs.data(), piece, offset, int(bufs.size()), op, ec); + return readwritev(files(), bufs, piece, offset, op, ec); } // much of what needs to be done when reading and writing is buffer // management and piece to file mapping. Most of that is the same for reading // and writing. This function is a template, and the fileop decides what to // do with the file and the buffers. - int readwritev(file_storage const& files, file::iovec_t const* const bufs - , const int piece, const int offset, const int num_bufs, fileop& op + int readwritev(file_storage const& files, span const bufs + , const int piece, const int offset, fileop& op , storage_error& ec) { - TORRENT_ASSERT(bufs != nullptr); TORRENT_ASSERT(piece >= 0); TORRENT_ASSERT(piece < files.num_pieces()); TORRENT_ASSERT(offset >= 0); - TORRENT_ASSERT(num_bufs > 0); + TORRENT_ASSERT(bufs.size() > 0); - const int size = bufs_size(bufs, num_bufs); + const int size = bufs_size(bufs); TORRENT_ASSERT(size > 0); TORRENT_ASSERT(files.is_loaded()); @@ -1148,11 +1137,11 @@ namespace libtorrent // copy the iovec array so we can use it to keep track of our current // location by updating the head base pointer and size. (see // advance_bufs()) - TORRENT_ALLOCA(current_buf, file::iovec_t, num_bufs); - copy_bufs(bufs, size, current_buf.data()); - TORRENT_ASSERT(count_bufs(current_buf.data(), size) == num_bufs); + TORRENT_ALLOCA(current_buf, file::iovec_t, bufs.size()); + copy_bufs(bufs, size, current_buf); + TORRENT_ASSERT(count_bufs(current_buf, size) == bufs.size()); - TORRENT_ALLOCA(tmp_buf, file::iovec_t, num_bufs); + TORRENT_ALLOCA(tmp_buf, file::iovec_t, bufs.size()); // the number of bytes left to read in the current file (specified by // file_index). This is the minimum of (file_size - file_offset) and @@ -1184,10 +1173,10 @@ namespace libtorrent // make a copy of the iovec array that _just_ covers the next // file_bytes_left bytes, i.e. just this one operation - copy_bufs(current_buf.data(), file_bytes_left, tmp_buf.data()); + int tmp_bufs_used = copy_bufs(current_buf, file_bytes_left, tmp_buf); - int bytes_transferred = op.file_op(file_index, file_offset, - file_bytes_left, tmp_buf.data(), ec); + int bytes_transferred = op.file_op(file_index, file_offset + , tmp_buf.first(tmp_bufs_used), ec); if (ec) return -1; // advance our position in the iovec array and the file offset. @@ -1195,7 +1184,7 @@ namespace libtorrent bytes_left -= bytes_transferred; file_offset += bytes_transferred; - TORRENT_ASSERT(count_bufs(current_buf.data(), bytes_left) <= num_bufs); + TORRENT_ASSERT(count_bufs(current_buf, bytes_left) <= bufs.size()); // if the file operation returned 0, we've hit end-of-file. We're done if (bytes_transferred == 0) @@ -1373,12 +1362,12 @@ namespace libtorrent int readv(span bufs , int, int, int, storage_error&) override { - return bufs_size(bufs.data(), int(bufs.size())); + return bufs_size(bufs); } int writev(span bufs , int, int, int, storage_error&) override { - return bufs_size(bufs.data(), int(bufs.size())); + return bufs_size(bufs); } bool verify_resume_data(add_torrent_params const& diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index b9b967347..831fad035 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -616,7 +616,7 @@ namespace libtorrent v.resize(std::size_t(s)); if (s == 0) return 0; file::iovec_t b = {&v[0], size_t(s) }; - std::int64_t read = f.readv(0, &b, 1, ec); + std::int64_t read = f.readv(0, b, ec); if (read != s) return -3; if (ec) return -3; return 0; diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index 130f42b3d..6b6f8dbf1 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -277,7 +277,7 @@ void save_file(char const* filename, char const* data, int size) return; } file::iovec_t b = { (void*)data, size_t(size) }; - out.writev(0, &b, 1, ec); + out.writev(0, b, ec); TEST_CHECK(!ec); if (ec) { @@ -692,7 +692,7 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu { int s = (std::min)(to_write, 300000); file::iovec_t b = { random_data, size_t(s)}; - f.writev(offset, &b, 1, ec); + f.writev(offset, b, ec); if (ec) std::printf("failed to write file \"%s\": (%d) %s\n" , full_path.c_str(), ec.value(), ec.message().c_str()); offset += s; diff --git a/test/test_block_cache.cpp b/test/test_block_cache.cpp index 991749ac5..bbae11c95 100644 --- a/test/test_block_cache.cpp +++ b/test/test_block_cache.cpp @@ -51,12 +51,12 @@ struct test_storage_impl : storage_interface int readv(span bufs , int piece, int offset, int flags, storage_error& ec) override { - return bufs_size(bufs.data(), int(bufs.size())); + return bufs_size(bufs); } int writev(span bufs , int piece, int offset, int flags, storage_error& ec) override { - return bufs_size(bufs.data(), int(bufs.size())); + return bufs_size(bufs); } bool has_any_file(storage_error& ec) override { return false; } @@ -112,8 +112,8 @@ static void nop() {} wj.storage = pm; \ cached_piece_entry* pe = nullptr; \ int ret = 0; \ - file::iovec_t iov[1]; \ - (void)iov[0]; \ + file::iovec_t iov; \ + (void)iov; \ (void)ret; \ (void)pe @@ -153,9 +153,9 @@ static void nop() {} wj.piece = p; \ wj.requester = (void*)1; \ pe = bc.allocate_piece(&wj, cached_piece_entry::read_lru1); \ - ret = bc.allocate_iovec(iov, 1); \ + ret = bc.allocate_iovec(iov); \ TEST_EQUAL(ret, 0); \ - bc.insert_blocks(pe, b, iov, 1, &wj) + bc.insert_blocks(pe, b, iov, &wj) void test_write() { @@ -419,8 +419,8 @@ void test_iovec() { TEST_SETUP; - ret = bc.allocate_iovec(iov, 1); - bc.free_iovec(iov, 1); + ret = bc.allocate_iovec(iov); + bc.free_iovec(iov); } void test_unaligned_read() diff --git a/test/test_file.cpp b/test/test_file.cpp index ba4cec88d..f5a165992 100644 --- a/test/test_file.cpp +++ b/test/test_file.cpp @@ -55,7 +55,7 @@ int touch_file(std::string const& filename, int size) if (!f.open(filename, file::write_only, ec)) return -1; if (ec) return -1; file::iovec_t b = {&v[0], v.size()}; - std::int64_t written = f.writev(0, &b, 1, ec); + std::int64_t written = f.writev(0, b, ec); if (written != int(v.size())) return -3; if (ec) return -3; return 0; @@ -295,14 +295,14 @@ TORRENT_TEST(file) TEST_EQUAL(ec, error_code()); if (ec) std::printf("%s\n", ec.message().c_str()); file::iovec_t b = {(void*)"test", 4}; - TEST_EQUAL(f.writev(0, &b, 1, ec), 4); + TEST_EQUAL(f.writev(0, b, ec), 4); if (ec) std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_CHECK(!ec); char test_buf[5] = {0}; b.iov_base = test_buf; b.iov_len = 4; - TEST_EQUAL(f.readv(0, &b, 1, ec), 4); + TEST_EQUAL(f.readv(0, b, ec), 4); if (ec) std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_EQUAL(ec, error_code()); @@ -325,7 +325,7 @@ TORRENT_TEST(hard_link) TEST_EQUAL(ec, error_code()); file::iovec_t b = {(void*)"abcdefghijklmnopqrstuvwxyz", 26}; - TEST_EQUAL(f.writev(0, &b, 1, ec), 26); + TEST_EQUAL(f.writev(0, b, ec), 26); if (ec) std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_EQUAL(ec, error_code()); @@ -346,7 +346,7 @@ TORRENT_TEST(hard_link) char test_buf[27] = {0}; b.iov_base = test_buf; b.iov_len = 27; - TEST_EQUAL(f.readv(0, &b, 1, ec), 26); + TEST_EQUAL(f.readv(0, b, ec), 26); if (ec) std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_EQUAL(ec, error_code()); @@ -372,7 +372,7 @@ TORRENT_TEST(coalesce_buffer) TEST_EQUAL(ec, error_code()); if (ec) std::printf("%s\n", ec.message().c_str()); file::iovec_t b[2] = {{(void*)"test", 4}, {(void*)"foobar", 6}}; - TEST_EQUAL(f.writev(0, b, 2, ec, file::coalesce_buffers), 4 + 6); + TEST_EQUAL(f.writev(0, {b, 2}, ec, file::coalesce_buffers), 4 + 6); if (ec) std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str()); TEST_CHECK(!ec); @@ -382,7 +382,7 @@ TORRENT_TEST(coalesce_buffer) b[0].iov_len = 4; b[1].iov_base = test_buf2; b[1].iov_len = 6; - TEST_EQUAL(f.readv(0, b, 2, ec), 4 + 6); + TEST_EQUAL(f.readv(0, {b, 2}, ec), 4 + 6); if (ec) { std::printf("readv failed: [%s] %s\n" diff --git a/test/test_http_connection.cpp b/test/test_http_connection.cpp index b7e660807..44f3d9220 100644 --- a/test/test_http_connection.cpp +++ b/test/test_http_connection.cpp @@ -150,7 +150,7 @@ void write_test_file() TEST_CHECK(!ec); if (ec) std::printf("file error: %s\n", ec.message().c_str()); file::iovec_t b = { data_buffer, 3216}; - test_file.writev(0, &b, 1, ec); + test_file.writev(0, b, ec); TEST_CHECK(!ec); if (ec) std::printf("file error: %s\n", ec.message().c_str()); test_file.close(); diff --git a/test/test_part_file.cpp b/test/test_part_file.cpp index b9d2138c1..035a8771a 100644 --- a/test/test_part_file.cpp +++ b/test/test_part_file.cpp @@ -70,7 +70,7 @@ TORRENT_TEST(part_file) for (int i = 0; i < 1024; ++i) buf[i] = i; file::iovec_t v = {&buf, 1024}; - pf.writev(&v, 1, 10, 0, ec); + pf.writev(v, 10, 0, ec); if (ec) std::printf("part_file::writev: %s\n", ec.message().c_str()); pf.flush_metadata(ec); @@ -88,7 +88,7 @@ TORRENT_TEST(part_file) memset(buf, 0, sizeof(buf)); - pf.readv(&v, 1, 10, 0, ec); + pf.readv(v, 10, 0, ec); if (ec) std::printf("part_file::readv: %s\n", ec.message().c_str()); for (int i = 0; i < 1024; ++i) @@ -102,7 +102,7 @@ TORRENT_TEST(part_file) memset(buf, 0, sizeof(buf)); file::iovec_t v = {&buf, 1024}; - pf.readv(&v, 1, 10, 0, ec); + pf.readv(v, 10, 0, ec); if (ec) std::printf("part_file::readv: %s\n", ec.message().c_str()); for (int i = 0; i < 1024; ++i) @@ -137,7 +137,7 @@ TORRENT_TEST(part_file) memset(buf, 0, sizeof(buf)); - output.readv(0, &v, 1, ec); + output.readv(0, v, ec); if (ec) std::printf("exported file read: %s\n", ec.message().c_str()); for (int i = 0; i < 1024; ++i) diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 52f4e0d3d..970dc78d4 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -912,7 +912,7 @@ TORRENT_TEST(iovec_copy_bufs) alloc_iov(iov1, 10); fill_pattern(iov1, 10); - TEST_CHECK(bufs_size(iov1, 10) >= 106); + TEST_CHECK(bufs_size({iov1, 10}) >= 106); // copy exactly 106 bytes from iov1 to iov2 int num_bufs = copy_bufs(iov1, 106, iov2); @@ -941,7 +941,7 @@ TORRENT_TEST(iovec_clear_bufs) alloc_iov(iov, 10); fill_pattern(iov, 10); - clear_bufs(iov, 10); + clear_bufs({iov, 10}); for (int i = 0; i < 10; ++i) { unsigned char* buf = (unsigned char*)iov[i].iov_base; @@ -963,7 +963,7 @@ TORRENT_TEST(iovec_bufs_size) int expected_size = 0; for (int k = 0; k < i; ++k) expected_size += i * (k + 1); - TEST_EQUAL(bufs_size(iov, i), expected_size); + TEST_EQUAL(bufs_size({iov, size_t(i)}), expected_size); free_iov(iov, i); } @@ -1018,8 +1018,8 @@ struct test_fileop : fileop { explicit test_fileop(int stripe_size) : m_stripe_size(stripe_size) {} - int file_op(int const file_index, std::int64_t const file_offset, int const size - , file::iovec_t const* bufs, storage_error& ec) override + int file_op(int const file_index, std::int64_t const file_offset + , span bufs, storage_error& ec) override { size_t offset = size_t(file_offset); if (file_index >= int(m_file_data.size())) @@ -1027,7 +1027,7 @@ struct test_fileop : fileop m_file_data.resize(file_index + 1); } - const int write_size = (std::min)(m_stripe_size, size); + const int write_size = (std::min)(m_stripe_size, bufs_size(bufs)); std::vector& file = m_file_data[file_index]; @@ -1039,9 +1039,9 @@ struct test_fileop : fileop int left = write_size; while (left > 0) { - const int copy_size = (std::min)(left, int(bufs->iov_len)); - memcpy(&file[offset], bufs->iov_base, copy_size); - ++bufs; + const int copy_size = (std::min)(left, int(bufs.front().iov_len)); + memcpy(&file[offset], bufs.front().iov_base, copy_size); + bufs = bufs.subspan(1); offset += copy_size; left -= copy_size; } @@ -1057,15 +1057,15 @@ struct test_read_fileop : fileop // EOF after size bytes read explicit test_read_fileop(int size) : m_size(size), m_counter(0) {} - int file_op(int const file_index, std::int64_t const file_offset, int const size - , file::iovec_t const* bufs, storage_error& ec) override + int file_op(int const file_index, std::int64_t const file_offset + , span bufs, storage_error& ec) override { - int local_size = (std::min)(m_size, size); + int local_size = (std::min)(m_size, bufs_size(bufs)); const int read = local_size; while (local_size > 0) { - unsigned char* p = (unsigned char*)bufs->iov_base; - const int len = (std::min)(int(bufs->iov_len), local_size); + unsigned char* p = (unsigned char*)bufs.front().iov_base; + const int len = (std::min)(int(bufs.front().iov_len), local_size); for (int i = 0; i < len; ++i) { p[i] = m_counter & 0xff; @@ -1073,7 +1073,7 @@ struct test_read_fileop : fileop } local_size -= len; m_size -= len; - ++bufs; + bufs = bufs.subspan(1); } return read; } @@ -1088,8 +1088,8 @@ struct test_error_fileop : fileop explicit test_error_fileop(int error_file) : m_error_file(error_file) {} - int file_op(int const file_index, std::int64_t const file_offset, int const size - , file::iovec_t const* bufs, storage_error& ec) override + int file_op(int const file_index, std::int64_t const file_offset + , span bufs, storage_error& ec) override { if (m_error_file == file_index) { @@ -1099,7 +1099,7 @@ struct test_error_fileop : fileop ec.operation = storage_error::read; return -1; } - return size; + return bufs_size(bufs); } int m_error_file; @@ -1129,14 +1129,14 @@ TORRENT_TEST(readwritev_stripe_1) test_fileop fop(1); storage_error ec; - TEST_CHECK(bufs_size(iov, num_bufs) >= fs.total_size()); + TEST_CHECK(bufs_size({iov, size_t(num_bufs)}) >= fs.total_size()); file::iovec_t iov2[num_bufs]; copy_bufs(iov, int(fs.total_size()), iov2); int num_bufs2 = count_bufs(iov2, int(fs.total_size())); TEST_CHECK(num_bufs2 <= num_bufs); - int ret = readwritev(fs, iov2, 0, 0, num_bufs2, fop, ec); + int ret = readwritev(fs, {iov2, size_t(num_bufs2)}, 0, 0, fop, ec); TEST_EQUAL(ret, fs.total_size()); TEST_EQUAL(fop.m_file_data.size(), 4); @@ -1163,7 +1163,7 @@ TORRENT_TEST(readwritev_single_buffer) file::iovec_t iov = { &buf[0], buf.size() }; fill_pattern(&iov, 1); - int ret = readwritev(fs, &iov, 0, 0, 1, fop, ec); + int ret = readwritev(fs, iov, 0, 0, fop, ec); TEST_EQUAL(ret, fs.total_size()); TEST_EQUAL(fop.m_file_data.size(), 4); @@ -1188,7 +1188,7 @@ TORRENT_TEST(readwritev_read) file::iovec_t iov = { &buf[0], buf.size() }; // read everything - int ret = readwritev(fs, &iov, 0, 0, 1, fop, ec); + int ret = readwritev(fs, iov, 0, 0, fop, ec); TEST_EQUAL(ret, fs.total_size()); TEST_CHECK(check_pattern(buf, 0)); @@ -1205,7 +1205,7 @@ TORRENT_TEST(readwritev_read_short) , static_cast(fs.total_size()) }; // read everything - int ret = readwritev(fs, &iov, 0, 0, 1, fop, ec); + int ret = readwritev(fs, iov, 0, 0, fop, ec); TEST_EQUAL(ec.file, 3); @@ -1225,7 +1225,7 @@ TORRENT_TEST(readwritev_error) , static_cast(fs.total_size()) }; // read everything - int ret = readwritev(fs, &iov, 0, 0, 1, fop, ec); + int ret = readwritev(fs, iov, 0, 0, fop, ec); TEST_EQUAL(ret, -1); TEST_EQUAL(ec.file, 2); @@ -1252,7 +1252,7 @@ TORRENT_TEST(readwritev_zero_size_files) , static_cast(fs.total_size()) }; // read everything - int ret = readwritev(fs, &iov, 0, 0, 1, fop, ec); + int ret = readwritev(fs, iov, 0, 0, fop, ec); TEST_EQUAL(ret, fs.total_size()); TEST_CHECK(check_pattern(buf, 0)); diff --git a/test/test_web_seed_redirect.cpp b/test/test_web_seed_redirect.cpp index b0a320da0..caa673bd4 100644 --- a/test/test_web_seed_redirect.cpp +++ b/test/test_web_seed_redirect.cpp @@ -59,7 +59,7 @@ TORRENT_TEST(web_seed_redirect) return; } file::iovec_t b = { random_data, size_t(16000)}; - f.writev(0, &b, 1, ec); + f.writev(0, b, ec); fs.add_file("test_file", 16000); int port = start_web_server();