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)
|
||||
, size_t(std::min(left_in_piece, 0x4000))};
|
||||
storage_error error;
|
||||
st->writev(b, i, j, 0, error);
|
||||
st->writev(b, i, j, open_mode_t::write_only, error);
|
||||
if (error)
|
||||
std::fprintf(stderr, "storage error: %s\n", error.ec.message().c_str());
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ nobase_include_HEADERS = \
|
|||
file_pool.hpp \
|
||||
file_storage.hpp \
|
||||
fingerprint.hpp \
|
||||
flags.hpp \
|
||||
fwd.hpp \
|
||||
gzip.hpp \
|
||||
hasher.hpp \
|
||||
|
|
|
@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/string_view.hpp"
|
||||
#include "libtorrent/span.hpp"
|
||||
#include "libtorrent/aux_/storage_utils.hpp"
|
||||
#include "libtorrent/flags.hpp"
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
||||
|
@ -125,77 +126,86 @@ namespace libtorrent {
|
|||
|
||||
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
|
||||
{
|
||||
// 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(std::string const& p, std::uint32_t m, error_code& ec);
|
||||
file(std::string const& p, open_mode_t m, error_code& ec);
|
||||
~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;
|
||||
void close();
|
||||
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
|
||||
, 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
|
||||
, 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;
|
||||
|
||||
|
@ -209,7 +219,7 @@ namespace libtorrent {
|
|||
|
||||
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
|
||||
static bool has_manage_volume_privs;
|
||||
#endif
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace libtorrent {
|
|||
// file_storage ``fs`` opened at save path ``p``. ``m`` is the
|
||||
// file open mode (see file::open_mode_t).
|
||||
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);
|
||||
// release all files belonging to the specified storage_interface (``st``)
|
||||
// the overload that takes ``file_index`` releases only the file with
|
||||
|
@ -111,7 +111,7 @@ namespace libtorrent {
|
|||
file_handle file_ptr;
|
||||
time_point const opened{aux::time_now()};
|
||||
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
|
||||
|
|
|
@ -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:
|
||||
|
||||
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);
|
||||
|
||||
std::string m_path;
|
||||
|
|
|
@ -208,9 +208,9 @@ namespace libtorrent {
|
|||
// error. If there's an error, the ``storage_error`` must be filled out
|
||||
// to represent the error that occurred.
|
||||
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
|
||||
, 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
|
||||
// storage for a torrent. It should return true if any of the files that
|
||||
|
@ -398,9 +398,9 @@ namespace libtorrent {
|
|||
virtual bool tick() override;
|
||||
|
||||
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
|
||||
, 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
|
||||
// file_storage, otherwise returns the original file_storage object.
|
||||
|
@ -424,8 +424,8 @@ namespace libtorrent {
|
|||
mutable stat_cache m_stat_cache;
|
||||
|
||||
// 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_impl(file_index_t file, std::uint32_t mode, error_code& 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, open_mode_t mode, error_code& ec) const;
|
||||
|
||||
aux::vector<std::uint8_t, file_index_t> m_file_priority;
|
||||
std::string m_save_path;
|
||||
|
|
|
@ -117,12 +117,12 @@ namespace libtorrent {
|
|||
|
||||
#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)
|
||||
{
|
||||
std::uint32_t ret = 0;
|
||||
if (!(j->flags & disk_interface::sequential_access)) ret |= file::random_access;
|
||||
if (coalesce_buffers) ret |= file::coalesce_buffers;
|
||||
open_mode_t ret = open_mode_t::none;
|
||||
if (!(j->flags & disk_interface::sequential_access)) ret |= open_mode_t::random_access;
|
||||
if (coalesce_buffers) ret |= open_mode_t::coalesce_buffers;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -664,8 +664,8 @@ namespace libtorrent {
|
|||
DLOG("]\n");
|
||||
#endif
|
||||
|
||||
std::uint32_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 const file_flags = m_settings.get_bool(settings_pack::coalesce_writes)
|
||||
? open_mode_t::coalesce_buffers : open_mode_t::none;
|
||||
|
||||
// issue the actual write operation
|
||||
auto iov_start = iov;
|
||||
|
@ -1232,7 +1232,7 @@ namespace libtorrent {
|
|||
|
||||
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));
|
||||
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
|
||||
// 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));
|
||||
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));
|
||||
|
||||
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_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 block_size = m_disk_cache.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));
|
||||
|
||||
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 */ )
|
||||
{
|
||||
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));
|
||||
|
||||
std::unique_lock<std::mutex> l(m_cache_mutex);
|
||||
|
|
103
src/file.cpp
103
src/file.cpp
|
@ -326,10 +326,6 @@ done:
|
|||
# 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
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -342,6 +338,10 @@ static_assert((libtorrent::file::sparse & libtorrent::file::attribute_mask) == 0
|
|||
|
||||
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)
|
||||
: m_done(false)
|
||||
{
|
||||
|
@ -505,14 +505,11 @@ namespace libtorrent {
|
|||
bool file::has_manage_volume_privs = get_manage_volume_privs();
|
||||
#endif
|
||||
|
||||
file::file()
|
||||
: m_file_handle(INVALID_HANDLE_VALUE)
|
||||
, m_open_mode(0)
|
||||
file::file() : m_file_handle(INVALID_HANDLE_VALUE)
|
||||
{}
|
||||
|
||||
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_open_mode(0)
|
||||
{
|
||||
// the return value is not important, since the
|
||||
// error code contains the same information
|
||||
|
@ -524,20 +521,20 @@ namespace libtorrent {
|
|||
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();
|
||||
native_path_string file_path = convert_to_native_path_string(path);
|
||||
|
||||
#ifdef TORRENT_WINDOWS
|
||||
|
||||
struct open_mode_t
|
||||
struct win_open_mode_t
|
||||
{
|
||||
DWORD rw_mode;
|
||||
DWORD create_mode;
|
||||
};
|
||||
|
||||
static const open_mode_t mode_array[] =
|
||||
static std::array<win_open_mode_t, 3> const mode_array{
|
||||
{
|
||||
// read_only
|
||||
{GENERIC_READ, OPEN_EXISTING},
|
||||
|
@ -545,15 +542,15 @@ namespace libtorrent {
|
|||
{GENERIC_WRITE, OPEN_ALWAYS},
|
||||
// read_write
|
||||
{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_HIDDEN, // hidden
|
||||
FILE_ATTRIBUTE_NORMAL, // executable
|
||||
FILE_ATTRIBUTE_HIDDEN, // hidden + executable
|
||||
};
|
||||
}};
|
||||
|
||||
#if TORRENT_USE_WSTRING
|
||||
#define CreateFile_ CreateFileW
|
||||
|
@ -561,21 +558,21 @@ namespace libtorrent {
|
|||
#define CreateFile_ CreateFileA
|
||||
#endif
|
||||
|
||||
TORRENT_ASSERT((mode & rw_mask) < sizeof(mode_array)/sizeof(mode_array[0]));
|
||||
open_mode_t const& m = mode_array[mode & rw_mask];
|
||||
DWORD a = attrib_array[(mode & attribute_mask) >> 12];
|
||||
TORRENT_ASSERT(static_cast<std::size_t>(mode & open_mode_t::rw_mask) < mode_array.size());
|
||||
win_open_mode_t const& m = mode_array[static_cast<std::size_t>(mode & open_mode_t::rw_mask)];
|
||||
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
|
||||
// turns out that it isn't. That flag will break your operating system:
|
||||
// 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)
|
||||
| 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
|
||||
, (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);
|
||||
|
||||
#undef CreateFile_
|
||||
|
@ -591,7 +588,8 @@ namespace libtorrent {
|
|||
|
||||
// try to make the file sparse if supported
|
||||
// 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;
|
||||
overlapped_t ol;
|
||||
|
@ -609,7 +607,7 @@ namespace libtorrent {
|
|||
| S_IRGRP | S_IWGRP
|
||||
| S_IROTH | S_IWOTH;
|
||||
|
||||
if (mode & attribute_executable)
|
||||
if (test(mode & open_mode_t::attribute_executable))
|
||||
permissions |= S_IXGRP | S_IXOTH | S_IXUSR;
|
||||
#ifdef 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
|
||||
#ifdef O_NOATIME
|
||||
| ((mode & no_atime) ? O_NOATIME : 0)
|
||||
| (test(mode & open_mode_t::no_atime) ? O_NOATIME : 0)
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
| ((mode & no_cache) ? O_SYNC : 0)
|
||||
| (test(mode & open_mode_t::no_cache) ? O_SYNC : 0)
|
||||
#endif
|
||||
;
|
||||
|
||||
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);
|
||||
|
||||
#ifdef O_NOATIME
|
||||
// O_NOATIME is not allowed for files we don't own
|
||||
// so, if we get EPERM when we try to open with it
|
||||
// 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;
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
@ -659,7 +658,7 @@ namespace libtorrent {
|
|||
|
||||
#ifdef DIRECTIO_ON
|
||||
// for solaris
|
||||
if (mode & no_cache)
|
||||
if (test(mode & open_mode_t::no_cache))
|
||||
{
|
||||
int yes = 1;
|
||||
directio(native_handle(), DIRECTIO_ON);
|
||||
|
@ -668,7 +667,7 @@ namespace libtorrent {
|
|||
|
||||
#ifdef F_NOCACHE
|
||||
// for BSD/Mac
|
||||
if (mode & no_cache)
|
||||
if (test(mode & open_mode_t::no_cache))
|
||||
{
|
||||
int yes = 1;
|
||||
fcntl(native_handle(), F_NOCACHE, &yes);
|
||||
|
@ -681,7 +680,7 @@ namespace libtorrent {
|
|||
#endif
|
||||
|
||||
#ifdef POSIX_FADV_RANDOM
|
||||
if (mode & random_access)
|
||||
if (test(mode & open_mode_t::random_access))
|
||||
{
|
||||
// disable read-ahead
|
||||
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
|
||||
// flag set, but there are no sparse regions, unset
|
||||
// the flag
|
||||
std::uint32_t rw_mode = m_open_mode & rw_mask;
|
||||
if ((rw_mode != read_only)
|
||||
&& (m_open_mode & sparse)
|
||||
open_mode_t const rw_mode = m_open_mode & open_mode_t::rw_mask;
|
||||
if ((rw_mode != open_mode_t::read_only)
|
||||
&& test(m_open_mode & open_mode_t::sparse)
|
||||
&& !is_sparse(native_handle()))
|
||||
{
|
||||
overlapped_t ol;
|
||||
|
@ -791,7 +790,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
|||
|
||||
m_file_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
m_open_mode = 0;
|
||||
m_open_mode = open_mode_t::none;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -974,7 +973,7 @@ namespace {
|
|||
// this has to be thread safe and atomic. i.e. on posix systems it has to be
|
||||
// turned into a series of pread() calls
|
||||
std::int64_t file::readv(std::int64_t file_offset, 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)
|
||||
{
|
||||
|
@ -985,7 +984,8 @@ namespace {
|
|||
#endif
|
||||
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(is_open());
|
||||
|
||||
|
@ -997,16 +997,16 @@ namespace {
|
|||
// there's no point in coalescing single buffer writes
|
||||
if (bufs.size() == 1)
|
||||
{
|
||||
flags &= ~file::coalesce_buffers;
|
||||
flags &= ~open_mode_t::coalesce_buffers;
|
||||
}
|
||||
|
||||
iovec_t tmp;
|
||||
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))
|
||||
// ok, that failed, don't coalesce this read
|
||||
flags &= ~file::coalesce_buffers;
|
||||
flags &= ~open_mode_t::coalesce_buffers;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_PREAD
|
||||
|
@ -1015,7 +1015,7 @@ namespace {
|
|||
std::int64_t ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec);
|
||||
#endif
|
||||
|
||||
if ((flags & file::coalesce_buffers))
|
||||
if (test(flags & open_mode_t::coalesce_buffers))
|
||||
coalesce_read_buffers_end(bufs
|
||||
, tmp.data(), !ec);
|
||||
|
||||
|
@ -1027,7 +1027,7 @@ namespace {
|
|||
// that means, on posix this has to be turned into a series of
|
||||
// pwrite() calls
|
||||
std::int64_t file::writev(std::int64_t file_offset, 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)
|
||||
{
|
||||
|
@ -1038,7 +1038,8 @@ namespace {
|
|||
#endif
|
||||
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(is_open());
|
||||
|
||||
|
@ -1053,15 +1054,15 @@ namespace {
|
|||
// there's no point in coalescing single buffer writes
|
||||
if (bufs.size() == 1)
|
||||
{
|
||||
flags &= ~file::coalesce_buffers;
|
||||
flags &= ~open_mode_t::coalesce_buffers;
|
||||
}
|
||||
|
||||
iovec_t tmp;
|
||||
if (flags & file::coalesce_buffers)
|
||||
if (test(flags & open_mode_t::coalesce_buffers))
|
||||
{
|
||||
if (!coalesce_write_buffers(bufs, tmp))
|
||||
// ok, that failed, don't coalesce writes
|
||||
flags &= ~file::coalesce_buffers;
|
||||
flags &= ~open_mode_t::coalesce_buffers;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_PREAD
|
||||
|
@ -1070,14 +1071,14 @@ namespace {
|
|||
std::int64_t ret = iov(&::write, native_handle(), file_offset, bufs, ec);
|
||||
#endif
|
||||
|
||||
if (flags & file::coalesce_buffers)
|
||||
if (test(flags & open_mode_t::coalesce_buffers))
|
||||
delete[] tmp.data();
|
||||
|
||||
#endif
|
||||
#if TORRENT_USE_FDATASYNC \
|
||||
&& !defined F_NOCACHE && \
|
||||
!defined DIRECTIO_ON
|
||||
if (m_open_mode & no_cache)
|
||||
if (test(m_open_mode & open_mode_t::no_cache))
|
||||
{
|
||||
if (fdatasync(native_handle()) != 0
|
||||
&& errno != EINVAL
|
||||
|
@ -1192,7 +1193,7 @@ namespace {
|
|||
}
|
||||
|
||||
#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
|
||||
, FILE_INFO_BY_HANDLE_CLASS FileInformationClass
|
||||
|
@ -1247,7 +1248,7 @@ namespace {
|
|||
// is less than the file size. Otherwise we would just
|
||||
// update the modification time of the file for no good
|
||||
// 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)
|
||||
{
|
||||
// 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_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
|
||||
// about to be destructed. If we have such object we assign it to
|
||||
|
@ -119,8 +119,8 @@ namespace libtorrent {
|
|||
#endif
|
||||
|
||||
TORRENT_ASSERT(is_complete(p));
|
||||
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|
||||
|| (m & file::rw_mask) == file::read_write);
|
||||
TORRENT_ASSERT((m & open_mode_t::rw_mask) == open_mode_t::read_only
|
||||
|| (m & open_mode_t::rw_mask) == open_mode_t::read_write);
|
||||
auto const i = m_files.find(std::make_pair(st, file_index));
|
||||
if (i != m_files.end())
|
||||
{
|
||||
|
@ -130,9 +130,9 @@ namespace libtorrent {
|
|||
// if we asked for a file in write mode,
|
||||
// and the cached file is is not opened in
|
||||
// write mode, re-open it
|
||||
if ((((e.mode & file::rw_mask) != file::read_write)
|
||||
&& ((m & file::rw_mask) == file::read_write))
|
||||
|| (e.mode & file::random_access) != (m & file::random_access))
|
||||
if ((((e.mode & open_mode_t::rw_mask) != open_mode_t::read_write)
|
||||
&& ((m & open_mode_t::rw_mask) == open_mode_t::read_write))
|
||||
|| (e.mode & open_mode_t::random_access) != (m & open_mode_t::random_access))
|
||||
{
|
||||
file_handle new_file = std::make_shared<file>();
|
||||
|
||||
|
@ -182,26 +182,23 @@ namespace libtorrent {
|
|||
|
||||
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;
|
||||
switch (mode & file::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;
|
||||
}
|
||||
open_mode_t const rw_mode = mode & open_mode_t::rw_mask;
|
||||
|
||||
if (mode & file::sparse) ret |= file_open_mode::sparse;
|
||||
if (mode & file::no_atime) ret |= file_open_mode::no_atime;
|
||||
if (mode & file::random_access) ret |= file_open_mode::random_access;
|
||||
if (mode & file::lock_file) ret |= file_open_mode::locked;
|
||||
ret = (rw_mode == open_mode_t::read_only)
|
||||
? file_open_mode::read_only
|
||||
: (rw_mode == open_mode_t::write_only)
|
||||
? 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace libtorrent {
|
|||
|
||||
error_code ec;
|
||||
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;
|
||||
|
||||
// parse header
|
||||
|
@ -178,7 +178,7 @@ namespace libtorrent {
|
|||
TORRENT_ASSERT(offset >= 0);
|
||||
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;
|
||||
|
||||
auto const i = m_piece_map.find(piece);
|
||||
|
@ -206,7 +206,7 @@ namespace libtorrent {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
l.unlock();
|
||||
|
@ -215,15 +215,15 @@ namespace libtorrent {
|
|||
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()
|
||||
&& ((m_file.open_mode() & file::rw_mask) == mode
|
||||
|| mode == file::read_only)) return;
|
||||
&& ((m_file.open_mode() & open_mode_t::rw_mask) == mode
|
||||
|| mode == open_mode_t::read_only)) return;
|
||||
|
||||
std::string fn = combine_path(m_path, m_name);
|
||||
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)
|
||||
{
|
||||
// this means the directory the file is in doesn't exist.
|
||||
|
@ -301,7 +301,7 @@ namespace libtorrent {
|
|||
if (i != m_piece_map.end())
|
||||
{
|
||||
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 (!buf) buf.reset(new char[m_piece_size]);
|
||||
|
@ -375,7 +375,7 @@ namespace libtorrent {
|
|||
return;
|
||||
}
|
||||
|
||||
open_file(file::read_write, ec);
|
||||
open_file(open_mode_t::read_write, ec);
|
||||
if (ec) return;
|
||||
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
|
||||
need_partfile();
|
||||
|
@ -165,7 +165,7 @@ namespace libtorrent {
|
|||
if (exists(fp))
|
||||
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) return;
|
||||
|
@ -272,8 +272,8 @@ namespace libtorrent {
|
|||
}
|
||||
}
|
||||
ec.ec.clear();
|
||||
file_handle f = open_file(file_index, file::read_write
|
||||
| file::random_access, ec);
|
||||
file_handle f = open_file(file_index, open_mode_t::read_write
|
||||
| open_mode_t::random_access, ec);
|
||||
if (ec)
|
||||
{
|
||||
ec.file(file_index);
|
||||
|
@ -467,7 +467,7 @@ namespace libtorrent {
|
|||
|
||||
int default_storage::readv(span<iovec_t const> bufs
|
||||
, 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
|
||||
std::this_thread::sleep_for(seconds(1));
|
||||
|
@ -506,7 +506,7 @@ namespace libtorrent {
|
|||
}
|
||||
|
||||
file_handle handle = open_file(file_index
|
||||
, file::read_only | flags, ec);
|
||||
, open_mode_t::read_only | flags, ec);
|
||||
if (ec) return -1;
|
||||
|
||||
error_code e;
|
||||
|
@ -534,7 +534,7 @@ namespace libtorrent {
|
|||
|
||||
int default_storage::writev(span<iovec_t const> bufs
|
||||
, 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
|
||||
, [this, flags](file_index_t const file_index
|
||||
|
@ -573,7 +573,7 @@ namespace libtorrent {
|
|||
m_stat_cache.set_dirty(file_index);
|
||||
|
||||
file_handle handle = open_file(file_index
|
||||
, file::read_write, ec);
|
||||
, open_mode_t::read_write, ec);
|
||||
if (ec) return -1;
|
||||
|
||||
error_code e;
|
||||
|
@ -600,10 +600,10 @@ namespace libtorrent {
|
|||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
// this means the directory the file is in doesn't exist.
|
||||
|
@ -631,7 +631,7 @@ namespace libtorrent {
|
|||
}
|
||||
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);
|
||||
if (m_file_created.size() != files().num_files())
|
||||
|
@ -662,37 +662,37 @@ namespace libtorrent {
|
|||
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
|
||||
{
|
||||
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
|
||||
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 (m_settings
|
||||
&& settings().get_int(settings_pack::disk_io_write_mode)
|
||||
== 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
|
||||
, 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
|
||||
// possible we're failing because we have another handle to this
|
||||
// file in use (but waiting to be closed). Just retry to open it
|
||||
// without locking.
|
||||
mode &= ~file::lock_file;
|
||||
mode &= ~open_mode_t::lock_file;
|
||||
ret = m_pool.open_file(storage_index(), m_save_path, file, files()
|
||||
, mode, ec);
|
||||
}
|
||||
|
@ -740,12 +740,12 @@ namespace {
|
|||
status_t move_storage(std::string const&, int, storage_error&) override { return status_t::no_error; }
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -773,7 +773,7 @@ namespace {
|
|||
void initialize(storage_error&) override {}
|
||||
|
||||
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;
|
||||
for (auto const& b : bufs)
|
||||
|
@ -784,7 +784,7 @@ namespace {
|
|||
return 0;
|
||||
}
|
||||
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;
|
||||
for (auto const& b : bufs)
|
||||
|
|
|
@ -552,7 +552,7 @@ namespace libtorrent {
|
|||
{
|
||||
ec.clear();
|
||||
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);
|
||||
if (ec) return -1;
|
||||
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) };
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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"
|
||||
, full_path.c_str(), ec.value(), ec.message().c_str());
|
||||
std::int64_t offset = 0;
|
||||
|
|
|
@ -51,12 +51,12 @@ struct test_storage_impl : storage_interface
|
|||
void initialize(storage_error& ec) override {}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ void test_checking(int flags = read_only_files)
|
|||
path = combine_path(path, name);
|
||||
|
||||
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"
|
||||
, path.c_str(), ec.value(), ec.message().c_str());
|
||||
f.set_size(file_sizes[i] / 2, ec);
|
||||
|
|
|
@ -52,7 +52,7 @@ int touch_file(std::string const& filename, int size)
|
|||
|
||||
file f;
|
||||
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;
|
||||
iovec_t b = {&v[0], v.size()};
|
||||
std::int64_t written = f.writev(0, b, ec);
|
||||
|
@ -283,9 +283,9 @@ TORRENT_TEST(file)
|
|||
error_code ec;
|
||||
file f;
|
||||
#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
|
||||
TEST_CHECK(f.open("test_file", file::read_write, ec));
|
||||
TEST_CHECK(f.open("test_file", open_mode_t::read_write, ec));
|
||||
#endif
|
||||
if (ec)
|
||||
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
|
||||
error_code ec;
|
||||
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)
|
||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||
TEST_EQUAL(ec, error_code());
|
||||
|
@ -336,7 +336,7 @@ TORRENT_TEST(hard_link)
|
|||
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)
|
||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||
TEST_EQUAL(ec, error_code());
|
||||
|
@ -363,7 +363,7 @@ TORRENT_TEST(coalesce_buffer)
|
|||
{
|
||||
error_code ec;
|
||||
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)
|
||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||
TEST_EQUAL(ec, error_code());
|
||||
|
@ -371,7 +371,7 @@ TORRENT_TEST(coalesce_buffer)
|
|||
char test[] = "test";
|
||||
char foobar[] = "foobar";
|
||||
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)
|
||||
std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||
TEST_CHECK(!ec);
|
||||
|
|
|
@ -146,7 +146,7 @@ void write_test_file()
|
|||
std::srand(unsigned(std::time(nullptr)));
|
||||
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
||||
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);
|
||||
if (ec) std::printf("file error: %s\n", ec.message().c_str());
|
||||
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)
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
// test unaligned read (where the bytes are aligned)
|
||||
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);
|
||||
TEST_CHECK(std::equal(piece+3, piece + piece_size-9, piece1.data()+3));
|
||||
|
||||
// test unaligned read (where the bytes are not aligned)
|
||||
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);
|
||||
if (ret != piece_size - 9) print_error("readv", ret, ec);
|
||||
TEST_CHECK(std::equal(piece, piece + piece_size-9, piece1.data()+3));
|
||||
|
||||
// verify piece 1
|
||||
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);
|
||||
if (ret != piece_size) print_error("readv", ret, ec);
|
||||
TEST_CHECK(std::equal(piece, piece + piece_size, piece1.data()));
|
||||
|
||||
// do the same with piece 0 and 2 (in slot 1 and 2)
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
// verify piece 0 and 2
|
||||
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);
|
||||
TEST_CHECK(std::equal(piece, piece + piece_size, piece0.data()));
|
||||
|
||||
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);
|
||||
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};
|
||||
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"
|
||||
, 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);
|
||||
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"
|
||||
, 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};
|
||||
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("_folder3", "test4.tmp"))));
|
||||
|
@ -1391,7 +1391,7 @@ TORRENT_TEST(move_storage_into_self)
|
|||
|
||||
iovec_t const b = {&buf[0], 4};
|
||||
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"));
|
||||
s->move_storage(test_path, 0, se);
|
||||
|
@ -1437,7 +1437,7 @@ TORRENT_TEST(dont_move_intermingled_files)
|
|||
|
||||
iovec_t b = {&buf[0], 4};
|
||||
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;
|
||||
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);
|
||||
file f;
|
||||
f.open(combine_path(save_path, combine_path("temp_storage", "alien1.tmp"))
|
||||
, file::write_only, ec);
|
||||
, open_mode_t::write_only, ec);
|
||||
f.close();
|
||||
TEST_EQUAL(ec, boost::system::errc::success);
|
||||
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();
|
||||
TEST_EQUAL(ec, boost::system::errc::success);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ struct test_storage : default_storage
|
|||
span<iovec_t const> bufs
|
||||
, piece_index_t piece_index
|
||||
, int offset
|
||||
, std::uint32_t const flags
|
||||
, open_mode_t const flags
|
||||
, storage_error& se) override
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_mutex);
|
||||
|
|
|
@ -50,7 +50,7 @@ TORRENT_TEST(web_seed_redirect)
|
|||
|
||||
char random_data[16000];
|
||||
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)
|
||||
{
|
||||
std::printf("failed to create file \"test_file\": (%d) %s\n"
|
||||
|
|
Loading…
Reference in New Issue