From 1c954451ffa04b512d5417a0161a2d88a2d76b2d Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 13 Mar 2014 08:00:53 +0000 Subject: [PATCH] seed mode fixes --- include/libtorrent/torrent.hpp | 26 ++++++------------- src/peer_connection.cpp | 19 ++------------ src/torrent.cpp | 47 ++++++++++++++++++++++++++++++++-- test/test_remap_files.cpp | 16 +++++++----- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 1d93c771c..2a61c9b79 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -535,6 +535,11 @@ namespace libtorrent int num_have() const { + // pretend we have every piece when in seed mode + if (m_seed_mode) { + return m_torrent_file->num_pieces(); + } + return has_picker() ? m_picker->num_have() : m_torrent_file->num_pieces(); @@ -823,16 +828,8 @@ namespace libtorrent int sequence_number() const { return m_sequence_number; } bool seed_mode() const { return m_seed_mode; } - void leave_seed_mode(bool seed) - { - if (!m_seed_mode) return; - m_seed_mode = false; - // seed is false if we turned out not - // to be a seed after all - if (!seed) force_recheck(); - m_num_verified = 0; - m_verified.clear(); - } + void leave_seed_mode(bool seed); + bool all_verified() const { return int(m_num_verified) == m_torrent_file->num_pieces(); } bool verified_piece(int piece) const @@ -841,14 +838,7 @@ namespace libtorrent TORRENT_ASSERT(piece >= 0); return m_verified.get_bit(piece); } - void verified(int piece) - { - TORRENT_ASSERT(piece < int(m_verified.size())); - TORRENT_ASSERT(piece >= 0); - TORRENT_ASSERT(m_verified.get_bit(piece) == false); - ++m_num_verified; - m_verified.set_bit(piece); - } + void verified(int piece); bool add_merkle_nodes(std::map const& n, int piece); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 1ef74c1fb..4c0eda8a4 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -2119,7 +2119,7 @@ namespace libtorrent , t->have_piece(r.piece) , t->block_size()); - peer_log("==> REJECT_PIECE [ piece: %d s: %d l: %d ]" + peer_log("==> REJECT_PIECE [ piece: %d | s: %d | l: %d ] invalid request" , r.piece , r.start , r.length); #endif @@ -2168,21 +2168,6 @@ namespace libtorrent boost::shared_ptr t = associated_torrent().lock(); TORRENT_ASSERT(t); - // piece_block can't necessarily hold large piece numbers - // so check that first - if (r.piece < 0 - || r.piece >= t->torrent_file().num_pieces() - || r.start < 0 - || r.start > t->torrent_file().piece_length()) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - peer_log("*** INVALID_PIECE [ piece: %d s: %d l: %d ]" - , r.piece, r.start, r.length); -#endif - disconnect(errors::invalid_piece, 2); - return; - } - piece_block b(r.piece, r.start / t->block_size()); m_receiving_block = b; @@ -3163,7 +3148,7 @@ namespace libtorrent ++m_ses.m_choked_piece_requests; #endif #ifdef TORRENT_VERBOSE_LOGGING - peer_log("==> REJECT_PIECE [ piece: %d s: %d l: %d ]" + peer_log("==> REJECT_PIECE [ piece: %d s: %d l: %d ] choking" , r.piece , r.start , r.length); #endif write_reject_request(r); diff --git a/src/torrent.cpp b/src/torrent.cpp index acb0f825f..6d1b1b524 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -565,7 +565,7 @@ namespace libtorrent m_override_resume_data = true; init(); } -#else +#else // if 0 void torrent::on_torrent_download(error_code const& ec , http_parser const& parser, char const* data, int size) @@ -679,7 +679,48 @@ namespace libtorrent init(); } +#endif // if 0 + + void torrent::leave_seed_mode(bool seed) + { + if (!m_seed_mode) return; + + if (!seed) + { + // this means the user promised we had all the + // files, but it turned out we didn't. This is + // an error. + + // TODO: 2 post alert + +#if defined TORRENT_ERROR_LOGGING + debug_log("*** FAILED SEED MODE, rechecking"); #endif + } + +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING + debug_log("*** LEAVING SEED MODE (%s)", seed ? "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) + { + set_state(torrent_status::downloading); + force_recheck(); + } + m_num_verified = 0; + m_verified.clear(); + } + + void torrent::verified(int piece) + { + TORRENT_ASSERT(piece < int(m_verified.size())); + TORRENT_ASSERT(piece >= 0); + TORRENT_ASSERT(m_verified.get_bit(piece) == false); + ++m_num_verified; + m_verified.set_bit(piece); + } void torrent::start() { @@ -2854,7 +2895,9 @@ namespace libtorrent const int last_piece = m_torrent_file->num_pieces() - 1; const int piece_size = m_torrent_file->piece_length(); - if (is_seed()) + // if any piece hash fails, we'll be taken out of seed mode + // and m_seed_mode will be false + if (m_seed_mode || is_seed()) { st.total_done = m_torrent_file->total_size() - m_padding; st.total_wanted_done = st.total_done; diff --git a/test/test_remap_files.cpp b/test/test_remap_files.cpp index 867ef62b2..b50a4dc01 100644 --- a/test/test_remap_files.cpp +++ b/test/test_remap_files.cpp @@ -391,7 +391,7 @@ void test_remap_files_prio(storage_mode_t storage_mode = storage_mode_sparse) add_torrent_params params; params.storage_mode = storage_mode; - params.flags &= ~add_torrent_params::flag_paused; + params.flags |= add_torrent_params::flag_paused; params.flags &= ~add_torrent_params::flag_auto_managed; wait_for_listen(ses1, "ses1"); @@ -399,15 +399,18 @@ void test_remap_files_prio(storage_mode_t storage_mode = storage_mode_sparse) peer_disconnects = 0; - std::vector file_prio(2, 1); - file_prio[0] = 0; - params.file_priorities = file_prio; - // test using piece sizes smaller than 16kB boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0 , true, false, true, "_remap3", 8 * 1024, &t, false, ¶ms , true, false, &t2); + std::vector file_prio(3, 1); + file_prio[0] = 0; + tor2.prioritize_files(file_prio); + + tor1.resume(); + tor2.resume(); + fprintf(stderr, "\ntesting remap scatter prio\n\n"); for (int i = 0; i < 50; ++i) @@ -443,8 +446,7 @@ void test_remap_files_prio(storage_mode_t storage_mode = storage_mode_sparse) std::cerr << "st2 state: " << state_str[st2.state] << std::endl; } - TEST_CHECK(st1.state == torrent_status::seeding - || st1.state == torrent_status::checking_files); + TEST_CHECK(st1.state == torrent_status::seeding); TEST_CHECK(st2.state == torrent_status::downloading || st2.state == torrent_status::checking_resume_data);