diff --git a/ChangeLog b/ChangeLog index d29dc7d16..b0fbb610c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -61,6 +61,7 @@ incoming connection * added more detailed instrumentation of the disk I/O thread + * fixed edge case of pad file support * limit number of torrents tracked by DHT * fixed bug when allow_multiple_connections_per_ip was enabled * potential WOW64 fix for unbuffered I/O (windows) diff --git a/src/storage.cpp b/src/storage.cpp index 321e031d1..208547b47 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1196,6 +1196,7 @@ ret: } advance_bufs(current_buf, file_bytes_left); TORRENT_ASSERT(count_bufs(current_buf, bytes_left - file_bytes_left) <= num_bufs); + file_offset = 0; continue; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 4c57fc267..e555374e3 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -973,7 +973,7 @@ namespace libtorrent for (file_storage::iterator i = m_torrent_file->files().begin() , end(m_torrent_file->files().end()); i != end; ++i, ++file) { - if (!i->pad_file) continue; + if (!i->pad_file || i->size == 0) continue; m_padding += i->size; peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size); @@ -983,12 +983,45 @@ namespace libtorrent int block = block_size(); int blocks_per_piece = m_torrent_file->piece_length() / block; - piece_block pb(pr.piece, pr.start / block_size()); + piece_block pb(pr.piece, pr.start / block); for (; pr.length >= block; pr.length -= block, ++pb.block_index) { if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; } m_picker->mark_as_finished(pb, 0); } + // ugly edge case where padfiles are not used they way they're + // supposed to be. i.e. added back-to back or at the end + if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; } + if (pr.length > 0 && (boost::next(i) != end && boost::next(i)->pad_file) + || boost::next(i) == end) + { + m_picker->mark_as_finished(pb, 0); + } + } + + if (m_padding > 0) + { + // if we marked an entire piece as finished, we actually + // need to consider it finished + + std::vector const& dq + = m_picker->get_download_queue(); + + std::vector have_pieces; + + for (std::vector::const_iterator i + = dq.begin(); i != dq.end(); ++i) + { + int num_blocks = m_picker->blocks_in_piece(i->index); + if (i->finished < num_blocks) continue; + have_pieces.push_back(i->index); + } + + for (std::vector::iterator i = have_pieces.begin(); + i != have_pieces.end(); ++i) + { + we_have(*i); + } } m_storage->async_check_fastresume(&m_resume_entry