make disk job flags type safe

This commit is contained in:
arvidn 2017-09-09 19:43:54 +02:00 committed by Arvid Norberg
parent a86bc767de
commit 55228756e5
12 changed files with 68 additions and 59 deletions

View File

@ -123,19 +123,26 @@ namespace libtorrent {
using pool_file_status = open_file_state;
#endif
struct disk_job_flags_tag;
using disk_job_flags_t = flags::bitfield_flag<std::uint8_t, disk_job_flags_tag>;
struct TORRENT_EXTRA_EXPORT disk_interface
{
enum flags_t : std::uint8_t
{
sequential_access = 0x1,
// force making a copy of the cached block, rather
// than getting a reference to the block already in
// the cache.
static constexpr disk_job_flags_t force_copy = 0_bit;
// this flag is set on a job when a read operation did
// not hit the disk, but found the data in the read cache.
cache_hit = 0x2,
// hint that there may be more disk operations with sequential access to
// the file
static constexpr disk_job_flags_t sequential_access = 3_bit;
// don't keep the read block in cache
volatile_read = 0x10,
};
// don't keep the read block in cache
static constexpr disk_job_flags_t volatile_read = 4_bit;
// this flag is set on a job when a read operation did
// not hit the disk, but found the data in the read cache.
static constexpr disk_job_flags_t cache_hit = 5_bit;
virtual storage_holder new_torrent(storage_constructor_type sc
, storage_params p, std::shared_ptr<void> const&) = 0;
@ -143,13 +150,13 @@ namespace libtorrent {
virtual storage_interface* get_torrent(storage_index_t) = 0;
virtual void async_read(storage_index_t storage, peer_request const& r
, std::function<void(disk_buffer_holder block, std::uint32_t flags, storage_error const& se)> handler
, std::uint8_t flags = 0) = 0;
, std::function<void(disk_buffer_holder block, disk_job_flags_t flags, storage_error const& se)> handler
, disk_job_flags_t flags = {}) = 0;
virtual bool async_write(storage_index_t storage, peer_request const& r
, char const* buf, std::shared_ptr<disk_observer> o
, std::function<void(storage_error const&)> handler
, std::uint8_t flags = 0) = 0;
virtual void async_hash(storage_index_t storage, piece_index_t piece, std::uint8_t flags
, disk_job_flags_t flags = {}) = 0;
virtual void async_hash(storage_index_t storage, piece_index_t piece, disk_job_flags_t flags
, std::function<void(piece_index_t, sha1_hash const&, storage_error const&)> handler) = 0;
virtual void async_move_storage(storage_index_t storage, std::string p, move_flags_t flags
, std::function<void(status_t, std::string const&, storage_error const&)> handler) = 0;

View File

@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/vector.hpp"
#include "libtorrent/units.hpp"
#include "libtorrent/session_types.hpp"
#include "libtorrent/flags.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/variant/variant.hpp>
@ -99,23 +100,15 @@ namespace libtorrent {
void call_callback();
enum flags_t
{
// force making a copy of the cached block, rather
// than getting a reference to the block already in
// the cache.
force_copy = 0x4,
// this is set by the storage object when a fence is raised
// for this job. It means that this no other jobs on the same
// storage will execute in parallel with this one. It's used
// to lower the fence when the job has completed
static constexpr disk_job_flags_t fence = 1_bit;
// this is set by the storage object when a fence is raised
// for this job. It means that this no other jobs on the same
// storage will execute in parallel with this one. It's used
// to lower the fence when the job has completed
fence = 0x8,
// this job is currently being performed, or it's hanging
// on a cache piece that may be flushed soon
in_progress = 0x20
};
// this job is currently being performed, or it's hanging
// on a cache piece that may be flushed soon
static constexpr disk_job_flags_t in_progress = 2_bit;
// for write jobs, returns true if its block
// is not dirty anymore
@ -136,7 +129,7 @@ namespace libtorrent {
// this is called when operation completes
using read_handler = std::function<void(disk_buffer_holder block, std::uint32_t flags, storage_error const& se)>;
using read_handler = std::function<void(disk_buffer_holder block, disk_job_flags_t flags, storage_error const& se)>;
using write_handler = std::function<void(storage_error const&)>;
using hash_handler = std::function<void(piece_index_t, sha1_hash const&, storage_error const&)>;
using move_handler = std::function<void(status_t, std::string const&, storage_error const&)>;
@ -200,7 +193,7 @@ namespace libtorrent {
status_t ret = status_t::no_error;
// flags controlling this job
std::uint8_t flags = 0;
disk_job_flags_t flags{};
move_flags_t move_flags = move_flags_t::always_replace_files;

View File

@ -300,12 +300,12 @@ namespace aux {
void async_read(storage_index_t storage, peer_request const& r
, std::function<void(disk_buffer_holder block
, std::uint32_t flags, storage_error const& se)> handler, std::uint8_t flags = 0) override;
, disk_job_flags_t flags, storage_error const& se)> handler, disk_job_flags_t flags = {}) override;
bool async_write(storage_index_t storage, peer_request const& r
, char const* buf, std::shared_ptr<disk_observer> o
, std::function<void(storage_error const&)> handler
, std::uint8_t flags = 0) override;
void async_hash(storage_index_t storage, piece_index_t piece, std::uint8_t flags
, disk_job_flags_t flags = {}) override;
void async_hash(storage_index_t storage, piece_index_t piece, disk_job_flags_t flags
, std::function<void(piece_index_t, sha1_hash const&, storage_error const&)> handler) override;
void async_move_storage(storage_index_t storage, std::string p, move_flags_t flags
, std::function<void(status_t, std::string const&, storage_error const&)> handler) override;

View File

@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/piece_block.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/aux_/vector.hpp"
#include "libtorrent/disk_interface.hpp"
#include <ctime>
#include <algorithm>
@ -758,7 +759,7 @@ namespace aux {
void do_update_interest();
void fill_send_buffer();
void on_disk_read_complete(disk_buffer_holder disk_block, int flags
void on_disk_read_complete(disk_buffer_holder disk_block, disk_job_flags_t flags
, storage_error const& error, peer_request const& r, time_point issue_time);
void on_disk_write_complete(storage_error const& error
, peer_request const &r, std::shared_ptr<torrent> t);

View File

@ -424,7 +424,7 @@ namespace libtorrent {
error_code error;
};
void read_piece(piece_index_t piece);
void on_disk_read_complete(disk_buffer_holder block, int flags, storage_error const& se
void on_disk_read_complete(disk_buffer_holder block, disk_job_flags_t, storage_error const& se
, peer_request const& r, std::shared_ptr<read_piece_struct> rp);
storage_mode_t storage_mode() const;

View File

@ -373,7 +373,7 @@ int block_cache::try_read(disk_io_job* j, buffer_allocator_interface& allocator
#if TORRENT_USE_ASSERTS
p->piece_log.push_back(piece_log_t(j->action, j->d.io.offset / 0x4000));
#endif
cache_hit(p, j->d.io.offset / block_size(), (j->flags & disk_interface::volatile_read) != 0);
cache_hit(p, j->d.io.offset / block_size(), bool(j->flags & disk_interface::volatile_read));
ret = copy_from_piece(p, j, allocator, expect_no_fail);
if (ret < 0) return ret;
@ -1253,7 +1253,7 @@ void block_cache::insert_blocks(cached_piece_entry* pe, int block, span<iovec_t
TORRENT_ASSERT(pe->in_use);
TORRENT_PIECE_ASSERT(iov.size() > 0, pe);
cache_hit(pe, j->d.io.offset / block_size(), (j->flags & disk_interface::volatile_read) != 0);
cache_hit(pe, j->d.io.offset / block_size(), bool(j->flags & disk_interface::volatile_read));
TORRENT_ASSERT(pe->in_use);
@ -1694,7 +1694,7 @@ int block_cache::copy_from_piece(cached_piece_entry* const pe
// if block_offset > 0, we need to read two blocks, and then
// copy parts of both, because it's not aligned to the block
// boundaries
if (blocks_to_read == 1 && (j->flags & disk_io_job::force_copy) == 0)
if (blocks_to_read == 1 && !(j->flags & disk_interface::force_copy))
{
// special case for block aligned request
// don't actually copy the buffer, just reference

View File

@ -100,6 +100,9 @@ namespace libtorrent {
};
}
constexpr disk_job_flags_t disk_io_job::fence;
constexpr disk_job_flags_t disk_io_job::in_progress;
disk_io_job::disk_io_job()
: argument(remove_flags_t{})
, piece(0)

View File

@ -185,6 +185,11 @@ namespace libtorrent {
} // anonymous namespace
constexpr disk_job_flags_t disk_interface::force_copy;
constexpr disk_job_flags_t disk_interface::sequential_access;
constexpr disk_job_flags_t disk_interface::volatile_read;
constexpr disk_job_flags_t disk_interface::cache_hit;
// ------- disk_io_thread ------
disk_io_thread::disk_io_thread(io_service& ios
@ -1559,8 +1564,8 @@ namespace libtorrent {
}
void disk_io_thread::async_read(storage_index_t storage, peer_request const& r
, std::function<void(disk_buffer_holder block, std::uint32_t const flags
, storage_error const& se)> handler, std::uint8_t const flags)
, std::function<void(disk_buffer_holder block, disk_job_flags_t const flags
, storage_error const& se)> handler, disk_job_flags_t const flags)
{
TORRENT_ASSERT(r.length <= m_disk_cache.block_size());
TORRENT_ASSERT(r.length <= 16 * 1024);
@ -1672,7 +1677,7 @@ namespace libtorrent {
bool disk_io_thread::async_write(storage_index_t const storage, peer_request const& r
, char const* buf, std::shared_ptr<disk_observer> o
, std::function<void(storage_error const&)> handler
, std::uint8_t const flags)
, disk_job_flags_t const flags)
{
TORRENT_ASSERT(r.length <= m_disk_cache.block_size());
TORRENT_ASSERT(r.length <= 16 * 1024);
@ -1765,7 +1770,7 @@ namespace libtorrent {
}
void disk_io_thread::async_hash(storage_index_t const storage
, piece_index_t piece, std::uint8_t flags
, piece_index_t piece, disk_job_flags_t const flags
, std::function<void(piece_index_t, sha1_hash const&, storage_error const&)> handler)
{
disk_io_job* j = allocate_job(job_action_t::hash);
@ -2212,7 +2217,7 @@ namespace libtorrent {
#endif
int const block_size = m_disk_cache.block_size();
m_disk_cache.cache_hit(pe, j->d.io.offset / block_size
, (j->flags & disk_interface::volatile_read) != 0);
, bool(j->flags & disk_interface::volatile_read));
TORRENT_PIECE_ASSERT(pe->cache_state <= cached_piece_entry::read_lru1 || pe->cache_state == cached_piece_entry::read_lru2, pe);
{
@ -2893,7 +2898,7 @@ namespace libtorrent {
}
else
{
TORRENT_ASSERT((fj->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(fj->flags & disk_io_job::in_progress));
TORRENT_ASSERT(fj->blocked);
}
@ -3270,7 +3275,7 @@ namespace libtorrent {
ret += j->storage->job_complete(j, new_jobs);
}
TORRENT_ASSERT(ret == new_jobs.size());
TORRENT_ASSERT((j->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(j->flags & disk_io_job::in_progress));
#if TORRENT_USE_ASSERTS
TORRENT_ASSERT(j->job_posted == false);
j->job_posted = true;

View File

@ -81,7 +81,7 @@ namespace libtorrent { namespace aux {
// executing currently, we should add the fence job.
if (m_outstanding_jobs == 0 && jobs.empty())
{
TORRENT_ASSERT((bj->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(bj->flags & disk_io_job::in_progress));
bj->flags |= disk_io_job::in_progress;
++m_outstanding_jobs;
++ret;
@ -98,7 +98,7 @@ namespace libtorrent { namespace aux {
}
return ret;
}
TORRENT_ASSERT((bj->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(bj->flags & disk_io_job::in_progress));
bj->flags |= disk_io_job::in_progress;
++m_outstanding_jobs;
@ -125,7 +125,7 @@ namespace libtorrent { namespace aux {
disk_io_job *bj = static_cast<disk_io_job*>(m_blocked_jobs.pop_front());
TORRENT_ASSERT(bj->flags & disk_io_job::fence);
TORRENT_ASSERT((bj->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(bj->flags & disk_io_job::in_progress));
bj->flags |= disk_io_job::in_progress;
++m_outstanding_jobs;
@ -149,7 +149,7 @@ namespace libtorrent { namespace aux {
// this job still needs to get queued up
if (m_has_fence == 0)
{
TORRENT_ASSERT((j->flags & disk_io_job::in_progress) == 0);
TORRENT_ASSERT(!(j->flags & disk_io_job::in_progress));
j->flags |= disk_io_job::in_progress;
++m_outstanding_jobs;
return false;
@ -183,7 +183,7 @@ namespace libtorrent { namespace aux {
int disk_job_fence::raise_fence(disk_io_job* j, disk_io_job* fj
, counters& cnt)
{
TORRENT_ASSERT((j->flags & disk_io_job::fence) == 0);
TORRENT_ASSERT(!(j->flags & disk_io_job::fence));
j->flags |= disk_io_job::fence;
std::lock_guard<std::mutex> l(m_mutex);

View File

@ -5121,7 +5121,7 @@ namespace libtorrent {
#endif
// this means we're in seed mode and we haven't yet
// verified this piece (r.piece)
m_disk_thread.async_hash(t->storage(), r.piece, 0
m_disk_thread.async_hash(t->storage(), r.piece, {}
, std::bind(&peer_connection::on_seed_mode_hashed, self()
, _1, _2, _3));
t->verifying(r.piece);
@ -5232,7 +5232,7 @@ namespace libtorrent {
}
void peer_connection::on_disk_read_complete(disk_buffer_holder buffer
, int const flags, storage_error const& error
, disk_job_flags_t const flags, storage_error const& error
, peer_request const& r, time_point issue_time)
{
TORRENT_ASSERT(is_single_thread());
@ -5312,7 +5312,7 @@ namespace libtorrent {
// if it's rare enough to make it into the suggested piece
// push another piece out
if (m_settings.get_int(settings_pack::suggest_mode) == settings_pack::suggest_read_cache
&& (flags & disk_interface::cache_hit) == 0)
&& !(flags & disk_interface::cache_hit))
{
t->add_suggest_piece(r.piece);
}

View File

@ -151,7 +151,7 @@ namespace {
m_torrent.session().disk_thread().async_read(m_torrent.storage(), r
, std::bind(&smart_ban_plugin::on_read_failed_block
, shared_from_this(), pb, i->address(), _1, r.length, _2, _3)
, disk_io_job::force_copy);
, disk_interface::force_copy);
}
r.start += 16*1024;
@ -173,7 +173,7 @@ namespace {
};
void on_read_failed_block(piece_block b, address a
, disk_buffer_holder buffer, int const block_size, int
, disk_buffer_holder buffer, int const block_size, disk_job_flags_t
, storage_error const& error)
{
TORRENT_ASSERT(m_torrent.session().is_single_thread());
@ -255,7 +255,7 @@ namespace {
}
void on_read_ok_block(std::pair<piece_block, block_entry> b, address a
, disk_buffer_holder buffer, int const block_size, int
, disk_buffer_holder buffer, int const block_size, disk_job_flags_t
, storage_error const& error)
{
TORRENT_ASSERT(m_torrent.session().is_single_thread());

View File

@ -1162,7 +1162,7 @@ namespace libtorrent {
catch (...) { handle_exception(); }
void torrent::on_disk_read_complete(disk_buffer_holder buffer
, int, storage_error const& se
, disk_job_flags_t, storage_error const& se
, peer_request const& r, std::shared_ptr<read_piece_struct> rp) try
{
// hold a reference until this function returns
@ -10185,7 +10185,7 @@ namespace libtorrent {
TORRENT_ASSERT(m_storage);
m_ses.disk_thread().async_hash(m_storage, piece, 0
m_ses.disk_thread().async_hash(m_storage, piece, {}
, std::bind(&torrent::on_piece_verified, shared_from_this(), _1, _2, _3));
}