From b06922dcd48cbf59d2917b4866d8327fe8f79c01 Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Sun, 15 Jul 2007 19:06:12 +0000 Subject: [PATCH] libtorrent sync 1401 --- .../include/libtorrent/bandwidth_manager.hpp | 5 +- .../include/libtorrent/connection_queue.hpp | 3 + .../include/libtorrent/piece_picker.hpp | 7 +- libtorrent/src/connection_queue.cpp | 16 +++ libtorrent/src/piece_picker.cpp | 101 +++++++++++++----- libtorrent/src/torrent.cpp | 2 - 6 files changed, 98 insertions(+), 36 deletions(-) diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index 30f99d0cf..4df9d4f2f 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -391,10 +391,6 @@ private: break; } - // don't hand out chunks larger than the throttle - // per second on the torrent - assert(qe.max_block_size <= t->bandwidth_throttle(m_channel)); - // so, hand out max_assignable, but no more than // the available bandwidth (amount) and no more // than the max_bandwidth_block_size @@ -402,6 +398,7 @@ private: , amount); assert(hand_out_amount > 0); amount -= hand_out_amount; + assert(hand_out_amount <= qe.max_block_size); t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size); qe.peer->assign_bandwidth(m_channel, hand_out_amount); add_history_entry(history_entry( diff --git a/libtorrent/include/libtorrent/connection_queue.hpp b/libtorrent/include/libtorrent/connection_queue.hpp index 05a8a61fe..17be248bf 100644 --- a/libtorrent/include/libtorrent/connection_queue.hpp +++ b/libtorrent/include/libtorrent/connection_queue.hpp @@ -88,6 +88,9 @@ private: int m_half_open_limit; deadline_timer m_timer; +#ifndef NDEBUG + bool m_in_timeout_function; +#endif }; } diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp index 49ecf7143..136e71c63 100755 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ b/libtorrent/include/libtorrent/piece_picker.hpp @@ -279,7 +279,8 @@ namespace libtorrent assert(index_ >= 0); } - // selects which vector to look in + // the number of peers that has this piece + // (availability) unsigned peer_count : 10; // is 1 if the piece is marked as being downloaded unsigned downloading : 1; @@ -350,13 +351,15 @@ namespace libtorrent void add(int index); void move(int vec_index, int elem_index); + void sort_piece(std::vector::iterator dp); int add_interesting_blocks(const std::vector& piece_list , const std::vector& pieces , std::vector& interesting_blocks , std::vector& backup_blocks , int num_blocks, bool prefer_whole_pieces - , void* peer, piece_state_t speed) const; + , void* peer, piece_state_t speed + , bool ignore_downloading_pieces) const; downloading_piece& add_download_piece(); void erase_download_piece(std::vector::iterator i); diff --git a/libtorrent/src/connection_queue.cpp b/libtorrent/src/connection_queue.cpp index f83baa196..473a92920 100644 --- a/libtorrent/src/connection_queue.cpp +++ b/libtorrent/src/connection_queue.cpp @@ -42,6 +42,9 @@ namespace libtorrent , m_num_connecting(0) , m_half_open_limit(0) , m_timer(ios) +#ifndef NDEBUG + , m_in_timeout_function(false) +#endif {} bool connection_queue::free_slots() const @@ -133,9 +136,22 @@ namespace libtorrent } } +#ifndef NDEBUG + struct function_guard + { + function_guard(bool& v): val(v) { assert(!val); val = true; } + ~function_guard() { val = false; } + + bool& val; + }; +#endif + void connection_queue::on_timeout(asio::error_code const& e) { INVARIANT_CHECK; +#ifndef NDEBUG + function_guard guard_(m_in_timeout_function); +#endif assert(!e || e == asio::error::operation_aborted); if (e) return; diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 3f9adcc75..61f3544b7 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -196,12 +196,13 @@ namespace libtorrent int block_index = num_downloads * m_blocks_per_piece; if (int(m_block_info.size()) < block_index + m_blocks_per_piece) { + block_info* base = &m_block_info[0]; m_block_info.resize(block_index + m_blocks_per_piece); - if (!m_downloads.empty() && &m_block_info[0] != m_downloads.front().info) + if (!m_downloads.empty() && &m_block_info[0] != base) { // this means the memory was reallocated, update the pointers for (int i = 0; i < int(m_downloads.size()); ++i) - m_downloads[i].info = &m_block_info[i * m_blocks_per_piece]; + m_downloads[i].info = &m_block_info[m_downloads[i].info - base]; } } m_downloads.push_back(downloading_piece()); @@ -218,21 +219,18 @@ namespace libtorrent void piece_picker::erase_download_piece(std::vector::iterator i) { - if (i != m_downloads.end() - 1) + std::vector::iterator other = std::find_if( + m_downloads.begin(), m_downloads.end() + , bind(&downloading_piece::info, _1) + == &m_block_info[(m_downloads.size() - 1) * m_blocks_per_piece]); + assert(other != m_downloads.end()); + + if (i != other) { - int remove_index = i - m_downloads.begin(); - int last_index = m_downloads.size() - 1; - assert(remove_index < last_index); - - assert(int(m_block_info.size()) >= last_index * m_blocks_per_piece + m_blocks_per_piece); - std::copy(m_block_info.begin() + (last_index * m_blocks_per_piece) - , m_block_info.begin() + (last_index * m_blocks_per_piece + m_blocks_per_piece) - , m_block_info.begin() + (remove_index * m_blocks_per_piece)); - m_downloads[remove_index] = m_downloads[last_index]; - m_downloads[remove_index].info = &m_block_info[remove_index * m_blocks_per_piece]; + std::copy(other->info, other->info + m_blocks_per_piece, i->info); + other->info = i->info; } - - m_downloads.pop_back(); + m_downloads.erase(i); } #ifndef NDEBUG @@ -242,6 +240,17 @@ namespace libtorrent assert(m_piece_info.empty() || m_piece_info[0].empty()); + if (!m_downloads.empty()) + { + for (std::vector::const_iterator i = m_downloads.begin(); + i != m_downloads.end() - 1; ++i) + { + downloading_piece const& dp = *i; + downloading_piece const& next = *(i + 1); + assert(dp.finished + dp.writing >= next.finished + next.writing); + } + } + if (t != 0) assert((int)m_piece_map.size() == t->torrent_file().num_pieces()); @@ -593,6 +602,20 @@ namespace libtorrent } } + void piece_picker::sort_piece(std::vector::iterator dp) + { + assert(m_piece_map[dp->index].downloading); + int complete = dp->writing + dp->finished; + for (std::vector::iterator i = dp, j(dp-1); + i != m_downloads.begin(); --i, --j) + { + assert(j >= m_downloads.begin()); + if (j->finished + j->writing >= complete) return; + using std::swap; + swap(*j, *i); + } + } + void piece_picker::restore_piece(int index) { TORRENT_PIECE_PICKER_INVARIANT_CHECK; @@ -1027,6 +1050,22 @@ namespace libtorrent // blocks belonging to a piece that others have // downloaded to std::vector backup_blocks; + + bool ignore_downloading_pieces = false; + if (!prefer_whole_pieces) + { + std::vector downloading_pieces; + downloading_pieces.reserve(m_downloads.size()); + for (std::vector::const_iterator i = m_downloads.begin() + , end(m_downloads.end()); i != end; ++i) + { + downloading_pieces.push_back(i->index); + } + num_blocks = add_interesting_blocks(downloading_pieces, pieces + , interesting_blocks, backup_blocks, num_blocks + , prefer_whole_pieces, peer, speed, ignore_downloading_pieces); + ignore_downloading_pieces = true; + } // this loop will loop from pieces with priority 1 and up // until we either reach the end of the piece list or @@ -1049,7 +1088,7 @@ namespace libtorrent if (bucket->empty()) continue; num_blocks = add_interesting_blocks(*bucket, pieces , interesting_blocks, backup_blocks, num_blocks - , prefer_whole_pieces, peer, speed); + , prefer_whole_pieces, peer, speed, ignore_downloading_pieces); assert(num_blocks >= 0); if (num_blocks == 0) return; if (rarest_first) continue; @@ -1135,7 +1174,8 @@ namespace libtorrent , std::vector& interesting_blocks , std::vector& backup_blocks , int num_blocks, bool prefer_whole_pieces - , void* peer, piece_state_t speed) const + , void* peer, piece_state_t speed + , bool ignore_downloading_pieces) const { // if we have less than 1% of the pieces, ignore speed priorities and just try // to finish any downloading piece @@ -1154,6 +1194,7 @@ namespace libtorrent if (m_piece_map[*i].downloading == 1) { + if (ignore_downloading_pieces) continue; std::vector::const_iterator p = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(*i)); assert(p != m_downloads.end()); @@ -1422,7 +1463,7 @@ namespace libtorrent assert(info.state == block_info::state_requested); if (info.state == block_info::state_requested) --i->requested; assert(i->requested >= 0); - assert (info.state != block_info::state_writing); + assert(info.state != block_info::state_writing); ++i->writing; info.state = block_info::state_writing; if (info.num_peers > 0) --info.num_peers; @@ -1434,6 +1475,7 @@ namespace libtorrent // remove the fast/slow state from it i->state = none; } + sort_piece(i); } void piece_picker::mark_as_finished(piece_block block, void* peer) @@ -1461,9 +1503,11 @@ namespace libtorrent block_info& info = dp.info[block.block_index]; info.peer = peer; assert(info.state == block_info::state_none); -// if (info.state == block_info::state_writing) --dp.writing; -// assert(dp.writing >= 0); - if (info.state != block_info::state_finished) ++dp.finished; + if (info.state != block_info::state_finished) + { + ++dp.finished; + sort_piece(m_downloads.end() - 1); + } info.state = block_info::state_finished; } else @@ -1477,16 +1521,17 @@ namespace libtorrent info.peer = peer; assert(info.state == block_info::state_writing || peer == 0); - if (info.state == block_info::state_writing) --i->writing; assert(i->writing >= 0); ++i->finished; - info.state = block_info::state_finished; - - if (i->requested == 0) + if (info.state == block_info::state_writing) { - // there are no blocks requested in this piece. - // remove the fast/slow state from it - i->state = none; + --i->writing; + info.state = block_info::state_finished; + } + else + { + info.state = block_info::state_finished; + sort_piece(i); } } } diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index db51d90f1..fb2e29ce5 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2010,8 +2010,6 @@ namespace libtorrent , int block_size , bool non_prioritized) { - assert(m_bandwidth_limit[channel].max_assignable() >= block_size); - m_ses.m_bandwidth_manager[channel]->request_bandwidth(p , block_size, non_prioritized); m_bandwidth_limit[channel].assign(block_size);