diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index 1e9c0115e..62126f6d5 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -307,7 +307,7 @@ namespace libtorrent // clears the given piece's download flag // this means that this piece-block can be picked again - void abort_download(piece_block block); + void abort_download(piece_block block, void* peer); bool is_piece_finished(int index) const; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index bdaf06634..9857ee124 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1204,7 +1204,7 @@ namespace libtorrent for (std::vector::const_iterator i = m_request_queue.begin() , end(m_request_queue.end()); i != end; ++i) { - p.abort_download(i->block); + p.abort_download(i->block, peer_info_struct()); } } m_request_queue.clear(); @@ -1272,7 +1272,7 @@ namespace libtorrent else if (!t->is_seed() && remove_from_picker) { piece_picker& p = t->picker(); - p.abort_download(b.block); + p.abort_download(b.block, peer_info_struct()); } #if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_DEBUG check_invariant(); @@ -2294,7 +2294,7 @@ namespace libtorrent "dqs: " << int(m_desired_queue_size) << "] ***\n"; #endif if (!qe.timed_out && !qe.not_wanted) - picker.abort_download(qe.block); + picker.abort_download(qe.block, peer_info_struct()); TORRENT_ASSERT(m_outstanding_bytes >= t->to_req(qe.block).length); m_outstanding_bytes -= t->to_req(qe.block).length; @@ -2812,7 +2812,7 @@ namespace libtorrent while (!m_request_queue.empty()) { - t->picker().abort_download(m_request_queue.back().block); + t->picker().abort_download(m_request_queue.back().block, peer_info_struct()); m_request_queue.pop_back(); } m_queued_time_critical = 0; @@ -2882,7 +2882,7 @@ namespace libtorrent // the block, just ignore to cancel it. if (rit == m_request_queue.end()) return; - t->picker().abort_download(block); + t->picker().abort_download(block, peer_info_struct()); m_request_queue.erase(rit); // since we found it in the request queue, it means it hasn't been // sent yet, so we don't have to send a cancel. @@ -3073,7 +3073,7 @@ namespace libtorrent if (t->picker().is_finished(block.block) || t->picker().is_downloaded(block.block)) { - t->picker().abort_download(block.block); + t->picker().abort_download(block.block, peer_info_struct()); continue; } @@ -3269,14 +3269,15 @@ namespace libtorrent while (!m_download_queue.empty()) { pending_block& qe = m_download_queue.back(); - if (!qe.timed_out && !qe.not_wanted) picker.abort_download(qe.block); + if (!qe.timed_out && !qe.not_wanted) + picker.abort_download(qe.block, peer_info_struct()); m_outstanding_bytes -= t->to_req(qe.block).length; if (m_outstanding_bytes < 0) m_outstanding_bytes = 0; m_download_queue.pop_back(); } while (!m_request_queue.empty()) { - picker.abort_download(m_request_queue.back().block); + picker.abort_download(m_request_queue.back().block, peer_info_struct()); m_request_queue.pop_back(); } } @@ -4011,7 +4012,7 @@ namespace libtorrent m_timeout_extend += m_ses.settings().request_timeout; if (r != piece_block::invalid) - picker.abort_download(r); + picker.abort_download(r, peer_info_struct()); send_block_requests(); } @@ -5100,6 +5101,8 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); if (m_disconnecting) { + TORRENT_ASSERT(m_download_queue.empty()); + TORRENT_ASSERT(m_request_queue.empty()); TORRENT_ASSERT(!t); TORRENT_ASSERT(m_disconnect_started); } diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 63b210ff5..32bbc695d 100644 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -2305,7 +2305,7 @@ namespace libtorrent // this is called when a request is rejected or when // a peer disconnects. The piece might be in any state - void piece_picker::abort_download(piece_block block) + void piece_picker::abort_download(piece_block block, void* peer) { #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS TORRENT_PIECE_PICKER_INVARIANT_CHECK; @@ -2340,6 +2340,7 @@ namespace libtorrent { TORRENT_ASSERT(info.num_peers > 0); if (info.num_peers > 0) --info.num_peers; + if (info.peer == peer) info.peer = 0; TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index)); diff --git a/src/torrent.cpp b/src/torrent.cpp index 00d5f65c9..52c80e2e8 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2482,7 +2482,13 @@ namespace libtorrent // this piece failed the check as it can restore it // and mark it as being interesting for download m_picker->restore_piece(index); + + // we might still have outstanding requests to this + // piece that hasn't been received yet. If this is the + // case, we need to re-open the piece and mark any + // blocks we're still waiting for as requested restore_piece_state(index); + TORRENT_ASSERT(m_storage); TORRENT_ASSERT(m_picker->have_piece(index) == false); @@ -2512,6 +2518,7 @@ namespace libtorrent for (std::vector::const_iterator k = dq.begin() , end(dq.end()); k != end; ++k) { + if (k->timed_out || k->not_wanted) continue; if (k->block.piece_index != index) continue; m_picker->mark_as_downloading(k->block, p->peer_info_struct() , (piece_picker::piece_state_t)p->peer_speed());