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; + } }