From 1c867a50263cf2243442bfc01a2b731e87c7be81 Mon Sep 17 00:00:00 2001 From: d_komarov Date: Tue, 13 Mar 2018 21:13:56 +0200 Subject: [PATCH] Changing file priorities while checking interrupts checking. Also, if the last file has zero priority, checking is interrupted prematurely. --- ChangeLog | 1 + simulation/test_torrent_status.cpp | 12 +--- src/torrent.cpp | 101 +++++++++++++++-------------- test/setup_transfer.cpp | 5 +- test/setup_transfer.hpp | 4 +- test/test_checking.cpp | 92 +++++++++++++++++--------- test/test_torrent.cpp | 4 ++ 7 files changed, 127 insertions(+), 92 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94679ba1d..7834e139f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ + * 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 diff --git a/simulation/test_torrent_status.cpp b/simulation/test_torrent_status.cpp index 763404b36..7dd0b2703 100644 --- a/simulation/test_torrent_status.cpp +++ b/simulation/test_torrent_status.cpp @@ -87,16 +87,8 @@ TORRENT_TEST(status_timers) TEST_EQUAL(st.last_scrape, -1); TEST_EQUAL(st.time_since_upload, -1); - // checking the torrent counts as downloading - // eventually though, we've forgotten about it and go back to -1 - if (since_start > 65000) - { - TEST_EQUAL(st.time_since_download, -1); - } - else - { - TEST_EQUAL(st.time_since_download, since_start); - } + // checking the torrent does not count as downloading + TEST_EQUAL(st.time_since_download, -1); } return false; }); diff --git a/src/torrent.cpp b/src/torrent.cpp index d606fbe41..d3fc722e5 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -115,6 +115,26 @@ namespace libtorrent { namespace { + bool is_downloading_state(int st) + { + switch (st) + { + case torrent_status::checking_files: + case torrent_status::allocating: + case torrent_status::checking_resume_data: + return false; + case torrent_status::downloading_metadata: + case torrent_status::downloading: + case torrent_status::finished: + case torrent_status::seeding: + return true; + default: + // unexpected state + TORRENT_ASSERT_VAL(false, st); + return false; + } + } + int root2(int x) { int ret = 0; @@ -4368,23 +4388,26 @@ namespace { remove_time_critical_piece(index, true); - if (is_finished() - && m_state != torrent_status::finished - && m_state != torrent_status::seeding) + if (is_downloading_state(m_state)) { - // torrent finished - // i.e. all the pieces we're interested in have - // been downloaded. Release the files (they will open - // in read only mode if needed) - finished(); - // if we just became a seed, picker is now invalid, since it - // is deallocated by the torrent once it starts seeding + if (is_finished() + && m_state != torrent_status::finished + && m_state != torrent_status::seeding) + { + // torrent finished + // i.e. all the pieces we're interested in have + // been downloaded. Release the files (they will open + // in read only mode if needed) + finished(); + // if we just became a seed, picker is now invalid, since it + // is deallocated by the torrent once it starts seeding + } + + m_last_download = m_ses.session_time(); + + if (m_share_mode) + recalc_share_mode(); } - - m_last_download = m_ses.session_time(); - - if (m_share_mode) - recalc_share_mode(); } // this is called when the piece hash is checked as correct. Note @@ -5795,6 +5818,15 @@ namespace { p->update_interest(); } + if (!is_downloading_state(m_state)) + { +#ifndef TORRENT_DISABLE_LOGGING + debug_log("*** UPDATE_PEER_INTEREST [ skipping, state: %d ]" + , int(m_state)); +#endif + return; + } + #ifndef TORRENT_DISABLE_LOGGING debug_log("*** UPDATE_PEER_INTEREST [ finished: %d was_finished %d ]" , is_finished(), was_finished); @@ -8108,8 +8140,7 @@ namespace { return false; } - if ((m_state == torrent_status::checking_files - || m_state == torrent_status::checking_resume_data) + if (!is_downloading_state(m_state) && valid_metadata()) { p->disconnect(errors::torrent_not_ready, op_bittorrent); @@ -8646,16 +8677,9 @@ namespace { // to be in downloading state (which it will be set to shortly) // INVARIANT_CHECK; - if (m_state == torrent_status::checking_resume_data - || m_state == torrent_status::checking_files - || m_state == torrent_status::allocating) - { -#ifndef TORRENT_DISABLE_LOGGING - debug_log("*** RESUME_DOWNLOAD [ skipping, state: %d ]" - , int(m_state)); -#endif - return; - } + TORRENT_ASSERT(m_state != torrent_status::checking_resume_data + && m_state != torrent_status::checking_files + && m_state != torrent_status::allocating); // we're downloading now, which means we're no longer in seed mode if (m_seed_mode) @@ -11945,29 +11969,6 @@ namespace { if (m_peer_list) m_peer_list->clear_peer_prio(); } - namespace - { - bool is_downloading_state(int st) - { - switch (st) - { - case torrent_status::checking_files: - case torrent_status::allocating: - case torrent_status::checking_resume_data: - return false; - case torrent_status::downloading_metadata: - case torrent_status::downloading: - case torrent_status::finished: - case torrent_status::seeding: - return true; - default: - // unexpected state - TORRENT_ASSERT_VAL(false, st); - return false; - } - } - } - void torrent::stop_when_ready(bool b) { m_stop_when_ready = b; diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index b599e7e41..383507a4f 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -145,9 +145,10 @@ std::map get_counters(libtorrent::session& s) return ret; } -alert const* wait_for_alert(lt::session& ses, int type, char const* name, int num) +alert const* wait_for_alert(lt::session& ses, int type, char const* name, int num + , lt::time_duration timeout) { - time_point end = libtorrent::clock_type::now() + seconds(10); + time_point end = libtorrent::clock_type::now() + timeout; while (true) { time_point now = clock_type::now(); diff --git a/test/setup_transfer.hpp b/test/setup_transfer.hpp index 4ab871b0e..33b4ce69e 100644 --- a/test/setup_transfer.hpp +++ b/test/setup_transfer.hpp @@ -65,7 +65,9 @@ EXPORT libtorrent::sha1_hash rand_hash(); EXPORT std::map get_counters(libtorrent::session& s); EXPORT libtorrent::alert const* wait_for_alert( - libtorrent::session& ses, int type, char const* name = "", int num = 1); + libtorrent::session& ses, int type, char const* name = "" + , int num = 1 + , lt::time_duration timeout = lt::seconds(10)); EXPORT void print_ses_rate(float time , libtorrent::torrent_status const* st1 diff --git a/test/test_checking.cpp b/test/test_checking.cpp index 940927b93..8ff6a89f1 100644 --- a/test/test_checking.cpp +++ b/test/test_checking.cpp @@ -34,16 +34,29 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session.hpp" #include "test.hpp" +#include "settings.hpp" #include "setup_transfer.hpp" #include "libtorrent/create_torrent.hpp" #include "libtorrent/alert_types.hpp" #include "libtorrent/torrent_info.hpp" #include "libtorrent/torrent_status.hpp" -static const int file_sizes[] = -{ 0, 5, 16 - 5, 16000, 17, 10, 8000, 8000, 1,1,1,1,1,100,1,1,1,1,100,1,1,1,1,1,1 - ,1,1,1,1,1,1,13,65000,34,75,2,30,400,500,23000,900,43000,400,4300,6, 4}; -const int num_files = sizeof(file_sizes)/sizeof(file_sizes[0]); +namespace +{ + const int file_sizes[] = + { 0, 5, 16 - 5, 16000, 17, 10, 8000, 8000, 1,1,1,1,1,100,1,1,1,1,100,1,1,1,1,1,1 + ,1,1,1,1,1,1,13,65000,34,75,2,30,400,500,23000,900,43000,400,4300,6, 4 }; + const int num_files = sizeof(file_sizes) / sizeof(file_sizes[0]); + + bool is_checking(int const state) + { + return state == lt::torrent_status::checking_files +#ifndef TORRENT_NO_DEPRECATE + || state == lt::torrent_status::queued_for_checking +#endif + || state == lt::torrent_status::checking_resume_data; + }; +} enum { @@ -63,7 +76,7 @@ enum force_recheck = 8, }; -void test_checking(int flags = read_only_files) +void test_checking(int flags) { using namespace libtorrent; namespace lt = libtorrent; @@ -167,20 +180,7 @@ void test_checking(int flags = read_only_files) , ec.value(), ec.message().c_str()); } - int const mask = alert::all_categories - & ~(alert::progress_notification - | alert::performance_warning - | alert::stats_notification); - - settings_pack pack; - pack.set_bool(settings_pack::enable_lsd, false); - pack.set_bool(settings_pack::enable_natpmp, false); - pack.set_bool(settings_pack::enable_upnp, false); - pack.set_bool(settings_pack::enable_dht, false); - pack.set_int(settings_pack::alert_mask, mask); - pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:48000"); - pack.set_int(settings_pack::max_retry_port_bind, 1000); - lt::session ses1(pack); + lt::session ses1(settings()); add_torrent_params p; p.save_path = "."; @@ -216,15 +216,7 @@ void test_checking(int flags = read_only_files) printf("%d %f %s\n", st.state, st.progress_ppm / 10000.f, st.errc.message().c_str()); - if ( -#ifndef TORRENT_NO_DEPRECATE - st.state != torrent_status::queued_for_checking && -#endif - st.state != torrent_status::checking_files - && st.state != torrent_status::checking_resume_data) - break; - - if (st.errc) break; + if (!is_checking(st.state) || st.errc) break; test_sleep(500); } @@ -280,7 +272,7 @@ void test_checking(int flags = read_only_files) TORRENT_TEST(checking) { - test_checking(); + test_checking(0); } TORRENT_TEST(read_only_corrupt) @@ -308,3 +300,45 @@ TORRENT_TEST(force_recheck) test_checking(force_recheck); } +TORRENT_TEST(discrete_checking) +{ + using namespace lt; + printf("\n==== TEST CHECKING discrete =====\n\n"); + error_code ec; + create_directory("test_torrent_dir", ec); + if (ec) printf("ERROR: creating directory test_torrent_dir: (%d) %s\n", ec.value(), ec.message().c_str()); + + int const megabyte = 0x100000; + int const piece_size = 2 * megabyte; + int const file_sizes[] = { 9 * megabyte, 4 * megabyte }; + int const num_files = sizeof(file_sizes) / sizeof(file_sizes[0]); + + file_storage fs; + create_random_files("test_torrent_dir", file_sizes, num_files, &fs); + lt::create_torrent t(fs, piece_size, 0, lt::create_torrent::optimize_alignment); + set_piece_hashes(t, ".", ec); + if (ec) printf("ERROR: set_piece_hashes: (%d) %s\n", ec.value(), ec.message().c_str()); + + std::vector buf; + bencode(std::back_inserter(buf), t.generate()); + boost::shared_ptr ti(new torrent_info(&buf[0], buf.size(), ec)); + printf("generated torrent: %s test_torrent_dir\n", to_hex(ti->info_hash().to_string()).c_str()); + TEST_EQUAL(ti->num_files(), 3); + { + session ses1(settings()); + add_torrent_params p; + p.file_priorities.resize(ti->num_files()); + p.file_priorities[0] = 1; + p.save_path = "."; + p.ti = ti; + torrent_handle tor1 = ses1.add_torrent(p, ec); + // change the priority of a file while checking and make sure it doesn't interrupt the checking. + std::vector prio(ti->num_files(), 0); + prio[2] = 1; + tor1.prioritize_files(prio); + TEST_CHECK(wait_for_alert(ses1, torrent_checked_alert::alert_type, "torrent checked", 1, seconds(50))); + TEST_CHECK(tor1.status(0).is_seeding); + } + remove_all("test_torrent_dir", ec); + if (ec) fprintf(stdout, "ERROR: removing test_torrent_dir: (%d) %s\n", ec.value(), ec.message().c_str()); +} diff --git a/test/test_torrent.cpp b/test/test_torrent.cpp index 85f1873ba..4ac7b2a2b 100644 --- a/test/test_torrent.cpp +++ b/test/test_torrent.cpp @@ -417,6 +417,8 @@ void test_queue(add_torrent_params p) torrents.push_back(ses.add_torrent(p)); } + print_alerts(ses, "ses"); + std::vector pieces = torrents[5].piece_priorities(); std::vector > piece_prios; for (int i = 0; i < int(pieces.size()); ++i) { @@ -425,6 +427,8 @@ void test_queue(add_torrent_params p) torrents[5].prioritize_pieces(piece_prios); torrent_handle finished = torrents[5]; + wait_for_alert(ses, torrent_finished_alert::alert_type, "ses"); + // add_torrent should be ordered TEST_EQUAL(finished.queue_position(), -1); TEST_EQUAL(torrents[0].queue_position(), 0);