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:
parent
3b4867046f
commit
3d06371f31
|
@ -86,6 +86,7 @@ set(sources
|
|||
stat
|
||||
stat_cache
|
||||
storage
|
||||
storage_utils
|
||||
time
|
||||
timestamp_history
|
||||
torrent
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -609,6 +609,7 @@ SOURCES =
|
|||
socks5_stream
|
||||
stat
|
||||
storage
|
||||
storage_utils
|
||||
torrent
|
||||
torrent_handle
|
||||
torrent_info
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
26
src/file.cpp
26
src/file.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
166
src/storage.cpp
166
src/storage.cpp
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue