factor out some common storage utilities out of storage.cpp (#1515)

factor out some common storage utilities out of storage.cpp
This commit is contained in:
Arvid Norberg 2017-01-11 00:42:10 -05:00 committed by GitHub
parent 3b4867046f
commit 3d06371f31
31 changed files with 381 additions and 285 deletions

View File

@ -86,6 +86,7 @@ set(sources
stat
stat_cache
storage
storage_utils
time
timestamp_history
torrent

View File

@ -609,6 +609,7 @@ SOURCES =
socks5_stream
stat
storage
storage_utils
torrent
torrent_handle
torrent_info

View File

@ -862,7 +862,7 @@ void generate_data(char const* path, torrent_info const& ti)
{
generate_block(piece, i, j, 0x4000);
int const left_in_piece = ti.piece_size(i) - j;
file::iovec_t const b = { piece, size_t(std::min(left_in_piece, 0x4000))};
iovec_t const b = { piece, size_t(std::min(left_in_piece, 0x4000))};
storage_error error;
st->writev(b, i, j, 0, error);
if (error)

View File

@ -187,6 +187,7 @@ nobase_include_HEADERS = \
aux_/win_crypto_provider.hpp \
aux_/win_util.hpp \
aux_/non_owning_handle.hpp \
aux_/storage_utils.hpp \
\
extensions/smart_ban.hpp \
extensions/ut_metadata.hpp \

View File

@ -0,0 +1,86 @@
/*
Copyright (c) 2003-2016, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_STORAGE_UTILS_HPP_INCLUDE
#define TORRENT_STORAGE_UTILS_HPP_INCLUDE
#include <cstdint>
#include "libtorrent/config.hpp"
#include "libtorrent/span.hpp"
#include "libtorrent/units.hpp"
#ifndef TORRENT_WINDOWS
#include <sys/uio.h> // for iovec
#endif
namespace libtorrent
{
class file_storage;
struct storage_error;
#ifdef TORRENT_WINDOWS
struct iovec_t
{
void* iov_base;
size_t iov_len;
};
#else
using iovec_t = ::iovec;
#endif
TORRENT_EXTRA_EXPORT int copy_bufs(span<iovec_t const> bufs, int bytes, span<iovec_t> target);
TORRENT_EXTRA_EXPORT span<iovec_t> advance_bufs(span<iovec_t> bufs, int bytes);
// this identifies a read or write operation so that readwritev() knows
// what to do when it's actually touching the file
struct fileop
{
virtual int file_op(file_index_t const file_index, std::int64_t const file_offset
, span<iovec_t const> bufs, storage_error& ec) = 0;
protected:
~fileop() {}
};
// 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
, span<iovec_t const> bufs, piece_index_t piece, int offset
, fileop& op, storage_error& ec);
}
#endif

View File

@ -424,7 +424,7 @@ 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, span<file::iovec_t const> iov
void insert_blocks(cached_piece_entry* pe, int block, span<iovec_t const> iov
, disk_io_job* j, int flags = 0);
#if TORRENT_USE_INVARIANT_CHECKS

View File

@ -80,8 +80,8 @@ namespace libtorrent
void free_buffer(char* buf);
void free_multiple_buffers(span<char*> bufvec);
int allocate_iovec(span<file::iovec_t> iov);
void free_iovec(span<file::iovec_t const> iov);
int allocate_iovec(span<iovec_t> iov);
void free_iovec(span<iovec_t const> iov);
int block_size() const { return m_block_size; }

View File

@ -443,8 +443,8 @@ namespace libtorrent
// low level flush operations, used by flush_range
int build_iovec(cached_piece_entry* pe, int start, int end
, span<file::iovec_t> iov, span<int> flushing, int block_base_index = 0);
void flush_iovec(cached_piece_entry* pe, span<file::iovec_t const> iov, span<int const> flushing
, span<iovec_t> iov, span<int> flushing, int block_base_index = 0);
void flush_iovec(cached_piece_entry* pe, span<iovec_t const> iov, span<int const> flushing
, int num_blocks, storage_error& error);
void iovec_flushed(cached_piece_entry* pe
, int* flushing, int num_blocks, int block_offset

View File

@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/string_view.hpp"
#include "libtorrent/span.hpp"
#include "libtorrent/aux_/storage_utils.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
@ -265,22 +266,6 @@ namespace libtorrent
attribute_mask = attribute_hidden | attribute_executable
};
#ifdef TORRENT_WINDOWS
struct iovec_t
{
void* iov_base;
size_t iov_len;
};
#else
using iovec_t = iovec;
#endif
#ifdef TORRENT_SOLARIS
using iovec_base_t = char*;
#else
using iovec_base_t = void*;
#endif
file();
file(std::string const& p, int m, error_code& ec);
~file();
@ -315,7 +300,7 @@ namespace libtorrent
#endif
};
TORRENT_EXTRA_EXPORT int bufs_size(span<file::iovec_t const> bufs);
TORRENT_EXTRA_EXPORT int bufs_size(span<iovec_t const> bufs);
}

View File

@ -53,8 +53,8 @@ namespace libtorrent
part_file(std::string const& path, std::string const& name, int num_pieces, int piece_size);
~part_file();
int writev(span<file::iovec_t const> bufs, piece_index_t piece, int offset, error_code& ec);
int readv(span<file::iovec_t const> bufs, piece_index_t piece, int offset, error_code& ec);
int writev(span<iovec_t const> bufs, piece_index_t piece, int offset, error_code& ec);
int readv(span<iovec_t const> bufs, piece_index_t 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

View File

@ -146,9 +146,7 @@ namespace libtorrent
struct cached_piece_entry;
struct add_torrent_params;
TORRENT_EXTRA_EXPORT int copy_bufs(span<file::iovec_t const> bufs, int bytes, span<file::iovec_t> target);
TORRENT_EXTRA_EXPORT span<file::iovec_t> advance_bufs(span<file::iovec_t> bufs, int bytes);
TORRENT_EXTRA_EXPORT void clear_bufs(span<file::iovec_t const> bufs);
TORRENT_EXTRA_EXPORT void clear_bufs(span<iovec_t const> bufs);
struct disk_io_thread;
@ -297,7 +295,7 @@ namespace libtorrent
// These functions should read and write the data in or to the given
// ``piece`` at the given ``offset``. It should read or write
// ``num_bufs`` buffers sequentially, where the size of each buffer is
// specified in the buffer array ``bufs``. The file::iovec_t type has the
// specified in the buffer array ``bufs``. The iovec_t type has the
// following members::
//
// struct iovec_t { void* iov_base; size_t iov_len; };
@ -323,9 +321,9 @@ namespace libtorrent
// The number of bytes read or written should be returned, or -1 on
// error. If there's an error, the ``storage_error`` must be filled out
// to represent the error that occurred.
virtual int readv(span<file::iovec_t const> bufs
virtual int readv(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) = 0;
virtual int writev(span<file::iovec_t const> bufs
virtual int writev(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) = 0;
// This function is called when first checking (or re-checking) the
@ -514,9 +512,9 @@ namespace libtorrent
, storage_error& error) override;
virtual bool tick() override;
int readv(span<file::iovec_t const> bufs
int readv(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) override;
int writev(span<file::iovec_t const> bufs
int writev(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) override;
// if the files in this storage are mapped, returns the mapped
@ -563,24 +561,6 @@ namespace libtorrent
bool m_allocate_files;
};
// this identifies a read or write operation so that readwritev() knows
// what to do when it's actually touching the file
struct fileop
{
virtual int file_op(file_index_t const file_index, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec) = 0;
protected:
~fileop() {}
};
// 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
, span<file::iovec_t const> bufs, piece_index_t piece, int offset
, fileop& op, storage_error& ec);
}
#endif // TORRENT_STORAGE_HPP_INCLUDED

View File

@ -100,7 +100,7 @@ TORRENT_TEST(dht_bootstrap)
sim::default_config cfg;
sim::simulation sim{cfg};
dht_network dht(sim, 2000);
dht_network dht(sim, 3000);
int routing_table_depth = 0;
int num_nodes = 0;

View File

@ -124,11 +124,11 @@ void test_interval(int interval)
// make sure the interval is within 500 ms of what it's supposed to be
// (this accounts for network latencies)
std::int64_t const actual_interval_ms = duration_cast<lt::milliseconds>(announces[i] - last_announce).count();
TEST_CHECK(abs(actual_interval_ms - interval * 1000) < 500);
TEST_CHECK(std::abs(actual_interval_ms - interval * 1000) < 500);
last_announce = announces[i];
std::int64_t const alert_interval_ms = duration_cast<lt::milliseconds>(announce_alerts[i] - last_alert).count();
TEST_CHECK(abs(alert_interval_ms - interval * 1000) < 500);
TEST_CHECK(std::abs(alert_interval_ms - interval * 1000) < 500);
last_alert = announce_alerts[i];
}
}
@ -222,7 +222,7 @@ TORRENT_TEST(event_completed)
{
// the announce should have come approximately the same time we
// completed
TEST_CHECK(abs(completion - timestamp) <= 1);
TEST_CHECK(std::abs(completion - timestamp) <= 1);
TEST_CHECK(has_completed);
break;
}

View File

@ -130,6 +130,7 @@ libtorrent_rasterbar_la_SOURCES = \
stat.cpp \
stat_cache.cpp \
storage.cpp \
storage_utils.cpp \
session_stats.cpp \
string_util.cpp \
torrent.cpp \

View File

@ -1260,7 +1260,7 @@ 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, span<file::iovec_t const> iov
void block_cache::insert_blocks(cached_piece_entry* pe, int block, span<iovec_t const> iov
, disk_io_job* j, int const flags)
{
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS

View File

@ -190,7 +190,7 @@ namespace libtorrent
// this function allocates buffers and
// fills in the iovec array with the buffers
int disk_buffer_pool::allocate_iovec(span<file::iovec_t> iov)
int disk_buffer_pool::allocate_iovec(span<iovec_t> iov)
{
std::unique_lock<std::mutex> l(m_pool_mutex);
for (auto& i : iov)
@ -216,7 +216,7 @@ namespace libtorrent
return 0;
}
void disk_buffer_pool::free_iovec(span<file::iovec_t const> iov)
void disk_buffer_pool::free_iovec(span<iovec_t const> iov)
{
// TODO: perhaps we should sort the buffers here?
std::unique_lock<std::mutex> l(m_pool_mutex);

View File

@ -462,7 +462,7 @@ namespace libtorrent
cont_pieces = static_cast<int>(range_end) - static_cast<int>(range_start);
int const blocks_to_flush = int(p->blocks_in_piece * cont_pieces);
TORRENT_ALLOCA(iov, file::iovec_t, blocks_to_flush);
TORRENT_ALLOCA(iov, 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);
@ -571,7 +571,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
, span<file::iovec_t> iov, span<int> flushing, int const block_base_index)
, span<iovec_t> iov, span<int> flushing, int const block_base_index)
{
DLOG("build_iovec: piece=%d [%d, %d)\n"
, int(pe->piece), start, end);
@ -633,7 +633,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
, span<file::iovec_t const> iov, span<int const> flushing
, span<iovec_t const> iov, span<int const> flushing
, int const num_blocks, storage_error& error)
{
TORRENT_PIECE_ASSERT(!error, pe);
@ -762,7 +762,7 @@ namespace libtorrent
TORRENT_PIECE_ASSERT(start >= 0, pe);
TORRENT_PIECE_ASSERT(start < end, pe);
TORRENT_ALLOCA(iov, file::iovec_t, std::size_t(pe->blocks_in_piece));
TORRENT_ALLOCA(iov, iovec_t, std::size_t(pe->blocks_in_piece));
TORRENT_ALLOCA(flushing, int, std::size_t(pe->blocks_in_piece));
int iov_len = build_iovec(pe, start, end, iov, flushing, 0);
if (iov_len == 0) return 0;
@ -1217,7 +1217,7 @@ namespace libtorrent
int const file_flags = file_flags_for_job(j
, m_settings.get_bool(settings_pack::coalesce_reads));
file::iovec_t b = {j->buffer.disk_block, std::size_t(j->d.io.buffer_size)};
iovec_t b = {j->buffer.disk_block, std::size_t(j->d.io.buffer_size)};
int ret = j->storage->readv(b
, j->piece, j->d.io.offset, file_flags, j->error);
@ -1247,7 +1247,7 @@ namespace libtorrent
int const iov_len = m_disk_cache.pad_job(j, blocks_in_piece
, m_settings.get_int(settings_pack::read_cache_line_size));
TORRENT_ALLOCA(iov, file::iovec_t, iov_len);
TORRENT_ALLOCA(iov, iovec_t, iov_len);
std::unique_lock<std::mutex> l(m_cache_mutex);
@ -1449,7 +1449,7 @@ namespace libtorrent
{
time_point const start_time = clock_type::now();
file::iovec_t const b = {j->buffer.disk_block, std::size_t(j->d.io.buffer_size)};
iovec_t const b = {j->buffer.disk_block, std::size_t(j->d.io.buffer_size)};
int const file_flags = file_flags_for_job(j
, m_settings.get_bool(settings_pack::coalesce_writes));
@ -2141,7 +2141,7 @@ namespace libtorrent
int const file_flags = file_flags_for_job(j
, m_settings.get_bool(settings_pack::coalesce_reads));
file::iovec_t iov;
iovec_t iov;
iov.iov_base = m_disk_cache.allocate_buffer("hashing");
hasher h;
int ret = 0;
@ -2305,7 +2305,7 @@ namespace libtorrent
int next_locked_block = 0;
for (int i = offset / block_size; i < blocks_in_piece; ++i)
{
file::iovec_t iov;
iovec_t iov;
iov.iov_len = (std::min)(block_size, piece_size - offset);
if (next_locked_block < num_locked_blocks

View File

@ -163,7 +163,7 @@ namespace
return WAIT_FAILED;
}
int preadv(HANDLE fd, libtorrent::file::iovec_t const* bufs, int num_bufs, std::int64_t file_offset)
int preadv(HANDLE fd, libtorrent::iovec_t const* bufs, int num_bufs, std::int64_t file_offset)
{
TORRENT_ALLOCA(ol, OVERLAPPED, num_bufs);
std::memset(ol.data(), 0, sizeof(OVERLAPPED) * num_bufs);
@ -233,7 +233,7 @@ done:
return ret;
}
int pwritev(HANDLE fd, libtorrent::file::iovec_t const* bufs, int num_bufs, std::int64_t file_offset)
int pwritev(HANDLE fd, libtorrent::iovec_t const* bufs, int num_bufs, std::int64_t file_offset)
{
TORRENT_ALLOCA(ol, OVERLAPPED, num_bufs);
std::memset(ol.data(), 0, sizeof(OVERLAPPED) * num_bufs);
@ -328,7 +328,7 @@ static_assert((libtorrent::file::sparse & libtorrent::file::attribute_mask) == 0
namespace libtorrent
{
int bufs_size(span<file::iovec_t const> bufs)
int bufs_size(span<iovec_t const> bufs)
{
std::size_t size = 0;
for (auto buf : bufs)
@ -1605,7 +1605,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
namespace {
#if !TORRENT_USE_PREADV
void gather_copy(span<file::iovec_t const> bufs, char* dst)
void gather_copy(span<iovec_t const> bufs, char* dst)
{
std::size_t offset = 0;
for (auto buf : bufs)
@ -1615,7 +1615,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
}
}
void scatter_copy(span<file::iovec_t const> bufs, char const* src)
void scatter_copy(span<iovec_t const> bufs, char const* src)
{
std::size_t offset = 0;
for (auto buf : bufs)
@ -1625,27 +1625,27 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
}
}
bool coalesce_read_buffers(span<file::iovec_t const>& bufs
, file::iovec_t& tmp)
bool coalesce_read_buffers(span<iovec_t const>& bufs
, iovec_t& tmp)
{
int const buf_size = bufs_size(bufs);
char* buf = static_cast<char*>(std::malloc(buf_size));
if (!buf) return false;
tmp.iov_base = buf;
tmp.iov_len = buf_size;
bufs = span<file::iovec_t const>(tmp);
bufs = span<iovec_t const>(tmp);
return true;
}
void coalesce_read_buffers_end(span<file::iovec_t const> bufs
void coalesce_read_buffers_end(span<iovec_t const> bufs
, char* const buf, bool const copy)
{
if (copy) scatter_copy(bufs, buf);
std::free(buf);
}
bool coalesce_write_buffers(span<file::iovec_t const>& bufs
, file::iovec_t& tmp)
bool coalesce_write_buffers(span<iovec_t const>& bufs
, iovec_t& tmp)
{
int const buf_size = bufs_size(bufs);
char* buf = static_cast<char*>(std::malloc(buf_size));
@ -1653,14 +1653,14 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
gather_copy(bufs, buf);
tmp.iov_base = buf;
tmp.iov_len = buf_size;
bufs = span<file::iovec_t const>(tmp);
bufs = span<iovec_t const>(tmp);
return true;
}
#endif // TORRENT_USE_PREADV
template <class Fun>
std::int64_t iov(Fun f, handle_type fd, std::int64_t file_offset
, span<file::iovec_t const> bufs, error_code& ec)
, span<iovec_t const> bufs, error_code& ec)
{
#if TORRENT_USE_PREADV

View File

@ -95,7 +95,7 @@ namespace libtorrent
{
// parse header
std::unique_ptr<std::uint32_t[]> header(new std::uint32_t[m_header_size]);
file::iovec_t b = {header.get(), std::size_t(m_header_size)};
iovec_t b = {header.get(), std::size_t(m_header_size)};
int n = int(m_file.readv(0, b, ec));
if (ec) return;
@ -171,7 +171,7 @@ namespace libtorrent
return slot;
}
int part_file::writev(span<file::iovec_t const> bufs, piece_index_t const piece
int part_file::writev(span<iovec_t const> bufs, piece_index_t const piece
, int offset, error_code& ec)
{
TORRENT_ASSERT(offset >= 0);
@ -190,7 +190,7 @@ namespace libtorrent
return int(m_file.writev(slot_offset + offset, bufs, ec));
}
int part_file::readv(span<file::iovec_t const> bufs
int part_file::readv(span<iovec_t const> bufs
, piece_index_t const piece, int offset, error_code& ec)
{
TORRENT_ASSERT(offset >= 0);
@ -324,7 +324,7 @@ namespace libtorrent
// don't hold the lock during disk I/O
l.unlock();
file::iovec_t v = {buf.get(), std::size_t(block_to_copy)};
iovec_t v = {buf.get(), std::size_t(block_to_copy)};
v.iov_len = std::size_t(m_file.readv(slot_offset + piece_offset, v, ec));
TORRENT_ASSERT(!ec);
if (ec || v.iov_len == 0) return;
@ -409,7 +409,7 @@ namespace libtorrent
}
std::memset(ptr, 0, m_header_size - (ptr - reinterpret_cast<char*>(header.get())));
file::iovec_t b = {header.get(), std::size_t(m_header_size)};
iovec_t b = {header.get(), std::size_t(m_header_size)};
m_file.writev(0, b, ec);
}
}

View File

@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/aux_/storage_utils.hpp"
#include <ctime>
#include <algorithm>
@ -70,7 +71,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/file_pool.hpp"
#include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/alloca.hpp"
#include "libtorrent/stat_cache.hpp"
#include "libtorrent/hex.hpp" // to_hex
// for convert_to_wstring and convert_to_native
@ -113,62 +113,12 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
int copy_bufs(span<file::iovec_t const> bufs, int bytes, span<file::iovec_t> target)
{
int size = 0;
for (int i = 0;; i++)
{
target[i] = bufs[i];
size += int(bufs[i].iov_len);
if (size >= bytes)
{
target[i].iov_len -= size - bytes;
return i + 1;
}
}
}
span<file::iovec_t> advance_bufs(span<file::iovec_t> bufs, int bytes)
{
int size = 0;
for (;;)
{
size += int(bufs.front().iov_len);
if (size >= bytes)
{
bufs.front().iov_base = reinterpret_cast<char*>(bufs.front().iov_base)
+ bufs.front().iov_len - (size - bytes);
bufs.front().iov_len = size - bytes;
return bufs;
}
bufs = bufs.subspan(1);
}
}
void clear_bufs(span<file::iovec_t const> bufs)
void clear_bufs(span<iovec_t const> bufs)
{
for (auto buf : bufs)
std::memset(buf.iov_base, 0, buf.iov_len);
}
namespace {
#if TORRENT_USE_ASSERTS
int count_bufs(span<file::iovec_t const> bufs, int bytes)
{
int size = 0;
int count = 1;
if (bytes == 0) return 0;
for (auto i = bufs.begin();; ++i, ++count)
{
size += int(i->iov_len);
if (size >= bytes) return count;
}
}
#endif
} // anonymous namespace
struct write_fileop final : fileop
{
write_fileop(default_storage& st, int flags)
@ -178,7 +128,7 @@ namespace libtorrent
int file_op(file_index_t const file_index
, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec)
, span<iovec_t const> bufs, storage_error& ec)
final
{
if (m_storage.files().pad_file_at(file_index))
@ -258,7 +208,7 @@ namespace libtorrent
int file_op(file_index_t const file_index
, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec)
, span<iovec_t const> bufs, storage_error& ec)
final
{
if (m_storage.files().pad_file_at(file_index))
@ -1036,7 +986,7 @@ namespace libtorrent
return ret;
}
int default_storage::readv(span<file::iovec_t const> bufs
int default_storage::readv(span<iovec_t const> bufs
, piece_index_t const piece, int offset, int flags, storage_error& ec)
{
read_fileop op(*this, flags);
@ -1047,109 +997,13 @@ namespace libtorrent
return readwritev(files(), bufs, piece, offset, op, ec);
}
int default_storage::writev(span<file::iovec_t const> bufs
int default_storage::writev(span<iovec_t const> bufs
, piece_index_t const piece, int offset, int flags, storage_error& ec)
{
write_fileop op(*this, flags);
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, span<file::iovec_t const> const bufs
, piece_index_t const piece, const int offset, fileop& op
, storage_error& ec)
{
TORRENT_ASSERT(piece >= piece_index_t(0));
TORRENT_ASSERT(piece < files.end_piece());
TORRENT_ASSERT(offset >= 0);
TORRENT_ASSERT(bufs.size() > 0);
const int size = bufs_size(bufs);
TORRENT_ASSERT(size > 0);
// find the file iterator and file offset
std::int64_t const torrent_offset = static_cast<int>(piece) * std::int64_t(files.piece_length()) + offset;
file_index_t file_index = files.file_index_at_offset(torrent_offset);
TORRENT_ASSERT(torrent_offset >= files.file_offset(file_index));
TORRENT_ASSERT(torrent_offset < files.file_offset(file_index) + files.file_size(file_index));
std::int64_t file_offset = torrent_offset - files.file_offset(file_index);
// the number of bytes left before this read or write operation is
// completely satisfied.
int bytes_left = size;
TORRENT_ASSERT(bytes_left >= 0);
// 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, bufs.size());
copy_bufs(bufs, size, current_buf);
TORRENT_ASSERT(count_bufs(current_buf, size) == int(bufs.size()));
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
// bytes_left.
int file_bytes_left;
while (bytes_left > 0)
{
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > files.file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files.file_size(file_index) - file_offset), 0);
// there are no bytes left in this file, move to the next one
// this loop skips over empty files
while (file_bytes_left == 0)
{
++file_index;
file_offset = 0;
TORRENT_ASSERT(file_index < files.end_file());
// this should not happen. bytes_left should be clamped by the total
// size of the torrent, so we should never run off the end of it
if (file_index >= files.end_file()) return size;
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > files.file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files.file_size(file_index) - file_offset), 0);
}
// make a copy of the iovec array that _just_ covers the next
// file_bytes_left bytes, i.e. just this one operation
int tmp_bufs_used = copy_bufs(current_buf, file_bytes_left, tmp_buf);
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.
current_buf = advance_bufs(current_buf, bytes_transferred);
bytes_left -= bytes_transferred;
file_offset += bytes_transferred;
TORRENT_ASSERT(count_bufs(current_buf, bytes_left) <= int(bufs.size()));
// if the file operation returned 0, we've hit end-of-file. We're done
if (bytes_transferred == 0)
{
if (file_bytes_left > 0 )
{
// fill in this information in case the caller wants to treat
// a short-read as an error
ec.file(file_index);
}
return size - bytes_left;
}
}
return size;
}
file_handle default_storage::open_file(file_index_t const file, int mode
, storage_error& ec) const
{
@ -1285,12 +1139,12 @@ namespace libtorrent
void initialize(storage_error&) override {}
status_t move_storage(std::string const&, int, storage_error&) override { return status_t::no_error; }
int readv(span<file::iovec_t const> bufs
int readv(span<iovec_t const> bufs
, piece_index_t, int, int, storage_error&) override
{
return bufs_size(bufs);
}
int writev(span<file::iovec_t const> bufs
int writev(span<iovec_t const> bufs
, piece_index_t, int, int, storage_error&) override
{
return bufs_size(bufs);
@ -1318,7 +1172,7 @@ namespace libtorrent
{
void initialize(storage_error&) override {}
int readv(span<file::iovec_t const> bufs
int readv(span<iovec_t const> bufs
, piece_index_t, int, int, storage_error&) override
{
int ret = 0;
@ -1329,7 +1183,7 @@ namespace libtorrent
}
return 0;
}
int writev(span<file::iovec_t const> bufs
int writev(span<iovec_t const> bufs
, piece_index_t, int, int, storage_error&) override
{
int ret = 0;

187
src/storage_utils.cpp Normal file
View File

@ -0,0 +1,187 @@
/*
Copyright (c) 2003-2016, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/aux_/storage_utils.hpp"
#include "libtorrent/file_storage.hpp"
#include "libtorrent/alloca.hpp"
#include "libtorrent/file.hpp" // for count_bufs
namespace libtorrent
{
int copy_bufs(span<iovec_t const> bufs, int bytes, span<iovec_t> target)
{
int size = 0;
for (int i = 0;; i++)
{
target[i] = bufs[i];
size += int(bufs[i].iov_len);
if (size >= bytes)
{
target[i].iov_len -= size - bytes;
return i + 1;
}
}
}
span<iovec_t> advance_bufs(span<iovec_t> bufs, int bytes)
{
int size = 0;
for (;;)
{
size += int(bufs.front().iov_len);
if (size >= bytes)
{
bufs.front().iov_base = reinterpret_cast<char*>(bufs.front().iov_base)
+ bufs.front().iov_len - (size - bytes);
bufs.front().iov_len = size - bytes;
return bufs;
}
bufs = bufs.subspan(1);
}
}
#if TORRENT_USE_ASSERTS
namespace {
int count_bufs(span<iovec_t const> bufs, int bytes)
{
int size = 0;
int count = 1;
if (bytes == 0) return 0;
for (auto i = bufs.begin();; ++i, ++count)
{
size += int(i->iov_len);
if (size >= bytes) return count;
}
}
}
#endif
// 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, span<iovec_t const> const bufs
, piece_index_t const piece, const int offset, fileop& op
, storage_error& ec)
{
TORRENT_ASSERT(piece >= piece_index_t(0));
TORRENT_ASSERT(piece < files.end_piece());
TORRENT_ASSERT(offset >= 0);
TORRENT_ASSERT(bufs.size() > 0);
const int size = bufs_size(bufs);
TORRENT_ASSERT(size > 0);
// find the file iterator and file offset
std::int64_t const torrent_offset = static_cast<int>(piece) * std::int64_t(files.piece_length()) + offset;
file_index_t file_index = files.file_index_at_offset(torrent_offset);
TORRENT_ASSERT(torrent_offset >= files.file_offset(file_index));
TORRENT_ASSERT(torrent_offset < files.file_offset(file_index) + files.file_size(file_index));
std::int64_t file_offset = torrent_offset - files.file_offset(file_index);
// the number of bytes left before this read or write operation is
// completely satisfied.
int bytes_left = size;
TORRENT_ASSERT(bytes_left >= 0);
// 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, iovec_t, bufs.size());
copy_bufs(bufs, size, current_buf);
TORRENT_ASSERT(count_bufs(current_buf, size) == int(bufs.size()));
TORRENT_ALLOCA(tmp_buf, 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
// bytes_left.
int file_bytes_left;
while (bytes_left > 0)
{
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > files.file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files.file_size(file_index) - file_offset), 0);
// there are no bytes left in this file, move to the next one
// this loop skips over empty files
while (file_bytes_left == 0)
{
++file_index;
file_offset = 0;
TORRENT_ASSERT(file_index < files.end_file());
// this should not happen. bytes_left should be clamped by the total
// size of the torrent, so we should never run off the end of it
if (file_index >= files.end_file()) return size;
file_bytes_left = bytes_left;
if (file_offset + file_bytes_left > files.file_size(file_index))
file_bytes_left = (std::max)(static_cast<int>(files.file_size(file_index) - file_offset), 0);
}
// make a copy of the iovec array that _just_ covers the next
// file_bytes_left bytes, i.e. just this one operation
int tmp_bufs_used = copy_bufs(current_buf, file_bytes_left, tmp_buf);
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.
current_buf = advance_bufs(current_buf, bytes_transferred);
bytes_left -= bytes_transferred;
file_offset += bytes_transferred;
TORRENT_ASSERT(count_bufs(current_buf, bytes_left) <= int(bufs.size()));
// if the file operation returned 0, we've hit end-of-file. We're done
if (bytes_transferred == 0)
{
if (file_bytes_left > 0 )
{
// fill in this information in case the caller wants to treat
// a short-read as an error
ec.file(file_index);
}
return size - bytes_left;
}
}
return size;
}
}

View File

@ -616,7 +616,7 @@ namespace libtorrent
if (ec) return -1;
v.resize(std::size_t(s));
if (s == 0) return 0;
file::iovec_t b = {&v[0], size_t(s) };
iovec_t b = {&v[0], size_t(s) };
std::int64_t read = f.readv(0, b, ec);
if (read != s) return -3;
if (ec) return -3;

View File

@ -190,7 +190,7 @@ void generate_files(libtorrent::torrent_info const& ti, std::string const& path
memcpy(&buffer[o], &data, 1);
}
file::iovec_t b = { &buffer[0], size_t(piece_size) };
iovec_t b = { &buffer[0], size_t(piece_size) };
storage_error ec;
int ret = st.writev(b, i, 0, 0, ec);
if (ret != piece_size || ec)

View File

@ -278,7 +278,7 @@ void save_file(char const* filename, char const* data, int size)
std::printf("ERROR opening file '%s': %s\n", filename, ec.message().c_str());
return;
}
file::iovec_t b = { (void*)data, size_t(size) };
iovec_t b = { (void*)data, size_t(size) };
out.writev(0, b, ec);
TEST_CHECK(!ec);
if (ec)
@ -693,7 +693,7 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu
while (to_write > 0)
{
int s = (std::min)(to_write, 300000);
file::iovec_t b = { random_data, size_t(s)};
iovec_t b = { random_data, size_t(s)};
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());

View File

@ -48,12 +48,12 @@ struct test_storage_impl : storage_interface
{
void initialize(storage_error& ec) override {}
int readv(span<file::iovec_t const> bufs
int readv(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) override
{
return bufs_size(bufs);
}
int writev(span<file::iovec_t const> bufs
int writev(span<iovec_t const> bufs
, piece_index_t piece, int offset, int flags, storage_error& ec) override
{
return bufs_size(bufs);
@ -109,7 +109,7 @@ static void nop() {}
wj.storage = pm; \
cached_piece_entry* pe = nullptr; \
int ret = 0; \
file::iovec_t iov; \
iovec_t iov; \
(void)iov; \
(void)ret; \
(void)pe

View File

@ -54,7 +54,7 @@ int touch_file(std::string const& filename, int size)
error_code ec;
if (!f.open(filename, file::write_only, ec)) return -1;
if (ec) return -1;
file::iovec_t b = {&v[0], v.size()};
iovec_t b = {&v[0], v.size()};
std::int64_t written = f.writev(0, b, ec);
if (written != int(v.size())) return -3;
if (ec) return -3;
@ -300,7 +300,7 @@ TORRENT_TEST(file)
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
TEST_EQUAL(ec, error_code());
if (ec) std::printf("%s\n", ec.message().c_str());
file::iovec_t b = {(void*)"test", 4};
iovec_t b = {(void*)"test", 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());
@ -330,7 +330,7 @@ TORRENT_TEST(hard_link)
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
TEST_EQUAL(ec, error_code());
file::iovec_t b = {(void*)"abcdefghijklmnopqrstuvwxyz", 26};
iovec_t b = {(void*)"abcdefghijklmnopqrstuvwxyz", 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());
@ -377,7 +377,7 @@ TORRENT_TEST(coalesce_buffer)
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
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}};
iovec_t b[2] = {{(void*)"test", 4}, {(void*)"foobar", 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());

View File

@ -151,7 +151,7 @@ void write_test_file()
file test_file("test_file", file::write_only, ec);
TEST_CHECK(!ec);
if (ec) std::printf("file error: %s\n", ec.message().c_str());
file::iovec_t b = { data_buffer, 3216};
iovec_t b = { data_buffer, 3216};
test_file.writev(0, b, ec);
TEST_CHECK(!ec);
if (ec) std::printf("file error: %s\n", ec.message().c_str());

View File

@ -69,7 +69,7 @@ TORRENT_TEST(part_file)
// write something to the metadata file
for (int i = 0; i < 1024; ++i) buf[i] = i;
file::iovec_t v = {&buf, 1024};
iovec_t v = {&buf, 1024};
pf.writev(v, piece_index_t(10), 0, ec);
if (ec) std::printf("part_file::writev: %s\n", ec.message().c_str());
@ -101,7 +101,7 @@ TORRENT_TEST(part_file)
memset(buf, 0, sizeof(buf));
file::iovec_t v = {&buf, 1024};
iovec_t v = {&buf, 1024};
pf.readv(v, piece_index_t(10), 0, ec);
if (ec) std::printf("part_file::readv: %s\n", ec.message().c_str());

View File

@ -239,7 +239,7 @@ void run_storage_tests(std::shared_ptr<torrent_info> info
int ret = 0;
// write piece 1 (in slot 0)
file::iovec_t iov = { piece1.data(), half};
iovec_t iov = { piece1.data(), half};
ret = s->writev(iov, piece_index_t(0), 0, 0, ec);
if (ret != half) print_error("writev", ret, ec);
@ -341,7 +341,7 @@ void test_remove(std::string const& test_path, bool unbuffered)
TEST_CHECK(!exists(combine_path(test_path, combine_path("temp_storage"
, combine_path("folder1", "test2.tmp")))));
file::iovec_t b = {&buf[0], 4};
iovec_t b = {&buf[0], 4};
storage_error se;
s->writev(b, piece_index_t(2), 0, 0, se);
@ -930,7 +930,7 @@ TORRENT_TEST(rename_file_fastresume_deprecated)
}
#endif
void alloc_iov(file::iovec_t* iov, int num_bufs)
void alloc_iov(iovec_t* iov, int num_bufs)
{
for (int i = 0; i < num_bufs; ++i)
{
@ -939,7 +939,7 @@ void alloc_iov(file::iovec_t* iov, int num_bufs)
}
}
void fill_pattern(file::iovec_t* iov, int num_bufs)
void fill_pattern(iovec_t* iov, int num_bufs)
{
int counter = 0;
for (int i = 0; i < num_bufs; ++i)
@ -964,7 +964,7 @@ bool check_pattern(std::vector<char> const& buf, int counter)
return true;
}
void fill_pattern2(file::iovec_t* iov, int num_bufs)
void fill_pattern2(iovec_t* iov, int num_bufs)
{
for (int i = 0; i < num_bufs; ++i)
{
@ -973,7 +973,7 @@ void fill_pattern2(file::iovec_t* iov, int num_bufs)
}
}
void free_iov(file::iovec_t* iov, int num_bufs)
void free_iov(iovec_t* iov, int num_bufs)
{
for (int i = 0; i < num_bufs; ++i)
{
@ -985,8 +985,8 @@ void free_iov(file::iovec_t* iov, int num_bufs)
TORRENT_TEST(iovec_copy_bufs)
{
file::iovec_t iov1[10];
file::iovec_t iov2[10];
iovec_t iov1[10];
iovec_t iov2[10];
alloc_iov(iov1, 10);
fill_pattern(iov1, 10);
@ -1016,7 +1016,7 @@ TORRENT_TEST(iovec_copy_bufs)
TORRENT_TEST(iovec_clear_bufs)
{
file::iovec_t iov[10];
iovec_t iov[10];
alloc_iov(iov, 10);
fill_pattern(iov, 10);
@ -1034,7 +1034,7 @@ TORRENT_TEST(iovec_clear_bufs)
TORRENT_TEST(iovec_bufs_size)
{
file::iovec_t iov[10];
iovec_t iov[10];
for (int i = 1; i < 10; ++i)
{
@ -1050,14 +1050,14 @@ TORRENT_TEST(iovec_bufs_size)
TORRENT_TEST(iovec_advance_bufs)
{
file::iovec_t iov1[10];
file::iovec_t iov2[10];
iovec_t iov1[10];
iovec_t iov2[10];
alloc_iov(iov1, 10);
fill_pattern(iov1, 10);
memcpy(iov2, iov1, sizeof(iov1));
span<file::iovec_t> iov = iov2;
span<iovec_t> iov = iov2;
// advance iov 13 bytes. Make sure what's left fits pattern 1 shifted
// 13 bytes
@ -1098,7 +1098,7 @@ struct test_fileop : libtorrent::fileop
explicit test_fileop(int stripe_size) : m_stripe_size(stripe_size) {}
int file_op(file_index_t const file_index, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec) override
, span<iovec_t const> bufs, storage_error& ec) override
{
size_t offset = size_t(file_offset);
if (file_index >= m_file_data.end_index())
@ -1137,7 +1137,7 @@ struct test_read_fileop : fileop
explicit test_read_fileop(int size) : m_size(size), m_counter(0) {}
int file_op(file_index_t const file_index, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec) override
, span<iovec_t const> bufs, storage_error& ec) override
{
int local_size = std::min(m_size, bufs_size(bufs));
const int read = local_size;
@ -1168,7 +1168,7 @@ struct test_error_fileop : fileop
: m_error_file(error_file) {}
int file_op(file_index_t const file_index, std::int64_t const file_offset
, span<file::iovec_t const> bufs, storage_error& ec) override
, span<iovec_t const> bufs, storage_error& ec) override
{
if (m_error_file == file_index)
{
@ -1184,12 +1184,12 @@ struct test_error_fileop : fileop
file_index_t m_error_file;
};
int count_bufs(file::iovec_t const* bufs, int bytes)
int count_bufs(iovec_t const* bufs, int bytes)
{
int size = 0;
int count = 1;
if (bytes == 0) return 0;
for (file::iovec_t const* i = bufs;; ++i, ++count)
for (iovec_t const* i = bufs;; ++i, ++count)
{
size += int(i->iov_len);
if (size >= bytes) return count;
@ -1199,7 +1199,7 @@ int count_bufs(file::iovec_t const* bufs, int bytes)
TORRENT_TEST(readwritev_stripe_1)
{
const int num_bufs = 30;
file::iovec_t iov[num_bufs];
iovec_t iov[num_bufs];
alloc_iov(iov, num_bufs);
fill_pattern(iov, num_bufs);
@ -1210,7 +1210,7 @@ TORRENT_TEST(readwritev_stripe_1)
TEST_CHECK(bufs_size({iov, size_t(num_bufs)}) >= fs.total_size());
file::iovec_t iov2[num_bufs];
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);
@ -1239,7 +1239,7 @@ TORRENT_TEST(readwritev_single_buffer)
storage_error ec;
std::vector<char> buf(size_t(fs.total_size()));
file::iovec_t iov = { &buf[0], buf.size() };
iovec_t iov = { &buf[0], buf.size() };
fill_pattern(&iov, 1);
int ret = readwritev(fs, iov, piece_index_t(0), 0, fop, ec);
@ -1264,7 +1264,7 @@ TORRENT_TEST(readwritev_read)
storage_error ec;
std::vector<char> buf(size_t(fs.total_size()));
file::iovec_t iov = { &buf[0], buf.size() };
iovec_t iov = { &buf[0], buf.size() };
// read everything
int ret = readwritev(fs, iov, piece_index_t(0), 0, fop, ec);
@ -1280,7 +1280,7 @@ TORRENT_TEST(readwritev_read_short)
storage_error ec;
std::vector<char> buf(size_t(fs.total_size()));
file::iovec_t iov = { &buf[0]
iovec_t iov = { &buf[0]
, static_cast<size_t>(fs.total_size()) };
// read everything
@ -1300,7 +1300,7 @@ TORRENT_TEST(readwritev_error)
storage_error ec;
std::vector<char> buf(size_t(fs.total_size()));
file::iovec_t iov = { &buf[0]
iovec_t iov = { &buf[0]
, static_cast<size_t>(fs.total_size()) };
// read everything
@ -1327,7 +1327,7 @@ TORRENT_TEST(readwritev_zero_size_files)
storage_error ec;
std::vector<char> buf(size_t(fs.total_size()));
file::iovec_t iov = { &buf[0]
iovec_t iov = { &buf[0]
, static_cast<size_t>(fs.total_size()) };
// read everything
@ -1364,7 +1364,7 @@ TORRENT_TEST(move_storage_to_self)
disk_buffer_pool dp(16 * 1024, ios, std::bind(&nop));
std::shared_ptr<default_storage> s = setup_torrent(fs, fp, buf, save_path, set);
file::iovec_t const b = {&buf[0], 4};
iovec_t const b = {&buf[0], 4};
storage_error se;
s->writev(b, piece_index_t(1), 0, 0, se);
@ -1393,7 +1393,7 @@ TORRENT_TEST(move_storage_into_self)
disk_buffer_pool dp(16 * 1024, ios, std::bind(&nop));
std::shared_ptr<default_storage> s = setup_torrent(fs, fp, buf, save_path, set);
file::iovec_t const b = {&buf[0], 4};
iovec_t const b = {&buf[0], 4};
storage_error se;
s->writev(b, piece_index_t(2), 0, 0, se);
@ -1439,7 +1439,7 @@ TORRENT_TEST(dont_move_intermingled_files)
disk_buffer_pool dp(16 * 1024, ios, std::bind(&nop));
std::shared_ptr<default_storage> s = setup_torrent(fs, fp, buf, save_path, set);
file::iovec_t b = {&buf[0], 4};
iovec_t b = {&buf[0], 4};
storage_error se;
s->writev(b, piece_index_t(2), 0, 0, se);

View File

@ -87,7 +87,7 @@ struct test_storage : default_storage
}
int writev(
span<file::iovec_t const> bufs
span<iovec_t const> bufs
, piece_index_t piece_index
, int offset
, int flags

View File

@ -58,7 +58,7 @@ TORRENT_TEST(web_seed_redirect)
TEST_ERROR("failed to create file");
return;
}
file::iovec_t b = { random_data, size_t(16000)};
iovec_t b = { random_data, size_t(16000)};
f.writev(0, b, ec);
fs.add_file("test_file", 16000);