diff --git a/include/libtorrent/aux_/posix_storage.hpp b/include/libtorrent/aux_/posix_storage.hpp index 7af292c51a..ac626f3170 100644 --- a/include/libtorrent/aux_/posix_storage.hpp +++ b/include/libtorrent/aux_/posix_storage.hpp @@ -68,7 +68,8 @@ namespace aux { , storage_error& error); bool has_any_file(storage_error& error); - void set_file_priority(aux::vector& prio + void set_file_priority(settings_interface const& + , aux::vector& prio , storage_error& ec); bool verify_resume_data(add_torrent_params const& rd , aux::vector const& links diff --git a/src/part_file.cpp b/src/part_file.cpp index 12f267e2dd..a76d07bf46 100644 --- a/src/part_file.cpp +++ b/src/part_file.cpp @@ -370,7 +370,6 @@ namespace libtorrent { span v = {buf.get(), block_to_copy}; auto bytes_read = aux::pread_all(file.fd(), v, slot_offset(slot) + piece_offset, ec); v = v.first(static_cast(bytes_read)); - TORRENT_ASSERT(!ec); if (ec || v.empty()) return; f(file_offset, {buf.get(), block_to_copy}); diff --git a/src/posix_disk_io.cpp b/src/posix_disk_io.cpp index c597f82c61..99a74a44a0 100644 --- a/src/posix_disk_io.cpp +++ b/src/posix_disk_io.cpp @@ -358,7 +358,7 @@ namespace { { posix_storage* st = m_torrents[storage].get(); storage_error error; - st->set_file_priority(prio, error); + st->set_file_priority(m_settings, prio, error); post(m_ios, [p = std::move(prio), h = std::move(handler), error] () mutable { h(error, std::move(p)); }); } diff --git a/src/posix_part_file.cpp b/src/posix_part_file.cpp index 163f81a952..3f5fa2c343 100644 --- a/src/posix_part_file.cpp +++ b/src/posix_part_file.cpp @@ -406,7 +406,6 @@ namespace aux { if (int(bytes_read) != block_to_copy) ec.assign(errno, generic_category()); - TORRENT_ASSERT(!ec); if (ec) return; f(file_offset, {buf.get(), block_to_copy}); diff --git a/src/posix_storage.cpp b/src/posix_storage.cpp index cfed5daae2..93585efa05 100644 --- a/src/posix_storage.cpp +++ b/src/posix_storage.cpp @@ -84,7 +84,8 @@ namespace aux { , files().num_pieces(), files().piece_length()); } - void posix_storage::set_file_priority(aux::vector& prio + void posix_storage::set_file_priority(settings_interface const& + , aux::vector& prio , storage_error& ec) { // extend our file priorities in case it's truncated diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 77a0cc9244..aa87527f4e 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -539,6 +539,118 @@ void test_rename(std::string const& test_path) TEST_EQUAL(s->files().file_path(0_file), "new_filename"); } +template +void test_pre_allocate() +{ + std::string const test_path = complete("pre_allocate_test_path"); + delete_dirs(combine_path(test_path, "temp_storage")); + + file_storage fs; + std::vector buf; + typename file_pool_type::type fp; + io_context ios; + + aux::session_settings set; + std::shared_ptr info = setup_torrent_info(fs, buf); + + aux::vector priorities{ + lt::dont_download, + lt::default_priority, + lt::default_priority, + lt::default_priority, + lt::default_priority, + }; + sha1_hash info_hash; + storage_params p{ + fs, + nullptr, + test_path, + storage_mode_allocate, + priorities, + info_hash + }; + auto s = make_storage(p, fp); + + // allocate the files and create the directories + storage_error se; + s->initialize(set, se); + if (se) + { + TEST_ERROR(se.ec.message().c_str()); + std::printf("storage::initialize %s: %d\n" + , se.ec.message().c_str(), static_cast(se.file())); + throw system_error(se.ec); + } + + std::vector piece1 = new_piece(0x4000); + span iov = span(piece1); + + // ensure all files, except the first one, have been allocated + for (auto i : fs.file_range()) + { + if (fs.file_size(i) > 0) + { + int ret = write(s, set, iov, fs.piece_index_at_file(i), 0, aux::open_mode::write, se); + TEST_EQUAL(ret, int(iov.size())); + TEST_CHECK(!se.ec); + } + + error_code ec; + file_status st; + std::string const path = fs.file_path(i, test_path); + stat_file(path, &st, ec); + if (i == file_index_t{0}) + { + // the first file has priority 0, and so should not be created + TEST_EQUAL(ec, boost::system::errc::no_such_file_or_directory); + } + else + { + TEST_CHECK(!ec); + std::cerr << "error: " << ec.message() << std::endl; + TEST_EQUAL(st.file_size, fs.file_size(i)); + +#ifdef TORRENT_WINDOWS + native_path_string path2 = convert_to_native_path_string(path); + FILE_STANDARD_INFO Standard; + TEST_CHECK(GetFileInformationByName(path2.c_str(), FILE_INFO_BY_HANDLE_CLASS::FileStandardInfo, &Standard, sizeof(FILE_STANDARD_INFO))); + TEST_EQUAL(Standard.AllocationSize, fs.file_size(i)); +#else + struct ::stat st2{}; + TEST_EQUAL(::stat(path.c_str(), &st2), 0); + TEST_CHECK(st2.st_blocks * 512 >= fs.file_size(i)); +#endif + } + } + + std::cerr << "set file priority" << std::endl; + // set priority of file 0 to non-zero, and make sure we create the file now + priorities[0_file] = lt::default_priority; + s->set_file_priority(set, priorities, se); + TEST_CHECK(!se.ec); + + for (auto i : fs.file_range()) + { + error_code ec; + file_status st; + std::string const path = fs.file_path(i, test_path); + stat_file(path, &st, ec); + std::cerr<< "error: " << ec.message() << std::endl; + TEST_CHECK(!ec); + +#ifdef TORRENT_WINDOWS + native_path_string path2 = convert_to_native_path_string(path); + FILE_STANDARD_INFO Standard; + TEST_CHECK(GetFileInformationByName(path2.c_str(), FILE_INFO_BY_HANDLE_CLASS::FileStandardInfo, &Standard, sizeof(FILE_STANDARD_INFO))); + TEST_EQUAL(Standard.AllocationSize, fs.file_size(i)); +#else + struct ::stat st2{}; + TEST_EQUAL(::stat(path.c_str(), &st2), 0); + TEST_CHECK(st2.st_blocks * 512 >= fs.file_size(i)); +#endif + } +} + using lt::operator""_bit; using check_files_flag_t = lt::flags::bitfield_flag; @@ -709,11 +821,15 @@ TORRENT_TEST(check_files_oversized_mmap) test_check_files(sparse | test_oversized, lt::mmap_disk_io_constructor); } - TORRENT_TEST(check_files_allocate_mmap) { test_check_files(zero_prio, lt::mmap_disk_io_constructor); } + +TORRENT_TEST(test_pre_allocate_mmap) +{ + test_pre_allocate(); +} #endif TORRENT_TEST(check_files_sparse_posix) { @@ -736,6 +852,14 @@ TORRENT_TEST(check_files_allocate_posix) test_check_files(zero_prio, lt::posix_disk_io_constructor); } +// posix_storage doesn't support pre-allocating files on non-windows +/* +TORRENT_TEST(test_pre_allocate_posix) +{ + test_pre_allocate(); +} +*/ + #if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE TORRENT_TEST(rename_mmap_disk_io) {