From bb705e9a529d74be65a4af9e9590397dc8e024cd Mon Sep 17 00:00:00 2001 From: arvidn Date: Tue, 21 Jul 2015 10:12:37 -0700 Subject: [PATCH] improved seed-mode handling (seed-mode will now automatically be left when performing operations implying it's not a seed). fixed issue with file priorities and override resume data --- ChangeLog | 3 ++ include/libtorrent/torrent.hpp | 5 ++- src/torrent.cpp | 78 ++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index a22f6d2bb..80fe6377c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -74,6 +74,9 @@ 1.0.6 release + * improved seed-mode handling (seed-mode will now automatically be left when + performing operations implying it's not a seed) + * fixed issue with file priorities and override resume data * fix request queue size performance issue * slightly improve UDP tracker performance * fix http scrape diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index bef22b0ac..e5096b65b 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -935,6 +935,7 @@ namespace libtorrent bool is_seed() const { if (!valid_metadata()) return false; + if (m_seed_mode) return true; if (m_have_all) return true; if (m_picker && m_picker->num_passed() == m_picker->num_pieces()) return true; return m_state == torrent_status::seeding; @@ -1067,7 +1068,7 @@ namespace libtorrent int sequence_number() const { return m_sequence_number; } bool seed_mode() const { return m_seed_mode; } - void leave_seed_mode(bool seed); + void leave_seed_mode(bool skip_checking); bool all_verified() const { return int(m_num_verified) == m_torrent_file->num_pieces(); } @@ -1513,7 +1514,7 @@ namespace libtorrent // this is set when we don't want to load seed_mode, // paused or auto_managed from the resume data - bool m_override_resume_data:1; + const bool m_override_resume_data:1; // this is true while there is a country // resolution in progress. To avoid flodding diff --git a/src/torrent.cpp b/src/torrent.cpp index f2e281903..144dbce9c 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -502,7 +502,6 @@ namespace libtorrent set_state(torrent_status::downloading); - m_override_resume_data = true; init(); } #else // if 0 @@ -649,17 +648,16 @@ namespace libtorrent set_state(torrent_status::downloading); - m_override_resume_data = true; init(); } #endif // if 0 - void torrent::leave_seed_mode(bool seed) + void torrent::leave_seed_mode(bool skip_checking) { if (!m_seed_mode) return; - if (!seed) + if (!skip_checking) { // this means the user promised we had all the // files, but it turned out we didn't. This is @@ -673,12 +671,13 @@ namespace libtorrent } #ifndef TORRENT_DISABLE_LOGGING - debug_log("*** LEAVING SEED MODE (%s)", seed ? "as seed" : "as non-seed"); + debug_log("*** LEAVING SEED MODE (%s)" + , skip_checking ? "as seed" : "as non-seed"); #endif m_seed_mode = false; // seed is false if we turned out not // to be a seed after all - if (!seed) + if (!skip_checking) { m_have_all = false; set_state(torrent_status::downloading); @@ -1915,8 +1914,6 @@ namespace libtorrent std::vector const& web_seeds = m_torrent_file->web_seeds(); m_web_seeds.insert(m_web_seeds.end(), web_seeds.begin(), web_seeds.end()); - set_state(torrent_status::checking_resume_data); - #if TORRENT_USE_ASSERTS m_resume_data_loaded = true; #endif @@ -1930,6 +1927,8 @@ namespace libtorrent return; } + set_state(torrent_status::checking_resume_data); + int num_pad_files = 0; TORRENT_ASSERT(block_size() > 0); file_storage const& fs = m_torrent_file->files(); @@ -2435,6 +2434,12 @@ namespace libtorrent update_gauge(); we_have(i); } + else if (m_seed_mode) + { + // being in seed mode and missing a piece is not compatible. + // Leave seed mode if that happens + leave_seed_mode(true); + } if (m_seed_mode && (pieces_str[i] & 2)) m_verified.set_bit(i); } } @@ -2472,6 +2477,10 @@ namespace libtorrent int piece = e.dict_find_int_value("piece", -1); if (piece < 0 || piece > torrent_file().num_pieces()) continue; + // being in seed mode and missing a piece is not compatible. + // Leave seed mode if that happens + if (m_seed_mode) leave_seed_mode(true); + if (has_picker() && m_picker->have_piece(piece)) { m_picker->we_dont_have(piece); @@ -2545,6 +2554,10 @@ namespace libtorrent disconnect_all(errors::stopping_torrent, op_bittorrent); stop_announcing(); + // we're checking everything anyway, no point in assuming we are a seed + // now. + leave_seed_mode(true); + m_ses.disk_thread().async_release_files(m_storage.get() , boost::function()); @@ -3697,12 +3710,12 @@ namespace libtorrent if (m_torrent_file->num_pieces() == 0) return 0; - if (!has_picker()) return m_have_all ? m_torrent_file->total_size() : 0; - // if any piece hash fails, we'll be taken out of seed mode // and m_seed_mode will be false if (m_seed_mode) return m_torrent_file->total_size(); + if (!has_picker()) return m_have_all ? m_torrent_file->total_size() : 0; + const int last_piece = m_torrent_file->num_pieces() - 1; boost::int64_t total_done @@ -5409,6 +5422,7 @@ namespace libtorrent if (!valid_metadata() || is_seed()) return; if (index < 0 || index >= m_torrent_file->num_files()) return; + if (prio < 0) prio = 0; else if (prio > 7) prio = 7; if (int(m_file_priority.size()) <= index) @@ -7165,11 +7179,17 @@ namespace libtorrent // are file priorities set, don't save piece priorities. if (!m_file_priority.empty()) { - // write file priorities - entry::list_type& file_priority = ret["file_priority"].list(); - file_priority.clear(); - for (int i = 0, end(m_file_priority.size()); i < end; ++i) - file_priority.push_back(m_file_priority[i]); + + // when in seed mode (i.e. the client promises that we have all files) + // it does not make sense to save file priorities. + if (!m_seed_mode) + { + // write file priorities + entry::list_type& file_priority = ret["file_priority"].list(); + file_priority.clear(); + for (int i = 0, end(m_file_priority.size()); i < end; ++i) + file_priority.push_back(m_file_priority[i]); + } } else if (has_picker()) { @@ -7569,13 +7589,6 @@ namespace libtorrent get_handle()); } - // this makes the resume data "paused" and - // "auto_managed" fields be ignored. If the paused - // field is not ignored, the invariant check will fail - // since we will be paused but without having disconnected - // any of the peers. - m_override_resume_data = true; - // we have to initialize the torrent before we start // disconnecting redundant peers, otherwise we'll think // we're a seed, because we have all 0 pieces @@ -8222,7 +8235,7 @@ namespace libtorrent } // this is called when we were finished, but some files were - // marked for downloading, and we are no longer finished + // marked for downloading, and we are no longer finished void torrent::resume_download() { // the invariant doesn't hold here, because it expects the torrent @@ -8234,12 +8247,16 @@ namespace libtorrent || m_state == torrent_status::allocating) { #ifndef TORRENT_DISABLE_LOGGING - debug_log("*** RESUME_DOWNLOAD [ skipping, state: %d ]" - , int(m_state)); + debug_log("*** RESUME_DOWNLOAD [ skipping, state: %d ]" + , int(m_state)); #endif return; } + // we're downloading now, which means we're no longer in seed mode + if (m_seed_mode) + leave_seed_mode(false); + TORRENT_ASSERT(!is_finished()); set_state(torrent_status::downloading); set_queue_position((std::numeric_limits::max)()); @@ -8354,8 +8371,11 @@ namespace libtorrent // not switch to downloading mode. If all files are // filtered, we're finished when we start. if (m_state != torrent_status::finished - && m_state != torrent_status::seeding) + && m_state != torrent_status::seeding + && !m_seed_mode) + { set_state(torrent_status::downloading); + } INVARIANT_CHECK; @@ -8656,6 +8676,10 @@ namespace libtorrent TORRENT_ASSERT(m_links[aux::session_interface::torrent_seeding_auto_managed].in_list() == is_seeding); + if (m_seed_mode) + { + TORRENT_ASSERT(is_seed()); + } TORRENT_ASSERT(is_single_thread()); // this fires during disconnecting peers @@ -11353,8 +11377,6 @@ namespace libtorrent TORRENT_ASSERT(s != 0); // this state isn't used anymore #if TORRENT_USE_ASSERTS - if (s == torrent_status::seeding) - TORRENT_ASSERT(is_seed()); if (s == torrent_status::seeding) {