From 4ac08f393affe2d81e4fa498b2e5e511fcee9bd2 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 16 Mar 2007 23:28:26 +0000 Subject: [PATCH] simplified the piece picker by initializing it properly in its constructor. Removed natpmp reporting port map success when removing mappings. fix where incoming connections before the files were completely checked would cause an assert. --- include/libtorrent/piece_picker.hpp | 21 +++++++------------ include/libtorrent/torrent.hpp | 17 +++++++++++++++ src/natpmp.cpp | 14 ++++++++----- src/peer_connection.cpp | 2 +- src/piece_picker.cpp | 23 +++++---------------- src/torrent.cpp | 32 +++++++++++++++++++---------- 6 files changed, 60 insertions(+), 49 deletions(-) diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index ceca530d6..56e52f273 100755 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -112,18 +112,14 @@ namespace libtorrent block_info info[max_blocks_per_piece]; }; - piece_picker(int blocks_per_piece - , int total_num_blocks); - - void set_sequenced_download_threshold(int sequenced_download_threshold); - - // this is called before any other method is called - // after the local files has been checked. // the vector tells which pieces we already have // and which we don't have. - void files_checked( - const std::vector& pieces - , const std::vector& unfinished); + piece_picker(int blocks_per_piece + , int total_num_blocks + , std::vector const& pieces + , std::vector const& unfinished); + + void set_sequenced_download_threshold(int sequenced_download_threshold); // increases the peer count for the given piece // (is used when a HAVE or BITFIELD message is received) @@ -304,8 +300,8 @@ namespace libtorrent } void add(int index); + //TODO: should be renamed update() void move(int vec_index, int elem_index); -// void remove(int vec_index, int elem_index); int add_interesting_blocks(const std::vector& piece_list , const std::vector& pieces @@ -354,9 +350,6 @@ namespace libtorrent // the required popularity of a piece in order to download // it in sequence instead of random order. int m_sequenced_download_threshold; -#ifndef NDEBUG - bool m_files_checked_called; -#endif }; inline int piece_picker::blocks_in_piece(int index) const diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 674c3f251..ddc6b4368 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -416,9 +416,17 @@ namespace libtorrent alert_manager& alerts() const; piece_picker& picker() { + assert(m_files_checked_called); + assert(!is_seed()); assert(m_picker.get()); return *m_picker; } + bool has_picker() const + { + assert((m_files_checked_called && !is_seed()) + == bool(m_picker.get())); + return m_picker.get(); + } policy& get_policy() { assert(m_policy); @@ -611,6 +619,11 @@ namespace libtorrent // m_have_pieces.end(), 0) int m_num_pieces; + // in case the piece picker hasn't been constructed + // when this settings is set, this variable will keep + // its value until the piece picker is created + int m_sequenced_download_threshold; + // is false by default and set to // true when the first tracker reponse // is received @@ -673,6 +686,10 @@ namespace libtorrent // is started. i.e. // total_done - m_initial_done <= total_payload_download size_type m_initial_done; + + // set to true once files_checked has been called + // and the piece picker is constructed + bool m_files_checked_called; #endif #ifdef TORRENT_LOGGING diff --git a/src/natpmp.cpp b/src/natpmp.cpp index 4feaf097f..4b0266157 100644 --- a/src/natpmp.cpp +++ b/src/natpmp.cpp @@ -307,11 +307,15 @@ void natpmp::on_reply(asio::error_code const& e throw std::runtime_error(errmsg.str()); } - int tcp_port = 0; - int udp_port = 0; - if (m.protocol == 1) udp_port = m.external_port; - else tcp_port = public_port; - m_callback(tcp_port, udp_port, ""); + // don't report when we remove mappings + if (m.local_port != 0) + { + int tcp_port = 0; + int udp_port = 0; + if (m.protocol == 1) udp_port = m.external_port; + else tcp_port = public_port; + m_callback(tcp_port, udp_port, ""); + } } catch (std::exception& e) { diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 331d9b8d6..d43d20192 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -687,7 +687,7 @@ namespace libtorrent // just remember the bitmask // don't update the piecepicker // (since it doesn't exist yet) - if (!t->valid_metadata()) + if (!t->ready_for_connections()) { m_have_piece = bitfield; m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true); diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 24f5fdecb..9efa2c861 100755 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -52,7 +52,9 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks) + piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks + , std::vector const& pieces + , std::vector const& unfinished) : m_piece_info(2) , m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece) , m_num_filtered(0) @@ -61,9 +63,6 @@ namespace libtorrent { assert(blocks_per_piece > 0); assert(total_num_blocks >= 0); -#ifndef NDEBUG - m_files_checked_called = false; -#endif // the piece index is stored in 20 bits, which limits the allowed // number of pieces somewhat @@ -82,16 +81,8 @@ namespace libtorrent // and make them invalid (as if though we already had every piece) std::fill(m_piece_map.begin(), m_piece_map.end() , piece_pos(0, piece_pos::we_have_index)); - } - // pieces is a bitmask with the pieces we have - void piece_picker::files_checked( - const std::vector& pieces - , const std::vector& unfinished) - { -#ifndef NDEBUG - m_files_checked_called = true; -#endif + for (std::vector::const_iterator i = pieces.begin(); i != pieces.end(); ++i) { @@ -126,6 +117,7 @@ namespace libtorrent } } } + } void piece_picker::set_sequenced_download_threshold( @@ -376,7 +368,6 @@ namespace libtorrent { assert(priority > 0); assert(elem_index >= 0); - assert(m_files_checked_called); assert(int(m_piece_info.size()) > priority); assert(int(m_piece_info[priority].size()) > elem_index); @@ -532,7 +523,6 @@ namespace libtorrent assert(index >= 0); assert(index < (int)m_piece_map.size()); - assert(m_files_checked_called); assert(m_piece_map[index].downloading == 1); @@ -554,7 +544,6 @@ namespace libtorrent // TORRENT_PIECE_PICKER_INVARIANT_CHECK; assert(i >= 0); assert(i < (int)m_piece_map.size()); - assert(m_files_checked_called); piece_pos& p = m_piece_map[i]; int index = p.index; @@ -587,7 +576,6 @@ namespace libtorrent { // TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(m_files_checked_called); assert(i >= 0); assert(i < (int)m_piece_map.size()); @@ -754,7 +742,6 @@ namespace libtorrent TORRENT_PIECE_PICKER_INVARIANT_CHECK; assert(num_blocks > 0); assert(pieces.size() == m_piece_map.size()); - assert(m_files_checked_called); // free refers to pieces that are free to download, no one else // is downloading them. diff --git a/src/torrent.cpp b/src/torrent.cpp index 130634f09..da9f863e6 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -256,6 +256,7 @@ namespace libtorrent , m_time_scaler(0) , m_priority(.5) , m_num_pieces(0) + , m_sequenced_download_threshold(0) , m_got_tracker_response(false) , m_ratio(0.f) , m_total_failed_bytes(0) @@ -270,6 +271,7 @@ namespace libtorrent { #ifndef NDEBUG m_initial_done = 0; + m_files_checked_called = false; #endif #ifdef TORRENT_LOGGING m_log = ses.create_log("torrent_" @@ -346,6 +348,7 @@ namespace libtorrent , m_time_scaler(0) , m_priority(.5) , m_num_pieces(0) + , m_sequenced_download_threshold(0) , m_got_tracker_response(false) , m_ratio(0.f) , m_total_failed_bytes(0) @@ -360,6 +363,7 @@ namespace libtorrent { #ifndef NDEBUG m_initial_done = 0; + m_files_checked_called = false; #endif #ifdef TORRENT_LOGGING @@ -459,9 +463,6 @@ namespace libtorrent m_storage.reset(new piece_manager(m_torrent_file, m_save_path , m_ses.m_files, m_storage_constructor)); m_block_size = calculate_block_size(m_torrent_file, m_default_block_size); - m_picker.reset(new piece_picker( - static_cast(m_torrent_file.piece_length() / m_block_size) - , static_cast((m_torrent_file.total_size()+m_block_size-1)/m_block_size))); std::vector const& url_seeds = m_torrent_file.url_seeds(); std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds @@ -701,10 +702,9 @@ namespace libtorrent { INVARIANT_CHECK; - if (!valid_metadata()) return tuple(0,0); - - if (m_torrent_file.num_pieces() == 0) + if (!has_picker() || m_torrent_file.num_pieces() == 0) return tuple(0,0); + const int last_piece = m_torrent_file.num_pieces() - 1; if (is_seed()) @@ -2132,11 +2132,17 @@ namespace libtorrent if (!is_seed()) { - m_picker->files_checked(m_have_pieces, unfinished_pieces); + m_picker.reset(new piece_picker( + static_cast(m_torrent_file.piece_length() / m_block_size) + , static_cast((m_torrent_file.total_size()+m_block_size-1)/m_block_size) + , m_have_pieces, unfinished_pieces)); + m_files_checked_called = true; + if (m_sequenced_download_threshold > 0) + picker().set_sequenced_download_threshold(m_sequenced_download_threshold); } else { - m_picker.reset(); + assert(!m_picker); } if (!m_connections_initialized) { @@ -2267,10 +2273,14 @@ namespace libtorrent void torrent::set_sequenced_download_threshold(int threshold) { - // TODO: if there is not valid metadata, save this setting and - // set it once the piece picker is created. - if (valid_metadata() && !is_seed()) + if (has_picker()) + { picker().set_sequenced_download_threshold(threshold); + } + else + { + m_sequenced_download_threshold = threshold; + } }