diff --git a/ChangeLog b/ChangeLog index 8d526e1d3..0e2becbee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,6 +41,7 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * improve support for de-selected files in full allocation mode * fix dht_bootstrap_alert being posted * SetFileValidData fix on windows (prevents zero-fill) * fix minor lock_files issue on unix diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index daed272ad..975f855c6 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -116,6 +116,7 @@ namespace libtorrent , update_settings , read_and_hash , cache_piece + , file_priority #ifndef TORRENT_NO_DEPRECATE , finalize_file #endif diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 9dc0c366f..567a97495 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -75,6 +75,7 @@ POSSIBILITY OF SUCH DAMAGE. // struct temp_storage : storage_interface // { // temp_storage(file_storage const& fs) : m_files(fs) {} +// void set_file_priority(std::vector const& prio) {} // virtual bool initialize(bool allocate_files) { return false; } // virtual bool has_any_file() { return false; } // virtual int read(char* buf, int slot, int offset, int size) @@ -193,6 +194,7 @@ namespace libtorrent // hidden storage_interface(): m_disk_pool(0), m_settings(0) {} + // This function is called when the storage is to be initialized. The default storage // will create directories and empty files at this point. If ``allocate_files`` is true, // it will also ``ftruncate`` all files to their target size. @@ -205,6 +207,10 @@ namespace libtorrent // If so, the storage will be checked for existing pieces before starting the download. virtual bool has_any_file() = 0; + + // change the priorities of files. + virtual void set_file_priority(std::vector const& prio) = 0; + // These functions should read or write the data in or to the given ``slot`` at the given ``offset``. // It should read or write ``num_bufs`` buffers sequentially, where the size of each buffer // is specified in the buffer array ``bufs``. The file::iovec_t type has the following members:: @@ -407,6 +413,7 @@ namespace libtorrent // hidden ~default_storage(); + void set_file_priority(std::vector const& prio); #ifndef TORRENT_NO_DEPRECATE void finalize_file(int file); #endif @@ -495,6 +502,7 @@ namespace libtorrent { public: disabled_storage(int piece_size) : m_piece_size(piece_size) {} + void set_file_priority(std::vector const& prio) {} bool has_any_file() { return false; } bool rename_file(int, std::string const&) { return false; } bool release_files() { return false; } @@ -609,6 +617,10 @@ namespace libtorrent void async_move_storage(std::string const& p, int flags , boost::function const& handler); + void async_set_file_priority( + std::vector const& prios + , boost::function const& handler); + void async_save_resume_data( boost::function const& handler); @@ -707,6 +719,8 @@ namespace libtorrent int delete_files_impl() { return m_storage->delete_files(); } int rename_file_impl(int index, std::string const& new_filename) { return m_storage->rename_file(index, new_filename); } + void set_file_priority_impl(std::vector const& p) + { m_storage->set_file_priority(p); } int move_storage_impl(std::string const& save_path, int flags); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 661ca6061..e672eb153 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -2486,8 +2486,17 @@ namespace libtorrent if (ret != 0) { test_error(j); - break; } + break; + } + case disk_io_job::file_priority: + { + std::vector* p + = reinterpret_cast*>(j.buffer); + j.storage->set_file_priority_impl(*p); + delete p; + ret = 0; + break; } } } diff --git a/src/storage.cpp b/src/storage.cpp index dd50dfcec..42211cecd 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -397,6 +397,11 @@ namespace libtorrent default_storage::~default_storage() { m_pool.release(this); } + void default_storage::set_file_priority(std::vector const& prio) + { + m_file_priority = prio; + } + bool default_storage::initialize(bool allocate_files) { m_allocate_files = allocate_files; @@ -457,7 +462,6 @@ namespace libtorrent ec.clear(); } - std::vector().swap(m_file_priority); // close files that were opened in write mode m_pool.release(this); @@ -1525,6 +1529,19 @@ ret: { } + void piece_manager::async_set_file_priority( + std::vector const& prios + , boost::function const& handler) + { + std::vector* p = new std::vector(prios); + + disk_io_job j; + j.storage = this; + j.buffer = (char*)p; + j.action = disk_io_job::file_priority; + m_io_thread.add_job(j, handler); + } + void piece_manager::async_save_resume_data( boost::function const& handler) { diff --git a/src/torrent.cpp b/src/torrent.cpp index a8498c065..6733f873e 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3964,6 +3964,8 @@ namespace libtorrent } } + void nop() {} + void torrent::prioritize_files(std::vector const& files) { INVARIANT_CHECK; @@ -3989,6 +3991,13 @@ namespace libtorrent if (valid_metadata() && m_torrent_file->num_files() > int(m_file_priority.size())) m_file_priority.resize(m_torrent_file->num_files(), 1); + // stoage may be NULL during shutdown + if (m_torrent_file->num_pieces() > 0 && m_storage) + { + filesystem().async_set_file_priority(m_file_priority + , boost::bind(&nop)); + } + update_piece_priorities(); } @@ -4009,6 +4018,12 @@ namespace libtorrent } if (m_file_priority[index] == prio) return; m_file_priority[index] = prio; + // stoage may be NULL during shutdown + if (m_storage) + { + filesystem().async_set_file_priority(m_file_priority + , boost::bind(&nop)); + } update_piece_priorities(); } diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 80aab5dd6..6ad0dde17 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -167,7 +167,7 @@ struct test_storage : storage_interface virtual bool initialize(bool allocate_files) { return true; } virtual bool has_any_file() { return true; } - + virtual void set_file_priority(std::vector const& p) {} int write( const char* buf diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index 0a1a88111..13612a194 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -77,6 +77,7 @@ struct test_storage : storage_interface , m_written(0) , m_limit(16 * 1024 * 2) {} + virtual void set_file_priority(std::vector const& p) {} virtual bool initialize(bool allocate_files) { return m_lower_layer->initialize(allocate_files); }