forked from premiere/premiere-libtorrent
make file open mode flags be an enum class for type-safety
This commit is contained in:
parent
77dcc5363f
commit
ffaabd846c
|
@ -869,7 +869,7 @@ void generate_data(char const* path, torrent_info const& ti)
|
||||||
iovec_t const b = { reinterpret_cast<char*>(piece)
|
iovec_t const b = { reinterpret_cast<char*>(piece)
|
||||||
, size_t(std::min(left_in_piece, 0x4000))};
|
, size_t(std::min(left_in_piece, 0x4000))};
|
||||||
storage_error error;
|
storage_error error;
|
||||||
st->writev(b, i, j, 0, error);
|
st->writev(b, i, j, open_mode_t::write_only, error);
|
||||||
if (error)
|
if (error)
|
||||||
std::fprintf(stderr, "storage error: %s\n", error.ec.message().c_str());
|
std::fprintf(stderr, "storage error: %s\n", error.ec.message().c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ nobase_include_HEADERS = \
|
||||||
file_pool.hpp \
|
file_pool.hpp \
|
||||||
file_storage.hpp \
|
file_storage.hpp \
|
||||||
fingerprint.hpp \
|
fingerprint.hpp \
|
||||||
|
flags.hpp \
|
||||||
fwd.hpp \
|
fwd.hpp \
|
||||||
gzip.hpp \
|
gzip.hpp \
|
||||||
hasher.hpp \
|
hasher.hpp \
|
||||||
|
|
|
@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/string_view.hpp"
|
#include "libtorrent/string_view.hpp"
|
||||||
#include "libtorrent/span.hpp"
|
#include "libtorrent/span.hpp"
|
||||||
#include "libtorrent/aux_/storage_utils.hpp"
|
#include "libtorrent/aux_/storage_utils.hpp"
|
||||||
|
#include "libtorrent/flags.hpp"
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||||
|
|
||||||
|
@ -125,77 +126,86 @@ namespace libtorrent {
|
||||||
|
|
||||||
using file_handle = std::shared_ptr<file>;
|
using file_handle = std::shared_ptr<file>;
|
||||||
|
|
||||||
|
// the open mode for files. Used for the file constructor or
|
||||||
|
// file::open().
|
||||||
|
enum class open_mode_t : std::uint32_t
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
|
||||||
|
// open the file for reading only
|
||||||
|
read_only = 0,
|
||||||
|
|
||||||
|
// open the file for writing only
|
||||||
|
write_only = 1,
|
||||||
|
|
||||||
|
// open the file for reading and writing
|
||||||
|
read_write = 2,
|
||||||
|
|
||||||
|
// the mask for the bits determining read or write mode
|
||||||
|
rw_mask = read_only | write_only | read_write,
|
||||||
|
|
||||||
|
// open the file in sparse mode (if supported by the
|
||||||
|
// filesystem).
|
||||||
|
sparse = 0x4,
|
||||||
|
|
||||||
|
// don't update the access timestamps on the file (if
|
||||||
|
// supported by the operating system and filesystem).
|
||||||
|
// this generally improves disk performance.
|
||||||
|
no_atime = 0x8,
|
||||||
|
|
||||||
|
// open the file for random access. This disables read-ahead
|
||||||
|
// logic
|
||||||
|
random_access = 0x10,
|
||||||
|
|
||||||
|
// prevent the file from being opened by another process
|
||||||
|
// while it's still being held open by this handle
|
||||||
|
lock_file = 0x20,
|
||||||
|
|
||||||
|
// don't put any pressure on the OS disk cache
|
||||||
|
// because of access to this file. We expect our
|
||||||
|
// files to be fairly large, and there is already
|
||||||
|
// a cache at the bittorrent block level. This
|
||||||
|
// may improve overall system performance by
|
||||||
|
// leaving running applications in the page cache
|
||||||
|
no_cache = 0x40,
|
||||||
|
|
||||||
|
// this is only used for readv/writev flags
|
||||||
|
coalesce_buffers = 0x100,
|
||||||
|
|
||||||
|
// when creating a file, set the hidden attribute (windows only)
|
||||||
|
attribute_hidden = 0x200,
|
||||||
|
|
||||||
|
// when creating a file, set the executable attribute
|
||||||
|
attribute_executable = 0x400,
|
||||||
|
|
||||||
|
// the mask of all attribute bits
|
||||||
|
attribute_mask = attribute_hidden | attribute_executable
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace flags {
|
||||||
|
template <>
|
||||||
|
struct enable_flag_operators<open_mode_t> : std::true_type {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace flags;
|
||||||
|
|
||||||
struct TORRENT_EXTRA_EXPORT file : boost::noncopyable
|
struct TORRENT_EXTRA_EXPORT file : boost::noncopyable
|
||||||
{
|
{
|
||||||
// the open mode for files. Used for the file constructor or
|
|
||||||
// file::open().
|
|
||||||
enum open_mode_t : std::uint32_t
|
|
||||||
{
|
|
||||||
// open the file for reading only
|
|
||||||
read_only = 0,
|
|
||||||
|
|
||||||
// open the file for writing only
|
|
||||||
write_only = 1,
|
|
||||||
|
|
||||||
// open the file for reading and writing
|
|
||||||
read_write = 2,
|
|
||||||
|
|
||||||
// the mask for the bits determining read or write mode
|
|
||||||
rw_mask = read_only | write_only | read_write,
|
|
||||||
|
|
||||||
// open the file in sparse mode (if supported by the
|
|
||||||
// filesystem).
|
|
||||||
sparse = 0x4,
|
|
||||||
|
|
||||||
// don't update the access timestamps on the file (if
|
|
||||||
// supported by the operating system and filesystem).
|
|
||||||
// this generally improves disk performance.
|
|
||||||
no_atime = 0x8,
|
|
||||||
|
|
||||||
// open the file for random access. This disables read-ahead
|
|
||||||
// logic
|
|
||||||
random_access = 0x10,
|
|
||||||
|
|
||||||
// prevent the file from being opened by another process
|
|
||||||
// while it's still being held open by this handle
|
|
||||||
lock_file = 0x20,
|
|
||||||
|
|
||||||
// don't put any pressure on the OS disk cache
|
|
||||||
// because of access to this file. We expect our
|
|
||||||
// files to be fairly large, and there is already
|
|
||||||
// a cache at the bittorrent block level. This
|
|
||||||
// may improve overall system performance by
|
|
||||||
// leaving running applications in the page cache
|
|
||||||
no_cache = 0x40,
|
|
||||||
|
|
||||||
// this is only used for readv/writev flags
|
|
||||||
coalesce_buffers = 0x100,
|
|
||||||
|
|
||||||
// when creating a file, set the hidden attribute (windows only)
|
|
||||||
attribute_hidden = 0x200,
|
|
||||||
|
|
||||||
// when creating a file, set the executable attribute
|
|
||||||
attribute_executable = 0x400,
|
|
||||||
|
|
||||||
// the mask of all attribute bits
|
|
||||||
attribute_mask = attribute_hidden | attribute_executable
|
|
||||||
};
|
|
||||||
|
|
||||||
file();
|
file();
|
||||||
file(std::string const& p, std::uint32_t m, error_code& ec);
|
file(std::string const& p, open_mode_t m, error_code& ec);
|
||||||
~file();
|
~file();
|
||||||
|
|
||||||
bool open(std::string const& p, std::uint32_t m, error_code& ec);
|
bool open(std::string const& p, open_mode_t m, error_code& ec);
|
||||||
bool is_open() const;
|
bool is_open() const;
|
||||||
void close();
|
void close();
|
||||||
bool set_size(std::int64_t size, error_code& ec);
|
bool set_size(std::int64_t size, error_code& ec);
|
||||||
|
|
||||||
std::uint32_t open_mode() const { return m_open_mode; }
|
open_mode_t open_mode() const { return m_open_mode; }
|
||||||
|
|
||||||
std::int64_t writev(std::int64_t file_offset, span<iovec_t const> bufs
|
std::int64_t writev(std::int64_t file_offset, span<iovec_t const> bufs
|
||||||
, error_code& ec, std::uint32_t flags = 0);
|
, error_code& ec, open_mode_t flags = open_mode_t::none);
|
||||||
std::int64_t readv(std::int64_t file_offset, span<iovec_t const> bufs
|
std::int64_t readv(std::int64_t file_offset, span<iovec_t const> bufs
|
||||||
, error_code& ec, std::uint32_t flags = 0);
|
, error_code& ec, open_mode_t flags = open_mode_t::none);
|
||||||
|
|
||||||
std::int64_t get_size(error_code& ec) const;
|
std::int64_t get_size(error_code& ec) const;
|
||||||
|
|
||||||
|
@ -209,7 +219,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
handle_type m_file_handle;
|
handle_type m_file_handle;
|
||||||
|
|
||||||
std::uint32_t m_open_mode;
|
open_mode_t m_open_mode = open_mode_t::none;
|
||||||
#if defined TORRENT_WINDOWS
|
#if defined TORRENT_WINDOWS
|
||||||
static bool has_manage_volume_privs;
|
static bool has_manage_volume_privs;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace libtorrent {
|
||||||
// file_storage ``fs`` opened at save path ``p``. ``m`` is the
|
// file_storage ``fs`` opened at save path ``p``. ``m`` is the
|
||||||
// file open mode (see file::open_mode_t).
|
// file open mode (see file::open_mode_t).
|
||||||
file_handle open_file(storage_index_t st, std::string const& p
|
file_handle open_file(storage_index_t st, std::string const& p
|
||||||
, file_index_t file_index, file_storage const& fs, std::uint32_t m
|
, file_index_t file_index, file_storage const& fs, open_mode_t m
|
||||||
, error_code& ec);
|
, error_code& ec);
|
||||||
// release all files belonging to the specified storage_interface (``st``)
|
// release all files belonging to the specified storage_interface (``st``)
|
||||||
// the overload that takes ``file_index`` releases only the file with
|
// the overload that takes ``file_index`` releases only the file with
|
||||||
|
@ -111,7 +111,7 @@ namespace libtorrent {
|
||||||
file_handle file_ptr;
|
file_handle file_ptr;
|
||||||
time_point const opened{aux::time_now()};
|
time_point const opened{aux::time_now()};
|
||||||
time_point last_use{opened};
|
time_point last_use{opened};
|
||||||
std::uint32_t mode = 0;
|
open_mode_t mode = open_mode_t::none;
|
||||||
};
|
};
|
||||||
|
|
||||||
// maps storage pointer, file index pairs to the
|
// maps storage pointer, file index pairs to the
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2017, 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_FLAGS_HPP_INCLUDED
|
||||||
|
#define TORRENT_FLAGS_HPP_INCLUDED
|
||||||
|
|
||||||
|
// this is based on Anthony William's article:
|
||||||
|
// https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html
|
||||||
|
|
||||||
|
#include <type_traits> // for enable_if
|
||||||
|
|
||||||
|
namespace libtorrent {
|
||||||
|
namespace flags {
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
struct enable_flag_operators : std::false_type {};
|
||||||
|
|
||||||
|
#define ENUM_OPERATOR(op) \
|
||||||
|
template<typename E> \
|
||||||
|
constexpr typename std::enable_if<enable_flag_operators<E>::value, E>::type \
|
||||||
|
operator op (E const lhs, E const rhs) { \
|
||||||
|
using underlying = typename std::underlying_type<E>::type; \
|
||||||
|
return static_cast<E>( \
|
||||||
|
static_cast<underlying>(lhs) op static_cast<underlying>(rhs)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template<typename E> \
|
||||||
|
typename std::enable_if<enable_flag_operators<E>::value, E&>::type \
|
||||||
|
operator op##= (E& lhs, E const rhs) { \
|
||||||
|
using underlying = typename std::underlying_type<E>::type; \
|
||||||
|
lhs = static_cast<E>( \
|
||||||
|
static_cast<underlying>(lhs) op static_cast<underlying>(rhs)); \
|
||||||
|
return lhs; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ENUM_OPERATOR(|)
|
||||||
|
ENUM_OPERATOR(&)
|
||||||
|
ENUM_OPERATOR(^)
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
constexpr typename std::enable_if<enable_flag_operators<E>::value, E>::type
|
||||||
|
operator~ (E const operand) {
|
||||||
|
using underlying = typename std::underlying_type<E>::type;
|
||||||
|
return static_cast<E>(~static_cast<underlying>(operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
constexpr typename std::enable_if<enable_flag_operators<E>::value, bool>::type
|
||||||
|
test(E const operand) {
|
||||||
|
using underlying = typename std::underlying_type<E>::type;
|
||||||
|
return static_cast<underlying>(operand) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ENUM_OPERATOR
|
||||||
|
|
||||||
|
} // flags
|
||||||
|
} // libtorrent
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void open_file(std::uint32_t mode, error_code& ec);
|
void open_file(open_mode_t mode, error_code& ec);
|
||||||
void flush_metadata_impl(error_code& ec);
|
void flush_metadata_impl(error_code& ec);
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
|
|
|
@ -208,9 +208,9 @@ namespace libtorrent {
|
||||||
// error. If there's an error, the ``storage_error`` must be filled out
|
// error. If there's an error, the ``storage_error`` must be filled out
|
||||||
// to represent the error that occurred.
|
// to represent the error that occurred.
|
||||||
virtual int readv(span<iovec_t const> bufs
|
virtual int readv(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) = 0;
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) = 0;
|
||||||
virtual int writev(span<iovec_t const> bufs
|
virtual int writev(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) = 0;
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) = 0;
|
||||||
|
|
||||||
// This function is called when first checking (or re-checking) the
|
// This function is called when first checking (or re-checking) the
|
||||||
// storage for a torrent. It should return true if any of the files that
|
// storage for a torrent. It should return true if any of the files that
|
||||||
|
@ -398,9 +398,9 @@ namespace libtorrent {
|
||||||
virtual bool tick() override;
|
virtual bool tick() override;
|
||||||
|
|
||||||
int readv(span<iovec_t const> bufs
|
int readv(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) override;
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) override;
|
||||||
int writev(span<iovec_t const> bufs
|
int writev(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) override;
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) override;
|
||||||
|
|
||||||
// if the files in this storage are mapped, returns the mapped
|
// if the files in this storage are mapped, returns the mapped
|
||||||
// file_storage, otherwise returns the original file_storage object.
|
// file_storage, otherwise returns the original file_storage object.
|
||||||
|
@ -424,8 +424,8 @@ namespace libtorrent {
|
||||||
mutable stat_cache m_stat_cache;
|
mutable stat_cache m_stat_cache;
|
||||||
|
|
||||||
// helper function to open a file in the file pool with the right mode
|
// helper function to open a file in the file pool with the right mode
|
||||||
file_handle open_file(file_index_t file, std::uint32_t mode, storage_error& ec) const;
|
file_handle open_file(file_index_t file, open_mode_t mode, storage_error& ec) const;
|
||||||
file_handle open_file_impl(file_index_t file, std::uint32_t mode, error_code& ec) const;
|
file_handle open_file_impl(file_index_t file, open_mode_t mode, error_code& ec) const;
|
||||||
|
|
||||||
aux::vector<std::uint8_t, file_index_t> m_file_priority;
|
aux::vector<std::uint8_t, file_index_t> m_file_priority;
|
||||||
std::string m_save_path;
|
std::string m_save_path;
|
||||||
|
|
|
@ -117,12 +117,12 @@ namespace libtorrent {
|
||||||
|
|
||||||
#endif // DEBUG_DISK_THREAD
|
#endif // DEBUG_DISK_THREAD
|
||||||
|
|
||||||
std::uint32_t file_flags_for_job(disk_io_job* j
|
open_mode_t file_flags_for_job(disk_io_job* j
|
||||||
, bool const coalesce_buffers)
|
, bool const coalesce_buffers)
|
||||||
{
|
{
|
||||||
std::uint32_t ret = 0;
|
open_mode_t ret = open_mode_t::none;
|
||||||
if (!(j->flags & disk_interface::sequential_access)) ret |= file::random_access;
|
if (!(j->flags & disk_interface::sequential_access)) ret |= open_mode_t::random_access;
|
||||||
if (coalesce_buffers) ret |= file::coalesce_buffers;
|
if (coalesce_buffers) ret |= open_mode_t::coalesce_buffers;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,8 +664,8 @@ namespace libtorrent {
|
||||||
DLOG("]\n");
|
DLOG("]\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::uint32_t const file_flags = m_settings.get_bool(settings_pack::coalesce_writes)
|
open_mode_t const file_flags = m_settings.get_bool(settings_pack::coalesce_writes)
|
||||||
? file::coalesce_buffers : static_cast<file::open_mode_t>(0);
|
? open_mode_t::coalesce_buffers : open_mode_t::none;
|
||||||
|
|
||||||
// issue the actual write operation
|
// issue the actual write operation
|
||||||
auto iov_start = iov;
|
auto iov_start = iov;
|
||||||
|
@ -1232,7 +1232,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
time_point const start_time = clock_type::now();
|
time_point const start_time = clock_type::now();
|
||||||
|
|
||||||
std::uint32_t const file_flags = file_flags_for_job(j
|
open_mode_t const file_flags = file_flags_for_job(j
|
||||||
, m_settings.get_bool(settings_pack::coalesce_reads));
|
, m_settings.get_bool(settings_pack::coalesce_reads));
|
||||||
iovec_t b = {buffer.get(), std::size_t(j->d.io.buffer_size)};
|
iovec_t b = {buffer.get(), std::size_t(j->d.io.buffer_size)};
|
||||||
|
|
||||||
|
@ -1308,7 +1308,7 @@ namespace libtorrent {
|
||||||
// can remove them. We can now release the cache std::mutex and dive into the
|
// can remove them. We can now release the cache std::mutex and dive into the
|
||||||
// disk operations.
|
// disk operations.
|
||||||
|
|
||||||
std::uint32_t const file_flags = file_flags_for_job(j
|
open_mode_t const file_flags = file_flags_for_job(j
|
||||||
, m_settings.get_bool(settings_pack::coalesce_reads));
|
, m_settings.get_bool(settings_pack::coalesce_reads));
|
||||||
time_point const start_time = clock_type::now();
|
time_point const start_time = clock_type::now();
|
||||||
|
|
||||||
|
@ -1467,7 +1467,7 @@ namespace libtorrent {
|
||||||
auto buffer = std::move(boost::get<disk_buffer_holder>(j->argument));
|
auto buffer = std::move(boost::get<disk_buffer_holder>(j->argument));
|
||||||
|
|
||||||
iovec_t const b = { buffer.get(), std::size_t(j->d.io.buffer_size)};
|
iovec_t const b = { buffer.get(), std::size_t(j->d.io.buffer_size)};
|
||||||
std::uint32_t const file_flags = file_flags_for_job(j
|
open_mode_t const file_flags = file_flags_for_job(j
|
||||||
, m_settings.get_bool(settings_pack::coalesce_writes));
|
, m_settings.get_bool(settings_pack::coalesce_writes));
|
||||||
|
|
||||||
m_stats_counters.inc_stats_counter(counters::num_writing_threads, 1);
|
m_stats_counters.inc_stats_counter(counters::num_writing_threads, 1);
|
||||||
|
@ -2155,7 +2155,7 @@ namespace libtorrent {
|
||||||
int const piece_size = j->storage->files().piece_size(j->piece);
|
int const piece_size = j->storage->files().piece_size(j->piece);
|
||||||
int const block_size = m_disk_cache.block_size();
|
int const block_size = m_disk_cache.block_size();
|
||||||
int const blocks_in_piece = (piece_size + block_size - 1) / block_size;
|
int const blocks_in_piece = (piece_size + block_size - 1) / block_size;
|
||||||
std::uint32_t const file_flags = file_flags_for_job(j
|
open_mode_t const file_flags = file_flags_for_job(j
|
||||||
, m_settings.get_bool(settings_pack::coalesce_reads));
|
, m_settings.get_bool(settings_pack::coalesce_reads));
|
||||||
|
|
||||||
iovec_t iov = { m_disk_cache.allocate_buffer("hashing")
|
iovec_t iov = { m_disk_cache.allocate_buffer("hashing")
|
||||||
|
@ -2200,7 +2200,7 @@ namespace libtorrent {
|
||||||
status_t disk_io_thread::do_hash(disk_io_job* j, jobqueue_t& /* completed_jobs */ )
|
status_t disk_io_thread::do_hash(disk_io_job* j, jobqueue_t& /* completed_jobs */ )
|
||||||
{
|
{
|
||||||
int const piece_size = j->storage->files().piece_size(j->piece);
|
int const piece_size = j->storage->files().piece_size(j->piece);
|
||||||
std::uint32_t const file_flags = file_flags_for_job(j
|
open_mode_t const file_flags = file_flags_for_job(j
|
||||||
, m_settings.get_bool(settings_pack::coalesce_reads));
|
, m_settings.get_bool(settings_pack::coalesce_reads));
|
||||||
|
|
||||||
std::unique_lock<std::mutex> l(m_cache_mutex);
|
std::unique_lock<std::mutex> l(m_cache_mutex);
|
||||||
|
|
103
src/file.cpp
103
src/file.cpp
|
@ -326,10 +326,6 @@ done:
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static_assert((libtorrent::file::rw_mask & libtorrent::file::sparse) == 0, "internal flags error");
|
|
||||||
static_assert((libtorrent::file::rw_mask & libtorrent::file::attribute_mask) == 0, "internal flags error");
|
|
||||||
static_assert((libtorrent::file::sparse & libtorrent::file::attribute_mask) == 0, "internal flags error");
|
|
||||||
|
|
||||||
#if defined TORRENT_WINDOWS && defined UNICODE && !TORRENT_USE_WSTRING
|
#if defined TORRENT_WINDOWS && defined UNICODE && !TORRENT_USE_WSTRING
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -342,6 +338,10 @@ static_assert((libtorrent::file::sparse & libtorrent::file::attribute_mask) == 0
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
|
|
||||||
|
static_assert((open_mode_t::rw_mask & open_mode_t::sparse) == open_mode_t::none, "internal flags error");
|
||||||
|
static_assert((open_mode_t::rw_mask & open_mode_t::attribute_mask) == open_mode_t::none, "internal flags error");
|
||||||
|
static_assert((open_mode_t::sparse & open_mode_t::attribute_mask) == open_mode_t::none, "internal flags error");
|
||||||
|
|
||||||
directory::directory(std::string const& path, error_code& ec)
|
directory::directory(std::string const& path, error_code& ec)
|
||||||
: m_done(false)
|
: m_done(false)
|
||||||
{
|
{
|
||||||
|
@ -505,14 +505,11 @@ namespace libtorrent {
|
||||||
bool file::has_manage_volume_privs = get_manage_volume_privs();
|
bool file::has_manage_volume_privs = get_manage_volume_privs();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
file::file()
|
file::file() : m_file_handle(INVALID_HANDLE_VALUE)
|
||||||
: m_file_handle(INVALID_HANDLE_VALUE)
|
|
||||||
, m_open_mode(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
file::file(std::string const& path, std::uint32_t const mode, error_code& ec)
|
file::file(std::string const& path, open_mode_t const mode, error_code& ec)
|
||||||
: m_file_handle(INVALID_HANDLE_VALUE)
|
: m_file_handle(INVALID_HANDLE_VALUE)
|
||||||
, m_open_mode(0)
|
|
||||||
{
|
{
|
||||||
// the return value is not important, since the
|
// the return value is not important, since the
|
||||||
// error code contains the same information
|
// error code contains the same information
|
||||||
|
@ -524,20 +521,20 @@ namespace libtorrent {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool file::open(std::string const& path, std::uint32_t mode, error_code& ec)
|
bool file::open(std::string const& path, open_mode_t mode, error_code& ec)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
native_path_string file_path = convert_to_native_path_string(path);
|
native_path_string file_path = convert_to_native_path_string(path);
|
||||||
|
|
||||||
#ifdef TORRENT_WINDOWS
|
#ifdef TORRENT_WINDOWS
|
||||||
|
|
||||||
struct open_mode_t
|
struct win_open_mode_t
|
||||||
{
|
{
|
||||||
DWORD rw_mode;
|
DWORD rw_mode;
|
||||||
DWORD create_mode;
|
DWORD create_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const open_mode_t mode_array[] =
|
static std::array<win_open_mode_t, 3> const mode_array{
|
||||||
{
|
{
|
||||||
// read_only
|
// read_only
|
||||||
{GENERIC_READ, OPEN_EXISTING},
|
{GENERIC_READ, OPEN_EXISTING},
|
||||||
|
@ -545,15 +542,15 @@ namespace libtorrent {
|
||||||
{GENERIC_WRITE, OPEN_ALWAYS},
|
{GENERIC_WRITE, OPEN_ALWAYS},
|
||||||
// read_write
|
// read_write
|
||||||
{GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS},
|
{GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS},
|
||||||
};
|
}};
|
||||||
|
|
||||||
static const DWORD attrib_array[] =
|
static std::array<DWORD, 4> const attrib_array{
|
||||||
{
|
{
|
||||||
FILE_ATTRIBUTE_NORMAL, // no attrib
|
FILE_ATTRIBUTE_NORMAL, // no attrib
|
||||||
FILE_ATTRIBUTE_HIDDEN, // hidden
|
FILE_ATTRIBUTE_HIDDEN, // hidden
|
||||||
FILE_ATTRIBUTE_NORMAL, // executable
|
FILE_ATTRIBUTE_NORMAL, // executable
|
||||||
FILE_ATTRIBUTE_HIDDEN, // hidden + executable
|
FILE_ATTRIBUTE_HIDDEN, // hidden + executable
|
||||||
};
|
}};
|
||||||
|
|
||||||
#if TORRENT_USE_WSTRING
|
#if TORRENT_USE_WSTRING
|
||||||
#define CreateFile_ CreateFileW
|
#define CreateFile_ CreateFileW
|
||||||
|
@ -561,21 +558,21 @@ namespace libtorrent {
|
||||||
#define CreateFile_ CreateFileA
|
#define CreateFile_ CreateFileA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TORRENT_ASSERT((mode & rw_mask) < sizeof(mode_array)/sizeof(mode_array[0]));
|
TORRENT_ASSERT(static_cast<std::size_t>(mode & open_mode_t::rw_mask) < mode_array.size());
|
||||||
open_mode_t const& m = mode_array[mode & rw_mask];
|
win_open_mode_t const& m = mode_array[static_cast<std::size_t>(mode & open_mode_t::rw_mask)];
|
||||||
DWORD a = attrib_array[(mode & attribute_mask) >> 12];
|
DWORD a = attrib_array[static_cast<std::size_t>(mode & open_mode_t::attribute_mask) >> 12];
|
||||||
|
|
||||||
// one might think it's a good idea to pass in FILE_FLAG_RANDOM_ACCESS. It
|
// one might think it's a good idea to pass in FILE_FLAG_RANDOM_ACCESS. It
|
||||||
// turns out that it isn't. That flag will break your operating system:
|
// turns out that it isn't. That flag will break your operating system:
|
||||||
// http://support.microsoft.com/kb/2549369
|
// http://support.microsoft.com/kb/2549369
|
||||||
|
|
||||||
DWORD flags = ((mode & random_access) ? 0 : FILE_FLAG_SEQUENTIAL_SCAN)
|
DWORD const flags = (test(mode & open_mode_t::random_access) ? 0 : FILE_FLAG_SEQUENTIAL_SCAN)
|
||||||
| (a ? a : FILE_ATTRIBUTE_NORMAL)
|
| (a ? a : FILE_ATTRIBUTE_NORMAL)
|
||||||
| FILE_FLAG_OVERLAPPED
|
| FILE_FLAG_OVERLAPPED
|
||||||
| ((mode & no_cache) ? FILE_FLAG_WRITE_THROUGH : 0);
|
| (test(mode & open_mode_t::no_cache) ? FILE_FLAG_WRITE_THROUGH : 0);
|
||||||
|
|
||||||
handle_type handle = CreateFile_(file_path.c_str(), m.rw_mode
|
handle_type handle = CreateFile_(file_path.c_str(), m.rw_mode
|
||||||
, (mode & lock_file) ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE
|
, test(mode & open_mode_t::lock_file) ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE
|
||||||
, 0, m.create_mode, flags, 0);
|
, 0, m.create_mode, flags, 0);
|
||||||
|
|
||||||
#undef CreateFile_
|
#undef CreateFile_
|
||||||
|
@ -591,7 +588,8 @@ namespace libtorrent {
|
||||||
|
|
||||||
// try to make the file sparse if supported
|
// try to make the file sparse if supported
|
||||||
// only set this flag if the file is opened for writing
|
// only set this flag if the file is opened for writing
|
||||||
if ((mode & file::sparse) && (mode & rw_mask) != read_only)
|
if (test(mode & open_mode_t::sparse)
|
||||||
|
&& (mode & open_mode_t::rw_mask) != open_mode_t::read_only)
|
||||||
{
|
{
|
||||||
DWORD temp;
|
DWORD temp;
|
||||||
overlapped_t ol;
|
overlapped_t ol;
|
||||||
|
@ -609,7 +607,7 @@ namespace libtorrent {
|
||||||
| S_IRGRP | S_IWGRP
|
| S_IRGRP | S_IWGRP
|
||||||
| S_IROTH | S_IWOTH;
|
| S_IROTH | S_IWOTH;
|
||||||
|
|
||||||
if (mode & attribute_executable)
|
if (test(mode & open_mode_t::attribute_executable))
|
||||||
permissions |= S_IXGRP | S_IXOTH | S_IXUSR;
|
permissions |= S_IXGRP | S_IXOTH | S_IXUSR;
|
||||||
#ifdef O_BINARY
|
#ifdef O_BINARY
|
||||||
static const int mode_array[] = {O_RDONLY | O_BINARY, O_WRONLY | O_CREAT | O_BINARY, O_RDWR | O_CREAT | O_BINARY};
|
static const int mode_array[] = {O_RDONLY | O_BINARY, O_WRONLY | O_CREAT | O_BINARY, O_RDWR | O_CREAT | O_BINARY};
|
||||||
|
@ -619,26 +617,27 @@ namespace libtorrent {
|
||||||
|
|
||||||
int open_mode = 0
|
int open_mode = 0
|
||||||
#ifdef O_NOATIME
|
#ifdef O_NOATIME
|
||||||
| ((mode & no_atime) ? O_NOATIME : 0)
|
| (test(mode & open_mode_t::no_atime) ? O_NOATIME : 0)
|
||||||
#endif
|
#endif
|
||||||
#ifdef O_SYNC
|
#ifdef O_SYNC
|
||||||
| ((mode & no_cache) ? O_SYNC : 0)
|
| (test(mode & open_mode_t::no_cache) ? O_SYNC : 0)
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
handle_type handle = ::open(file_path.c_str()
|
handle_type handle = ::open(file_path.c_str()
|
||||||
, mode_array[mode & rw_mask] | open_mode
|
, mode_array[static_cast<std::size_t>(mode & open_mode_t::rw_mask)] | open_mode
|
||||||
, permissions);
|
, permissions);
|
||||||
|
|
||||||
#ifdef O_NOATIME
|
#ifdef O_NOATIME
|
||||||
// O_NOATIME is not allowed for files we don't own
|
// O_NOATIME is not allowed for files we don't own
|
||||||
// so, if we get EPERM when we try to open with it
|
// so, if we get EPERM when we try to open with it
|
||||||
// try again without O_NOATIME
|
// try again without O_NOATIME
|
||||||
if (handle == -1 && (mode & no_atime) && errno == EPERM)
|
if (handle == -1 && test(mode & open_mode_t::no_atime) && errno == EPERM)
|
||||||
{
|
{
|
||||||
mode &= ~no_atime;
|
mode &= ~open_mode_t::no_atime;
|
||||||
open_mode &= ~O_NOATIME;
|
open_mode &= ~O_NOATIME;
|
||||||
handle = ::open(file_path.c_str(), mode_array[mode & rw_mask] | open_mode
|
handle = ::open(file_path.c_str()
|
||||||
|
, mode_array[static_cast<std::size_t>(mode & open_mode_t::rw_mask)] | open_mode
|
||||||
, permissions);
|
, permissions);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -659,7 +658,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
#ifdef DIRECTIO_ON
|
#ifdef DIRECTIO_ON
|
||||||
// for solaris
|
// for solaris
|
||||||
if (mode & no_cache)
|
if (test(mode & open_mode_t::no_cache))
|
||||||
{
|
{
|
||||||
int yes = 1;
|
int yes = 1;
|
||||||
directio(native_handle(), DIRECTIO_ON);
|
directio(native_handle(), DIRECTIO_ON);
|
||||||
|
@ -668,7 +667,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
#ifdef F_NOCACHE
|
#ifdef F_NOCACHE
|
||||||
// for BSD/Mac
|
// for BSD/Mac
|
||||||
if (mode & no_cache)
|
if (test(mode & open_mode_t::no_cache))
|
||||||
{
|
{
|
||||||
int yes = 1;
|
int yes = 1;
|
||||||
fcntl(native_handle(), F_NOCACHE, &yes);
|
fcntl(native_handle(), F_NOCACHE, &yes);
|
||||||
|
@ -681,7 +680,7 @@ namespace libtorrent {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef POSIX_FADV_RANDOM
|
#ifdef POSIX_FADV_RANDOM
|
||||||
if (mode & random_access)
|
if (test(mode & open_mode_t::random_access))
|
||||||
{
|
{
|
||||||
// disable read-ahead
|
// disable read-ahead
|
||||||
posix_fadvise(native_handle(), 0, 0, POSIX_FADV_RANDOM);
|
posix_fadvise(native_handle(), 0, 0, POSIX_FADV_RANDOM);
|
||||||
|
@ -758,9 +757,9 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
// if this file is open for writing, has the sparse
|
// if this file is open for writing, has the sparse
|
||||||
// flag set, but there are no sparse regions, unset
|
// flag set, but there are no sparse regions, unset
|
||||||
// the flag
|
// the flag
|
||||||
std::uint32_t rw_mode = m_open_mode & rw_mask;
|
open_mode_t const rw_mode = m_open_mode & open_mode_t::rw_mask;
|
||||||
if ((rw_mode != read_only)
|
if ((rw_mode != open_mode_t::read_only)
|
||||||
&& (m_open_mode & sparse)
|
&& test(m_open_mode & open_mode_t::sparse)
|
||||||
&& !is_sparse(native_handle()))
|
&& !is_sparse(native_handle()))
|
||||||
{
|
{
|
||||||
overlapped_t ol;
|
overlapped_t ol;
|
||||||
|
@ -791,7 +790,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
|
|
||||||
m_file_handle = INVALID_HANDLE_VALUE;
|
m_file_handle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
m_open_mode = 0;
|
m_open_mode = open_mode_t::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -974,7 +973,7 @@ namespace {
|
||||||
// this has to be thread safe and atomic. i.e. on posix systems it has to be
|
// this has to be thread safe and atomic. i.e. on posix systems it has to be
|
||||||
// turned into a series of pread() calls
|
// turned into a series of pread() calls
|
||||||
std::int64_t file::readv(std::int64_t file_offset, span<iovec_t const> bufs
|
std::int64_t file::readv(std::int64_t file_offset, span<iovec_t const> bufs
|
||||||
, error_code& ec, std::uint32_t flags)
|
, error_code& ec, open_mode_t flags)
|
||||||
{
|
{
|
||||||
if (m_file_handle == INVALID_HANDLE_VALUE)
|
if (m_file_handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
@ -985,7 +984,8 @@ namespace {
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT((m_open_mode & rw_mask) == read_only || (m_open_mode & rw_mask) == read_write);
|
TORRENT_ASSERT((m_open_mode & open_mode_t::rw_mask) == open_mode_t::read_only
|
||||||
|
|| (m_open_mode & open_mode_t::rw_mask) == open_mode_t::read_write);
|
||||||
TORRENT_ASSERT(!bufs.empty());
|
TORRENT_ASSERT(!bufs.empty());
|
||||||
TORRENT_ASSERT(is_open());
|
TORRENT_ASSERT(is_open());
|
||||||
|
|
||||||
|
@ -997,16 +997,16 @@ namespace {
|
||||||
// there's no point in coalescing single buffer writes
|
// there's no point in coalescing single buffer writes
|
||||||
if (bufs.size() == 1)
|
if (bufs.size() == 1)
|
||||||
{
|
{
|
||||||
flags &= ~file::coalesce_buffers;
|
flags &= ~open_mode_t::coalesce_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
iovec_t tmp;
|
iovec_t tmp;
|
||||||
span<iovec_t const> tmp_bufs = bufs;
|
span<iovec_t const> tmp_bufs = bufs;
|
||||||
if ((flags & file::coalesce_buffers))
|
if (test(flags & open_mode_t::coalesce_buffers))
|
||||||
{
|
{
|
||||||
if (!coalesce_read_buffers(tmp_bufs, tmp))
|
if (!coalesce_read_buffers(tmp_bufs, tmp))
|
||||||
// ok, that failed, don't coalesce this read
|
// ok, that failed, don't coalesce this read
|
||||||
flags &= ~file::coalesce_buffers;
|
flags &= ~open_mode_t::coalesce_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TORRENT_USE_PREAD
|
#if TORRENT_USE_PREAD
|
||||||
|
@ -1015,7 +1015,7 @@ namespace {
|
||||||
std::int64_t ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec);
|
std::int64_t ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((flags & file::coalesce_buffers))
|
if (test(flags & open_mode_t::coalesce_buffers))
|
||||||
coalesce_read_buffers_end(bufs
|
coalesce_read_buffers_end(bufs
|
||||||
, tmp.data(), !ec);
|
, tmp.data(), !ec);
|
||||||
|
|
||||||
|
@ -1027,7 +1027,7 @@ namespace {
|
||||||
// that means, on posix this has to be turned into a series of
|
// that means, on posix this has to be turned into a series of
|
||||||
// pwrite() calls
|
// pwrite() calls
|
||||||
std::int64_t file::writev(std::int64_t file_offset, span<iovec_t const> bufs
|
std::int64_t file::writev(std::int64_t file_offset, span<iovec_t const> bufs
|
||||||
, error_code& ec, std::uint32_t flags)
|
, error_code& ec, open_mode_t flags)
|
||||||
{
|
{
|
||||||
if (m_file_handle == INVALID_HANDLE_VALUE)
|
if (m_file_handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
@ -1038,7 +1038,8 @@ namespace {
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT((m_open_mode & rw_mask) == write_only || (m_open_mode & rw_mask) == read_write);
|
TORRENT_ASSERT((m_open_mode & open_mode_t::rw_mask) == open_mode_t::write_only
|
||||||
|
|| (m_open_mode & open_mode_t::rw_mask) == open_mode_t::read_write);
|
||||||
TORRENT_ASSERT(!bufs.empty());
|
TORRENT_ASSERT(!bufs.empty());
|
||||||
TORRENT_ASSERT(is_open());
|
TORRENT_ASSERT(is_open());
|
||||||
|
|
||||||
|
@ -1053,15 +1054,15 @@ namespace {
|
||||||
// there's no point in coalescing single buffer writes
|
// there's no point in coalescing single buffer writes
|
||||||
if (bufs.size() == 1)
|
if (bufs.size() == 1)
|
||||||
{
|
{
|
||||||
flags &= ~file::coalesce_buffers;
|
flags &= ~open_mode_t::coalesce_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
iovec_t tmp;
|
iovec_t tmp;
|
||||||
if (flags & file::coalesce_buffers)
|
if (test(flags & open_mode_t::coalesce_buffers))
|
||||||
{
|
{
|
||||||
if (!coalesce_write_buffers(bufs, tmp))
|
if (!coalesce_write_buffers(bufs, tmp))
|
||||||
// ok, that failed, don't coalesce writes
|
// ok, that failed, don't coalesce writes
|
||||||
flags &= ~file::coalesce_buffers;
|
flags &= ~open_mode_t::coalesce_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TORRENT_USE_PREAD
|
#if TORRENT_USE_PREAD
|
||||||
|
@ -1070,14 +1071,14 @@ namespace {
|
||||||
std::int64_t ret = iov(&::write, native_handle(), file_offset, bufs, ec);
|
std::int64_t ret = iov(&::write, native_handle(), file_offset, bufs, ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (flags & file::coalesce_buffers)
|
if (test(flags & open_mode_t::coalesce_buffers))
|
||||||
delete[] tmp.data();
|
delete[] tmp.data();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if TORRENT_USE_FDATASYNC \
|
#if TORRENT_USE_FDATASYNC \
|
||||||
&& !defined F_NOCACHE && \
|
&& !defined F_NOCACHE && \
|
||||||
!defined DIRECTIO_ON
|
!defined DIRECTIO_ON
|
||||||
if (m_open_mode & no_cache)
|
if (test(m_open_mode & open_mode_t::no_cache))
|
||||||
{
|
{
|
||||||
if (fdatasync(native_handle()) != 0
|
if (fdatasync(native_handle()) != 0
|
||||||
&& errno != EINVAL
|
&& errno != EINVAL
|
||||||
|
@ -1192,7 +1193,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _WIN32_WINNT >= 0x0600 // only if Windows Vista or newer
|
#if _WIN32_WINNT >= 0x0600 // only if Windows Vista or newer
|
||||||
if ((m_open_mode & sparse) == 0)
|
if (!test(m_open_mode & open_mode_t::sparse))
|
||||||
{
|
{
|
||||||
typedef DWORD (WINAPI *GetFileInformationByHandleEx_t)(HANDLE hFile
|
typedef DWORD (WINAPI *GetFileInformationByHandleEx_t)(HANDLE hFile
|
||||||
, FILE_INFO_BY_HANDLE_CLASS FileInformationClass
|
, FILE_INFO_BY_HANDLE_CLASS FileInformationClass
|
||||||
|
@ -1247,7 +1248,7 @@ namespace {
|
||||||
// is less than the file size. Otherwise we would just
|
// is less than the file size. Otherwise we would just
|
||||||
// update the modification time of the file for no good
|
// update the modification time of the file for no good
|
||||||
// reason.
|
// reason.
|
||||||
if ((m_open_mode & sparse) == 0
|
if (!test(m_open_mode & open_mode_t::sparse)
|
||||||
&& std::int64_t(st.st_blocks) < (s + st.st_blksize - 1) / st.st_blksize)
|
&& std::int64_t(st.st_blocks) < (s + st.st_blksize - 1) / st.st_blksize)
|
||||||
{
|
{
|
||||||
// How do we know that the file is already allocated?
|
// How do we know that the file is already allocated?
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
file_handle file_pool::open_file(storage_index_t st, std::string const& p
|
file_handle file_pool::open_file(storage_index_t st, std::string const& p
|
||||||
, file_index_t const file_index, file_storage const& fs
|
, file_index_t const file_index, file_storage const& fs
|
||||||
, std::uint32_t const m, error_code& ec)
|
, open_mode_t const m, error_code& ec)
|
||||||
{
|
{
|
||||||
// potentially used to hold a reference to a file object that's
|
// potentially used to hold a reference to a file object that's
|
||||||
// about to be destructed. If we have such object we assign it to
|
// about to be destructed. If we have such object we assign it to
|
||||||
|
@ -119,8 +119,8 @@ namespace libtorrent {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TORRENT_ASSERT(is_complete(p));
|
TORRENT_ASSERT(is_complete(p));
|
||||||
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|
TORRENT_ASSERT((m & open_mode_t::rw_mask) == open_mode_t::read_only
|
||||||
|| (m & file::rw_mask) == file::read_write);
|
|| (m & open_mode_t::rw_mask) == open_mode_t::read_write);
|
||||||
auto const i = m_files.find(std::make_pair(st, file_index));
|
auto const i = m_files.find(std::make_pair(st, file_index));
|
||||||
if (i != m_files.end())
|
if (i != m_files.end())
|
||||||
{
|
{
|
||||||
|
@ -130,9 +130,9 @@ namespace libtorrent {
|
||||||
// if we asked for a file in write mode,
|
// if we asked for a file in write mode,
|
||||||
// and the cached file is is not opened in
|
// and the cached file is is not opened in
|
||||||
// write mode, re-open it
|
// write mode, re-open it
|
||||||
if ((((e.mode & file::rw_mask) != file::read_write)
|
if ((((e.mode & open_mode_t::rw_mask) != open_mode_t::read_write)
|
||||||
&& ((m & file::rw_mask) == file::read_write))
|
&& ((m & open_mode_t::rw_mask) == open_mode_t::read_write))
|
||||||
|| (e.mode & file::random_access) != (m & file::random_access))
|
|| (e.mode & open_mode_t::random_access) != (m & open_mode_t::random_access))
|
||||||
{
|
{
|
||||||
file_handle new_file = std::make_shared<file>();
|
file_handle new_file = std::make_shared<file>();
|
||||||
|
|
||||||
|
@ -182,26 +182,23 @@ namespace libtorrent {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::uint32_t to_file_open_mode(std::uint32_t const mode)
|
std::uint32_t to_file_open_mode(open_mode_t const mode)
|
||||||
{
|
{
|
||||||
std::uint32_t ret = 0;
|
std::uint32_t ret = 0;
|
||||||
switch (mode & file::rw_mask)
|
open_mode_t const rw_mode = mode & open_mode_t::rw_mask;
|
||||||
{
|
|
||||||
case file::read_only:
|
|
||||||
ret = file_open_mode::read_only;
|
|
||||||
break;
|
|
||||||
case file::write_only:
|
|
||||||
ret = file_open_mode::write_only;
|
|
||||||
break;
|
|
||||||
case file::read_write:
|
|
||||||
ret = file_open_mode::read_write;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode & file::sparse) ret |= file_open_mode::sparse;
|
ret = (rw_mode == open_mode_t::read_only)
|
||||||
if (mode & file::no_atime) ret |= file_open_mode::no_atime;
|
? file_open_mode::read_only
|
||||||
if (mode & file::random_access) ret |= file_open_mode::random_access;
|
: (rw_mode == open_mode_t::write_only)
|
||||||
if (mode & file::lock_file) ret |= file_open_mode::locked;
|
? file_open_mode::write_only
|
||||||
|
: (rw_mode == open_mode_t::read_write)
|
||||||
|
? file_open_mode::read_write
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (test(mode & open_mode_t::sparse)) ret |= file_open_mode::sparse;
|
||||||
|
if (test(mode & open_mode_t::no_atime)) ret |= file_open_mode::no_atime;
|
||||||
|
if (test(mode & open_mode_t::random_access)) ret |= file_open_mode::random_access;
|
||||||
|
if (test(mode & open_mode_t::lock_file)) ret |= file_open_mode::locked;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
std::string fn = combine_path(m_path, m_name);
|
std::string fn = combine_path(m_path, m_name);
|
||||||
m_file.open(fn, file::read_only, ec);
|
m_file.open(fn, open_mode_t::read_only, ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
|
||||||
// parse header
|
// parse header
|
||||||
|
@ -178,7 +178,7 @@ namespace libtorrent {
|
||||||
TORRENT_ASSERT(offset >= 0);
|
TORRENT_ASSERT(offset >= 0);
|
||||||
std::unique_lock<std::mutex> l(m_mutex);
|
std::unique_lock<std::mutex> l(m_mutex);
|
||||||
|
|
||||||
open_file(file::read_write, ec);
|
open_file(open_mode_t::read_write, ec);
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
|
|
||||||
auto const i = m_piece_map.find(piece);
|
auto const i = m_piece_map.find(piece);
|
||||||
|
@ -206,7 +206,7 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
slot_index_t const slot = i->second;
|
slot_index_t const slot = i->second;
|
||||||
open_file(file::read_write, ec);
|
open_file(open_mode_t::read_write, ec);
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
|
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
@ -215,15 +215,15 @@ namespace libtorrent {
|
||||||
return int(m_file.readv(slot_offset + offset, bufs, ec));
|
return int(m_file.readv(slot_offset + offset, bufs, ec));
|
||||||
}
|
}
|
||||||
|
|
||||||
void part_file::open_file(std::uint32_t const mode, error_code& ec)
|
void part_file::open_file(open_mode_t const mode, error_code& ec)
|
||||||
{
|
{
|
||||||
if (m_file.is_open()
|
if (m_file.is_open()
|
||||||
&& ((m_file.open_mode() & file::rw_mask) == mode
|
&& ((m_file.open_mode() & open_mode_t::rw_mask) == mode
|
||||||
|| mode == file::read_only)) return;
|
|| mode == open_mode_t::read_only)) return;
|
||||||
|
|
||||||
std::string fn = combine_path(m_path, m_name);
|
std::string fn = combine_path(m_path, m_name);
|
||||||
m_file.open(fn, mode, ec);
|
m_file.open(fn, mode, ec);
|
||||||
if (((mode & file::rw_mask) != file::read_only)
|
if (((mode & open_mode_t::rw_mask) != open_mode_t::read_only)
|
||||||
&& ec == boost::system::errc::no_such_file_or_directory)
|
&& ec == boost::system::errc::no_such_file_or_directory)
|
||||||
{
|
{
|
||||||
// this means the directory the file is in doesn't exist.
|
// this means the directory the file is in doesn't exist.
|
||||||
|
@ -301,7 +301,7 @@ namespace libtorrent {
|
||||||
if (i != m_piece_map.end())
|
if (i != m_piece_map.end())
|
||||||
{
|
{
|
||||||
slot_index_t const slot = i->second;
|
slot_index_t const slot = i->second;
|
||||||
open_file(file::read_only, ec);
|
open_file(open_mode_t::read_only, ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
|
||||||
if (!buf) buf.reset(new char[m_piece_size]);
|
if (!buf) buf.reset(new char[m_piece_size]);
|
||||||
|
@ -375,7 +375,7 @@ namespace libtorrent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
open_file(file::read_write, ec);
|
open_file(open_mode_t::read_write, ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
|
||||||
std::vector<char> header(static_cast<std::size_t>(m_header_size));
|
std::vector<char> header(static_cast<std::size_t>(m_header_size));
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace libtorrent {
|
||||||
if (old_prio == 0 && new_prio != 0)
|
if (old_prio == 0 && new_prio != 0)
|
||||||
{
|
{
|
||||||
// move stuff out of the part file
|
// move stuff out of the part file
|
||||||
file_handle f = open_file(i, file::read_write, ec);
|
file_handle f = open_file(i, open_mode_t::read_write, ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
|
||||||
need_partfile();
|
need_partfile();
|
||||||
|
@ -165,7 +165,7 @@ namespace libtorrent {
|
||||||
if (exists(fp))
|
if (exists(fp))
|
||||||
new_prio = 1;
|
new_prio = 1;
|
||||||
/*
|
/*
|
||||||
file_handle f = open_file(i, file::read_only, ec);
|
file_handle f = open_file(i, open_mode_t::read_only, ec);
|
||||||
if (ec.ec != boost::system::errc::no_such_file_or_directory)
|
if (ec.ec != boost::system::errc::no_such_file_or_directory)
|
||||||
{
|
{
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
@ -272,8 +272,8 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ec.ec.clear();
|
ec.ec.clear();
|
||||||
file_handle f = open_file(file_index, file::read_write
|
file_handle f = open_file(file_index, open_mode_t::read_write
|
||||||
| file::random_access, ec);
|
| open_mode_t::random_access, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
ec.file(file_index);
|
ec.file(file_index);
|
||||||
|
@ -467,7 +467,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
int default_storage::readv(span<iovec_t const> bufs
|
int default_storage::readv(span<iovec_t const> bufs
|
||||||
, piece_index_t const piece, int const offset
|
, piece_index_t const piece, int const offset
|
||||||
, std::uint32_t const flags, storage_error& error)
|
, open_mode_t const flags, storage_error& error)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_SIMULATE_SLOW_READ
|
#ifdef TORRENT_SIMULATE_SLOW_READ
|
||||||
std::this_thread::sleep_for(seconds(1));
|
std::this_thread::sleep_for(seconds(1));
|
||||||
|
@ -506,7 +506,7 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
file_handle handle = open_file(file_index
|
file_handle handle = open_file(file_index
|
||||||
, file::read_only | flags, ec);
|
, open_mode_t::read_only | flags, ec);
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
|
|
||||||
error_code e;
|
error_code e;
|
||||||
|
@ -534,7 +534,7 @@ namespace libtorrent {
|
||||||
|
|
||||||
int default_storage::writev(span<iovec_t const> bufs
|
int default_storage::writev(span<iovec_t const> bufs
|
||||||
, piece_index_t const piece, int const offset
|
, piece_index_t const piece, int const offset
|
||||||
, std::uint32_t const flags, storage_error& error)
|
, open_mode_t const flags, storage_error& error)
|
||||||
{
|
{
|
||||||
return readwritev(files(), bufs, piece, offset, error
|
return readwritev(files(), bufs, piece, offset, error
|
||||||
, [this, flags](file_index_t const file_index
|
, [this, flags](file_index_t const file_index
|
||||||
|
@ -573,7 +573,7 @@ namespace libtorrent {
|
||||||
m_stat_cache.set_dirty(file_index);
|
m_stat_cache.set_dirty(file_index);
|
||||||
|
|
||||||
file_handle handle = open_file(file_index
|
file_handle handle = open_file(file_index
|
||||||
, file::read_write, ec);
|
, open_mode_t::read_write, ec);
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
|
|
||||||
error_code e;
|
error_code e;
|
||||||
|
@ -600,10 +600,10 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
file_handle default_storage::open_file(file_index_t const file
|
file_handle default_storage::open_file(file_index_t const file
|
||||||
, std::uint32_t mode, storage_error& ec) const
|
, open_mode_t mode, storage_error& ec) const
|
||||||
{
|
{
|
||||||
file_handle h = open_file_impl(file, mode, ec.ec);
|
file_handle h = open_file_impl(file, mode, ec.ec);
|
||||||
if (((mode & file::rw_mask) != file::read_only)
|
if (((mode & open_mode_t::rw_mask) != open_mode_t::read_only)
|
||||||
&& ec.ec == boost::system::errc::no_such_file_or_directory)
|
&& ec.ec == boost::system::errc::no_such_file_or_directory)
|
||||||
{
|
{
|
||||||
// this means the directory the file is in doesn't exist.
|
// this means the directory the file is in doesn't exist.
|
||||||
|
@ -631,7 +631,7 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT(h);
|
TORRENT_ASSERT(h);
|
||||||
|
|
||||||
if (m_allocate_files && (mode & file::rw_mask) != file::read_only)
|
if (m_allocate_files && (mode & open_mode_t::rw_mask) != open_mode_t::read_only)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_file_created_mutex);
|
std::unique_lock<std::mutex> l(m_file_created_mutex);
|
||||||
if (m_file_created.size() != files().num_files())
|
if (m_file_created.size() != files().num_files())
|
||||||
|
@ -662,37 +662,37 @@ namespace libtorrent {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_handle default_storage::open_file_impl(file_index_t file, std::uint32_t mode
|
file_handle default_storage::open_file_impl(file_index_t file, open_mode_t mode
|
||||||
, error_code& ec) const
|
, error_code& ec) const
|
||||||
{
|
{
|
||||||
bool const lock_files = m_settings ? settings().get_bool(settings_pack::lock_files) : false;
|
bool const lock_files = m_settings ? settings().get_bool(settings_pack::lock_files) : false;
|
||||||
if (lock_files) mode |= file::lock_file;
|
if (lock_files) mode |= open_mode_t::lock_file;
|
||||||
|
|
||||||
if (!m_allocate_files) mode |= file::sparse;
|
if (!m_allocate_files) mode |= open_mode_t::sparse;
|
||||||
|
|
||||||
// files with priority 0 should always be sparse
|
// files with priority 0 should always be sparse
|
||||||
if (m_file_priority.end_index() > file && m_file_priority[file] == 0)
|
if (m_file_priority.end_index() > file && m_file_priority[file] == 0)
|
||||||
mode |= file::sparse;
|
mode |= open_mode_t::sparse;
|
||||||
|
|
||||||
if (m_settings && settings().get_bool(settings_pack::no_atime_storage)) mode |= file::no_atime;
|
if (m_settings && settings().get_bool(settings_pack::no_atime_storage)) mode |= open_mode_t::no_atime;
|
||||||
|
|
||||||
// if we have a cache already, don't store the data twice by leaving it in the OS cache as well
|
// if we have a cache already, don't store the data twice by leaving it in the OS cache as well
|
||||||
if (m_settings
|
if (m_settings
|
||||||
&& settings().get_int(settings_pack::disk_io_write_mode)
|
&& settings().get_int(settings_pack::disk_io_write_mode)
|
||||||
== settings_pack::disable_os_cache)
|
== settings_pack::disable_os_cache)
|
||||||
{
|
{
|
||||||
mode |= file::no_cache;
|
mode |= open_mode_t::no_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_handle ret = m_pool.open_file(storage_index(), m_save_path, file
|
file_handle ret = m_pool.open_file(storage_index(), m_save_path, file
|
||||||
, files(), mode, ec);
|
, files(), mode, ec);
|
||||||
if (ec && (mode & file::lock_file))
|
if (ec && test(mode & open_mode_t::lock_file))
|
||||||
{
|
{
|
||||||
// we failed to open the file and we're trying to lock it. It's
|
// we failed to open the file and we're trying to lock it. It's
|
||||||
// possible we're failing because we have another handle to this
|
// possible we're failing because we have another handle to this
|
||||||
// file in use (but waiting to be closed). Just retry to open it
|
// file in use (but waiting to be closed). Just retry to open it
|
||||||
// without locking.
|
// without locking.
|
||||||
mode &= ~file::lock_file;
|
mode &= ~open_mode_t::lock_file;
|
||||||
ret = m_pool.open_file(storage_index(), m_save_path, file, files()
|
ret = m_pool.open_file(storage_index(), m_save_path, file, files()
|
||||||
, mode, ec);
|
, mode, ec);
|
||||||
}
|
}
|
||||||
|
@ -740,12 +740,12 @@ namespace {
|
||||||
status_t move_storage(std::string const&, int, storage_error&) override { return status_t::no_error; }
|
status_t move_storage(std::string const&, int, storage_error&) override { return status_t::no_error; }
|
||||||
|
|
||||||
int readv(span<iovec_t const> bufs
|
int readv(span<iovec_t const> bufs
|
||||||
, piece_index_t, int, std::uint32_t, storage_error&) override
|
, piece_index_t, int, open_mode_t, storage_error&) override
|
||||||
{
|
{
|
||||||
return bufs_size(bufs);
|
return bufs_size(bufs);
|
||||||
}
|
}
|
||||||
int writev(span<iovec_t const> bufs
|
int writev(span<iovec_t const> bufs
|
||||||
, piece_index_t, int, std::uint32_t, storage_error&) override
|
, piece_index_t, int, open_mode_t, storage_error&) override
|
||||||
{
|
{
|
||||||
return bufs_size(bufs);
|
return bufs_size(bufs);
|
||||||
}
|
}
|
||||||
|
@ -773,7 +773,7 @@ namespace {
|
||||||
void initialize(storage_error&) override {}
|
void initialize(storage_error&) override {}
|
||||||
|
|
||||||
int readv(span<iovec_t const> bufs
|
int readv(span<iovec_t const> bufs
|
||||||
, piece_index_t, int, std::uint32_t, storage_error&) override
|
, piece_index_t, int, open_mode_t, storage_error&) override
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (auto const& b : bufs)
|
for (auto const& b : bufs)
|
||||||
|
@ -784,7 +784,7 @@ namespace {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int writev(span<iovec_t const> bufs
|
int writev(span<iovec_t const> bufs
|
||||||
, piece_index_t, int, std::uint32_t, storage_error&) override
|
, piece_index_t, int, open_mode_t, storage_error&) override
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (auto const& b : bufs)
|
for (auto const& b : bufs)
|
||||||
|
|
|
@ -552,7 +552,7 @@ namespace libtorrent {
|
||||||
{
|
{
|
||||||
ec.clear();
|
ec.clear();
|
||||||
file f;
|
file f;
|
||||||
if (!f.open(filename, file::read_only, ec)) return -1;
|
if (!f.open(filename, open_mode_t::read_only, ec)) return -1;
|
||||||
std::int64_t s = f.get_size(ec);
|
std::int64_t s = f.get_size(ec);
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
v.resize(std::size_t(s));
|
v.resize(std::size_t(s));
|
||||||
|
|
|
@ -192,7 +192,7 @@ void generate_files(lt::torrent_info const& ti, std::string const& path
|
||||||
|
|
||||||
iovec_t b = { &buffer[0], size_t(piece_size) };
|
iovec_t b = { &buffer[0], size_t(piece_size) };
|
||||||
storage_error ec;
|
storage_error ec;
|
||||||
int ret = st.writev(b, i, 0, 0, ec);
|
int ret = st.writev(b, i, 0, open_mode_t::read_only, ec);
|
||||||
if (ret != piece_size || ec)
|
if (ret != piece_size || ec)
|
||||||
{
|
{
|
||||||
std::printf("ERROR writing files: (%d expected %d) %s\n"
|
std::printf("ERROR writing files: (%d expected %d) %s\n"
|
||||||
|
|
|
@ -658,7 +658,7 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu
|
||||||
full_path = combine_path(full_path, filename);
|
full_path = combine_path(full_path, filename);
|
||||||
|
|
||||||
int to_write = file_sizes[i];
|
int to_write = file_sizes[i];
|
||||||
file f(full_path, file::write_only, ec);
|
file f(full_path, open_mode_t::write_only, ec);
|
||||||
if (ec) std::printf("failed to create file \"%s\": (%d) %s\n"
|
if (ec) std::printf("failed to create file \"%s\": (%d) %s\n"
|
||||||
, full_path.c_str(), ec.value(), ec.message().c_str());
|
, full_path.c_str(), ec.value(), ec.message().c_str());
|
||||||
std::int64_t offset = 0;
|
std::int64_t offset = 0;
|
||||||
|
|
|
@ -51,12 +51,12 @@ struct test_storage_impl : storage_interface
|
||||||
void initialize(storage_error& ec) override {}
|
void initialize(storage_error& ec) override {}
|
||||||
|
|
||||||
int readv(span<iovec_t const> bufs
|
int readv(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) override
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) override
|
||||||
{
|
{
|
||||||
return bufs_size(bufs);
|
return bufs_size(bufs);
|
||||||
}
|
}
|
||||||
int writev(span<iovec_t const> bufs
|
int writev(span<iovec_t const> bufs
|
||||||
, piece_index_t piece, int offset, std::uint32_t flags, storage_error& ec) override
|
, piece_index_t piece, int offset, open_mode_t flags, storage_error& ec) override
|
||||||
{
|
{
|
||||||
return bufs_size(bufs);
|
return bufs_size(bufs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ void test_checking(int flags = read_only_files)
|
||||||
path = combine_path(path, name);
|
path = combine_path(path, name);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file f(path, file::read_write, ec);
|
file f(path, open_mode_t::read_write, ec);
|
||||||
if (ec) std::printf("ERROR: opening file \"%s\": (%d) %s\n"
|
if (ec) std::printf("ERROR: opening file \"%s\": (%d) %s\n"
|
||||||
, path.c_str(), ec.value(), ec.message().c_str());
|
, path.c_str(), ec.value(), ec.message().c_str());
|
||||||
f.set_size(file_sizes[i] / 2, ec);
|
f.set_size(file_sizes[i] / 2, ec);
|
||||||
|
|
|
@ -52,7 +52,7 @@ int touch_file(std::string const& filename, int size)
|
||||||
|
|
||||||
file f;
|
file f;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
if (!f.open(filename, file::write_only, ec)) return -1;
|
if (!f.open(filename, open_mode_t::write_only, ec)) return -1;
|
||||||
if (ec) return -1;
|
if (ec) return -1;
|
||||||
iovec_t b = {&v[0], v.size()};
|
iovec_t b = {&v[0], v.size()};
|
||||||
std::int64_t written = f.writev(0, b, ec);
|
std::int64_t written = f.writev(0, b, ec);
|
||||||
|
@ -283,9 +283,9 @@ TORRENT_TEST(file)
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file f;
|
file f;
|
||||||
#if TORRENT_USE_UNC_PATHS || !defined _WIN32
|
#if TORRENT_USE_UNC_PATHS || !defined _WIN32
|
||||||
TEST_CHECK(f.open("con", file::read_write, ec));
|
TEST_CHECK(f.open("con", open_mode_t::read_write, ec));
|
||||||
#else
|
#else
|
||||||
TEST_CHECK(f.open("test_file", file::read_write, ec));
|
TEST_CHECK(f.open("test_file", open_mode_t::read_write, ec));
|
||||||
#endif
|
#endif
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
|
@ -316,7 +316,7 @@ TORRENT_TEST(hard_link)
|
||||||
// read that file and assert we get the same stuff we wrote to the first file
|
// read that file and assert we get the same stuff we wrote to the first file
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file f;
|
file f;
|
||||||
TEST_CHECK(f.open("original_file", file::read_write, ec));
|
TEST_CHECK(f.open("original_file", open_mode_t::read_write, ec));
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
|
@ -336,7 +336,7 @@ TORRENT_TEST(hard_link)
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
|
|
||||||
|
|
||||||
TEST_CHECK(f.open("second_link", file::read_write, ec));
|
TEST_CHECK(f.open("second_link", open_mode_t::read_write, ec));
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
|
@ -363,7 +363,7 @@ TORRENT_TEST(coalesce_buffer)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file f;
|
file f;
|
||||||
TEST_CHECK(f.open("test_file", file::read_write, ec));
|
TEST_CHECK(f.open("test_file", open_mode_t::read_write, ec));
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
|
@ -371,7 +371,7 @@ TORRENT_TEST(coalesce_buffer)
|
||||||
char test[] = "test";
|
char test[] = "test";
|
||||||
char foobar[] = "foobar";
|
char foobar[] = "foobar";
|
||||||
iovec_t b[2] = {{test, 4}, {foobar, 6}};
|
iovec_t b[2] = {{test, 4}, {foobar, 6}};
|
||||||
TEST_EQUAL(f.writev(0, b, ec, file::coalesce_buffers), 4 + 6);
|
TEST_EQUAL(f.writev(0, b, ec, open_mode_t::coalesce_buffers), 4 + 6);
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_CHECK(!ec);
|
TEST_CHECK(!ec);
|
||||||
|
|
|
@ -146,7 +146,7 @@ void write_test_file()
|
||||||
std::srand(unsigned(std::time(nullptr)));
|
std::srand(unsigned(std::time(nullptr)));
|
||||||
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file test_file("test_file", file::write_only, ec);
|
file test_file("test_file", open_mode_t::write_only, ec);
|
||||||
TEST_CHECK(!ec);
|
TEST_CHECK(!ec);
|
||||||
if (ec) std::printf("file error: %s\n", ec.message().c_str());
|
if (ec) std::printf("file error: %s\n", ec.message().c_str());
|
||||||
iovec_t b = { data_buffer, 3216};
|
iovec_t b = { data_buffer, 3216};
|
||||||
|
|
|
@ -242,50 +242,50 @@ void run_storage_tests(std::shared_ptr<torrent_info> info
|
||||||
|
|
||||||
// write piece 1 (in slot 0)
|
// write piece 1 (in slot 0)
|
||||||
iovec_t iov = { piece1.data(), half};
|
iovec_t iov = { piece1.data(), half};
|
||||||
ret = s->writev(iov, piece_index_t(0), 0, 0, ec);
|
ret = s->writev(iov, piece_index_t(0), 0, open_mode_t::read_write, ec);
|
||||||
if (ret != half) print_error("writev", ret, ec);
|
if (ret != half) print_error("writev", ret, ec);
|
||||||
|
|
||||||
iov = { piece1.data() + half, half };
|
iov = { piece1.data() + half, half };
|
||||||
ret = s->writev(iov, piece_index_t(0), half, 0, ec);
|
ret = s->writev(iov, piece_index_t(0), half, open_mode_t::read_write, ec);
|
||||||
if (ret != half) print_error("writev", ret, ec);
|
if (ret != half) print_error("writev", ret, ec);
|
||||||
|
|
||||||
// test unaligned read (where the bytes are aligned)
|
// test unaligned read (where the bytes are aligned)
|
||||||
iov = { piece + 3, piece_size - 9};
|
iov = { piece + 3, piece_size - 9};
|
||||||
ret = s->readv(iov, piece_index_t(0), 3, 0, ec);
|
ret = s->readv(iov, piece_index_t(0), 3, open_mode_t::read_write, ec);
|
||||||
if (ret != piece_size - 9) print_error("readv",ret, ec);
|
if (ret != piece_size - 9) print_error("readv",ret, ec);
|
||||||
TEST_CHECK(std::equal(piece+3, piece + piece_size-9, piece1.data()+3));
|
TEST_CHECK(std::equal(piece+3, piece + piece_size-9, piece1.data()+3));
|
||||||
|
|
||||||
// test unaligned read (where the bytes are not aligned)
|
// test unaligned read (where the bytes are not aligned)
|
||||||
iov = { piece, piece_size - 9};
|
iov = { piece, piece_size - 9};
|
||||||
ret = s->readv(iov, piece_index_t(0), 3, 0, ec);
|
ret = s->readv(iov, piece_index_t(0), 3, open_mode_t::read_write, ec);
|
||||||
TEST_CHECK(ret == piece_size - 9);
|
TEST_CHECK(ret == piece_size - 9);
|
||||||
if (ret != piece_size - 9) print_error("readv", ret, ec);
|
if (ret != piece_size - 9) print_error("readv", ret, ec);
|
||||||
TEST_CHECK(std::equal(piece, piece + piece_size-9, piece1.data()+3));
|
TEST_CHECK(std::equal(piece, piece + piece_size-9, piece1.data()+3));
|
||||||
|
|
||||||
// verify piece 1
|
// verify piece 1
|
||||||
iov = { piece, piece_size };
|
iov = { piece, piece_size };
|
||||||
ret = s->readv(iov, piece_index_t(0), 0, 0, ec);
|
ret = s->readv(iov, piece_index_t(0), 0, open_mode_t::read_write, ec);
|
||||||
TEST_CHECK(ret == piece_size);
|
TEST_CHECK(ret == piece_size);
|
||||||
if (ret != piece_size) print_error("readv", ret, ec);
|
if (ret != piece_size) print_error("readv", ret, ec);
|
||||||
TEST_CHECK(std::equal(piece, piece + piece_size, piece1.data()));
|
TEST_CHECK(std::equal(piece, piece + piece_size, piece1.data()));
|
||||||
|
|
||||||
// do the same with piece 0 and 2 (in slot 1 and 2)
|
// do the same with piece 0 and 2 (in slot 1 and 2)
|
||||||
iov = { piece0.data(), piece_size };
|
iov = { piece0.data(), piece_size };
|
||||||
ret = s->writev(iov, piece_index_t(1), 0, 0, ec);
|
ret = s->writev(iov, piece_index_t(1), 0, open_mode_t::read_write, ec);
|
||||||
if (ret != piece_size) print_error("writev", ret, ec);
|
if (ret != piece_size) print_error("writev", ret, ec);
|
||||||
|
|
||||||
iov = { piece2.data(), piece_size };
|
iov = { piece2.data(), piece_size };
|
||||||
ret = s->writev(iov, piece_index_t(2), 0, 0, ec);
|
ret = s->writev(iov, piece_index_t(2), 0, open_mode_t::read_write, ec);
|
||||||
if (ret != piece_size) print_error("writev", ret, ec);
|
if (ret != piece_size) print_error("writev", ret, ec);
|
||||||
|
|
||||||
// verify piece 0 and 2
|
// verify piece 0 and 2
|
||||||
iov = { piece, piece_size };
|
iov = { piece, piece_size };
|
||||||
ret = s->readv(iov, piece_index_t(1), 0, 0, ec);
|
ret = s->readv(iov, piece_index_t(1), 0, open_mode_t::read_write, ec);
|
||||||
if (ret != piece_size) print_error("readv", ret, ec);
|
if (ret != piece_size) print_error("readv", ret, ec);
|
||||||
TEST_CHECK(std::equal(piece, piece + piece_size, piece0.data()));
|
TEST_CHECK(std::equal(piece, piece + piece_size, piece0.data()));
|
||||||
|
|
||||||
iov = { piece, piece_size };
|
iov = { piece, piece_size };
|
||||||
ret = s->readv(iov, piece_index_t(2), 0, 0, ec);
|
ret = s->readv(iov, piece_index_t(2), 0, open_mode_t::read_write, ec);
|
||||||
if (ret != piece_size) print_error("readv", ret, ec);
|
if (ret != piece_size) print_error("readv", ret, ec);
|
||||||
TEST_CHECK(std::equal(piece, piece + piece_size, piece2.data()));
|
TEST_CHECK(std::equal(piece, piece + piece_size, piece2.data()));
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ void test_remove(std::string const& test_path, bool unbuffered)
|
||||||
|
|
||||||
iovec_t b = {&buf[0], 4};
|
iovec_t b = {&buf[0], 4};
|
||||||
storage_error se;
|
storage_error se;
|
||||||
s->writev(b, piece_index_t(2), 0, 0, se);
|
s->writev(b, piece_index_t(2), 0, open_mode_t::read_write, se);
|
||||||
|
|
||||||
TEST_CHECK(exists(combine_path(test_path, combine_path("temp_storage"
|
TEST_CHECK(exists(combine_path(test_path, combine_path("temp_storage"
|
||||||
, combine_path("folder1", "test2.tmp")))));
|
, combine_path("folder1", "test2.tmp")))));
|
||||||
|
@ -348,7 +348,7 @@ void test_remove(std::string const& test_path, bool unbuffered)
|
||||||
, combine_path("folder1", "test2.tmp"))), &st, ec);
|
, combine_path("folder1", "test2.tmp"))), &st, ec);
|
||||||
TEST_EQUAL(st.file_size, 8);
|
TEST_EQUAL(st.file_size, 8);
|
||||||
|
|
||||||
s->writev(b, piece_index_t(4), 0, 0, se);
|
s->writev(b, piece_index_t(4), 0, open_mode_t::read_write, se);
|
||||||
|
|
||||||
TEST_CHECK(exists(combine_path(test_path, combine_path("temp_storage"
|
TEST_CHECK(exists(combine_path(test_path, combine_path("temp_storage"
|
||||||
, combine_path("_folder3", combine_path("subfolder", "test5.tmp"))))));
|
, combine_path("_folder3", combine_path("subfolder", "test5.tmp"))))));
|
||||||
|
@ -1362,7 +1362,7 @@ TORRENT_TEST(move_storage_to_self)
|
||||||
|
|
||||||
iovec_t const b = {&buf[0], 4};
|
iovec_t const b = {&buf[0], 4};
|
||||||
storage_error se;
|
storage_error se;
|
||||||
s->writev(b, piece_index_t(1), 0, 0, se);
|
s->writev(b, piece_index_t(1), 0, open_mode_t::read_write, se);
|
||||||
|
|
||||||
TEST_CHECK(exists(combine_path(test_path, combine_path("folder2", "test3.tmp"))));
|
TEST_CHECK(exists(combine_path(test_path, combine_path("folder2", "test3.tmp"))));
|
||||||
TEST_CHECK(exists(combine_path(test_path, combine_path("_folder3", "test4.tmp"))));
|
TEST_CHECK(exists(combine_path(test_path, combine_path("_folder3", "test4.tmp"))));
|
||||||
|
@ -1391,7 +1391,7 @@ TORRENT_TEST(move_storage_into_self)
|
||||||
|
|
||||||
iovec_t const b = {&buf[0], 4};
|
iovec_t const b = {&buf[0], 4};
|
||||||
storage_error se;
|
storage_error se;
|
||||||
s->writev(b, piece_index_t(2), 0, 0, se);
|
s->writev(b, piece_index_t(2), 0, open_mode_t::read_write, se);
|
||||||
|
|
||||||
std::string const test_path = combine_path(save_path, combine_path("temp_storage", "folder1"));
|
std::string const test_path = combine_path(save_path, combine_path("temp_storage", "folder1"));
|
||||||
s->move_storage(test_path, 0, se);
|
s->move_storage(test_path, 0, se);
|
||||||
|
@ -1437,7 +1437,7 @@ TORRENT_TEST(dont_move_intermingled_files)
|
||||||
|
|
||||||
iovec_t b = {&buf[0], 4};
|
iovec_t b = {&buf[0], 4};
|
||||||
storage_error se;
|
storage_error se;
|
||||||
s->writev(b, piece_index_t(2), 0, 0, se);
|
s->writev(b, piece_index_t(2), 0, open_mode_t::read_write, se);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
create_directory(combine_path(save_path, combine_path("temp_storage"
|
create_directory(combine_path(save_path, combine_path("temp_storage"
|
||||||
|
@ -1445,11 +1445,11 @@ TORRENT_TEST(dont_move_intermingled_files)
|
||||||
TEST_EQUAL(ec, boost::system::errc::success);
|
TEST_EQUAL(ec, boost::system::errc::success);
|
||||||
file f;
|
file f;
|
||||||
f.open(combine_path(save_path, combine_path("temp_storage", "alien1.tmp"))
|
f.open(combine_path(save_path, combine_path("temp_storage", "alien1.tmp"))
|
||||||
, file::write_only, ec);
|
, open_mode_t::write_only, ec);
|
||||||
f.close();
|
f.close();
|
||||||
TEST_EQUAL(ec, boost::system::errc::success);
|
TEST_EQUAL(ec, boost::system::errc::success);
|
||||||
f.open(combine_path(save_path, combine_path("temp_storage"
|
f.open(combine_path(save_path, combine_path("temp_storage"
|
||||||
, combine_path("folder1", "alien2.tmp"))), file::write_only, ec);
|
, combine_path("folder1", "alien2.tmp"))), open_mode_t::write_only, ec);
|
||||||
f.close();
|
f.close();
|
||||||
TEST_EQUAL(ec, boost::system::errc::success);
|
TEST_EQUAL(ec, boost::system::errc::success);
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ struct test_storage : default_storage
|
||||||
span<iovec_t const> bufs
|
span<iovec_t const> bufs
|
||||||
, piece_index_t piece_index
|
, piece_index_t piece_index
|
||||||
, int offset
|
, int offset
|
||||||
, std::uint32_t const flags
|
, open_mode_t const flags
|
||||||
, storage_error& se) override
|
, storage_error& se) override
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_mutex);
|
std::unique_lock<std::mutex> l(m_mutex);
|
||||||
|
|
|
@ -50,7 +50,7 @@ TORRENT_TEST(web_seed_redirect)
|
||||||
|
|
||||||
char random_data[16000];
|
char random_data[16000];
|
||||||
std::generate(random_data, random_data + sizeof(random_data), random_byte);
|
std::generate(random_data, random_data + sizeof(random_data), random_byte);
|
||||||
file f("test_file", file::write_only, ec);
|
file f("test_file", open_mode_t::write_only, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
std::printf("failed to create file \"test_file\": (%d) %s\n"
|
std::printf("failed to create file \"test_file\": (%d) %s\n"
|
||||||
|
|
Loading…
Reference in New Issue