diff --git a/ChangeLog b/ChangeLog index 4e82969d5..7a3245e3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -84,15 +84,20 @@ * resume data no longer has timestamps of files * require C++11 to build libtorrent + * improve error handling of failing to change file priority + The API for custom storage implementations was altered * set the hidden attribute when creating the part file + * fix tracker announces reporting more data downloaded than the size of the torrent * fix recent regression with force_proxy setting + +1.1.7 release + * don't perform DNS lookups for the DHT bootstrap unless DHT is enabled * fix issue where setting file/piece priority would stop checking * expose post_dht_stats() to python binding * fix backwards compatibility to downloads without partfiles * improve part-file related error messages * fix reporting &redundant= in tracker announces - * fix tracker announces reporting more data downloaded than the size of the torrent * fix tie-break in duplicate peer connection disconnect logic * fix issue with SSL tracker connections left in CLOSE_WAIT state * defer truncating existing files until the first time we write to them diff --git a/include/libtorrent/disk_interface.hpp b/include/libtorrent/disk_interface.hpp index 0653abb82..5020022a4 100644 --- a/include/libtorrent/disk_interface.hpp +++ b/include/libtorrent/disk_interface.hpp @@ -172,7 +172,7 @@ namespace libtorrent { , std::function handler) = 0; virtual void async_set_file_priority(storage_index_t storage , aux::vector prio - , std::function handler) = 0; + , std::function const&)> handler) = 0; virtual void async_clear_piece(storage_index_t storage, piece_index_t index , std::function handler) = 0; diff --git a/include/libtorrent/disk_io_job.hpp b/include/libtorrent/disk_io_job.hpp index 321c3034d..82345a33c 100644 --- a/include/libtorrent/disk_io_job.hpp +++ b/include/libtorrent/disk_io_job.hpp @@ -140,6 +140,7 @@ namespace libtorrent { using check_handler = std::function; using rename_handler = std::function; using clear_piece_handler = std::function; + using set_file_prio_handler = std::function const&)>; boost::variant callback; + , clear_piece_handler + , set_file_prio_handler> callback; // the error code from the file operation // on error, this also contains the path of the diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 1fd03dae7..05751452d 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -324,7 +324,7 @@ namespace aux { , std::function handler = std::function()) override; void async_set_file_priority(storage_index_t storage , aux::vector prio - , std::function handler) override; + , std::function const&)> handler) override; void async_clear_piece(storage_index_t storage, piece_index_t index , std::function handler) override; diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 80c0834ee..e8ae9c39b 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -232,7 +232,7 @@ namespace libtorrent { // change the priorities of files. This is a fenced job and is // guaranteed to be the only running function on this storage // when called - virtual void set_file_priority(aux::vector const& prio + virtual void set_file_priority(aux::vector& prio , storage_error& ec) = 0; // This function should move all the files belonging to the storage to @@ -390,7 +390,7 @@ namespace libtorrent { ~default_storage() override; bool has_any_file(storage_error& ec) override; - void set_file_priority(aux::vector const& prio + void set_file_priority(aux::vector& prio , storage_error& ec) override; void rename_file(file_index_t index, std::string const& new_filename , storage_error& ec) override; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ab5ac7f88..179420799 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -569,7 +569,7 @@ namespace libtorrent { void set_file_priority(file_index_t index, download_priority_t priority); download_priority_t file_priority(file_index_t index) const; - void on_file_priority(storage_error const&); + void on_file_priority(storage_error const& err, aux::vector const& prios); void prioritize_files(aux::vector const& files); void file_priorities(aux::vector*) const; diff --git a/src/disk_io_job.cpp b/src/disk_io_job.cpp index c312aea17..29d3036e2 100644 --- a/src/disk_io_job.cpp +++ b/src/disk_io_job.cpp @@ -97,6 +97,12 @@ namespace libtorrent { h(m_job.piece); } + void operator()(disk_io_job::set_file_prio_handler& h) const + { + if (!h) return; + h(m_job.error, boost::get>(m_job.argument)); + } + private: disk_io_job& m_job; }; diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index eff018b4b..42d8ef60c 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -1922,7 +1922,7 @@ constexpr disk_job_flags_t disk_interface::cache_hit; void disk_io_thread::async_set_file_priority(storage_index_t const storage , aux::vector prios - , std::function handler) + , std::function const&)> handler) { disk_io_job* j = allocate_job(job_action_t::file_priority); j->storage = m_torrents[storage]->shared_from_this(); @@ -2733,7 +2733,7 @@ constexpr disk_job_flags_t disk_interface::cache_hit; status_t disk_io_thread::do_file_priority(disk_io_job* j, jobqueue_t& /* completed_jobs */ ) { j->storage->set_file_priority( - boost::get>(j->argument) + boost::get&>(j->argument) , j->error); return status_t::no_error; } diff --git a/src/storage.cpp b/src/storage.cpp index 027df4027..f8c137802 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -111,7 +111,7 @@ namespace libtorrent { } void default_storage::set_file_priority( - aux::vector const& prio + aux::vector& prio , storage_error& ec) { // extend our file priorities in case it's truncated @@ -135,6 +135,7 @@ namespace libtorrent { { ec.file(i); ec.operation = operation_t::file_open; + prio = m_file_priority; return; } @@ -152,6 +153,7 @@ namespace libtorrent { { ec.file(i); ec.operation = operation_t::partfile_write; + prio = m_file_priority; return; } } @@ -168,7 +170,13 @@ namespace libtorrent { file_handle f = open_file(i, open_mode::read_only, ec); if (ec.ec != boost::system::errc::no_such_file_or_directory) { - if (ec) return; + if (ec) + { + ec.file = i; + ec.operation = storage_error::open; + prio = m_file_priority; + return; + } need_partfile(); @@ -177,6 +185,7 @@ namespace libtorrent { { ec.file(i); ec.operation = operation_t::partfile_read; + prio = m_file_priority; return; } // remove the file @@ -186,6 +195,8 @@ namespace libtorrent { { ec.file(i); ec.operation = operation_t::file_remove; + prio = m_file_priority; + return; } } */ @@ -737,7 +748,7 @@ namespace { explicit disabled_storage(file_storage const& fs) : storage_interface(fs) {} bool has_any_file(storage_error&) override { return false; } - void set_file_priority(aux::vector const& + void set_file_priority(aux::vector& , storage_error&) override {} void rename_file(file_index_t, std::string const&, storage_error&) override {} void release_files(storage_error&) override {} @@ -799,7 +810,7 @@ namespace { } bool has_any_file(storage_error&) override { return false; } - void set_file_priority(aux::vector const& /* prio */ + void set_file_priority(aux::vector& /* prio */ , storage_error&) override {} status_t move_storage(std::string const& /* save_path */ , move_flags_t, storage_error&) override { return status_t::no_error; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 1e856eaa2..59b2ba874 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -5014,7 +5014,23 @@ bool is_downloading_state(int const st) m_picker->piece_priorities(*pieces); } - void torrent::on_file_priority(storage_error const&) {} + void torrent::on_file_priority(storage_error const& err + , aux::vector const& prios) + { + COMPLETE_ASYNC("file_priority"); + if (m_file_priority == prios) return; + + // in this case, some file priorities failed to get set + m_file_priority = prios; + update_piece_priorities(); + + if (alerts().should_post()) + alerts().emplace_alert(err.ec + , resolve_filename(err.file()), err.operation, get_handle()); + + set_error(err.ec, err.file()); + pause(); + } void torrent::prioritize_files(aux::vector const& files) { @@ -5041,8 +5057,9 @@ bool is_downloading_state(int const st) // storage may be nullptr during construction and shutdown if (m_torrent_file->num_pieces() > 0 && m_storage) { + ADD_OUTSTANDING_ASYNC("file_priority"); m_ses.disk_thread().async_set_file_priority(m_storage - , m_file_priority, std::bind(&torrent::on_file_priority, shared_from_this(), _1)); + , m_file_priority, std::bind(&torrent::on_file_priority, shared_from_this(), _1, _2)); } update_piece_priorities(); @@ -5080,8 +5097,9 @@ bool is_downloading_state(int const st) // storage may be nullptr during shutdown if (m_storage) { + ADD_OUTSTANDING_ASYNC("file_priority"); m_ses.disk_thread().async_set_file_priority(m_storage - , m_file_priority, std::bind(&torrent::on_file_priority, shared_from_this(), _1)); + , m_file_priority, std::bind(&torrent::on_file_priority, shared_from_this(), _1, _2)); } update_piece_priorities(); } diff --git a/test/test_block_cache.cpp b/test/test_block_cache.cpp index fd17bf0bf..2a5546128 100644 --- a/test/test_block_cache.cpp +++ b/test/test_block_cache.cpp @@ -64,7 +64,7 @@ struct test_storage_impl : storage_interface } bool has_any_file(storage_error&) override { return false; } - void set_file_priority(aux::vector const& + void set_file_priority(aux::vector& , storage_error&) override {} status_t move_storage(std::string const&, move_flags_t , storage_error&) override { return status_t::no_error; } diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index 22b2c1dfd..4e599e0dc 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -79,7 +79,7 @@ struct test_storage : default_storage , m_limit(16 * 1024 * 2) {} - void set_file_priority(aux::vector const& + void set_file_priority(aux::vector& , storage_error&) override {} void set_limit(int lim)