diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index dcff791f9..583721763 100755 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -106,7 +106,9 @@ namespace libtorrent // 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); + void files_checked( + const std::vector& pieces + , const std::vector& unfinished); // increases the peer count for the given piece // (is used when a HAVE or BITFIELD message is received) @@ -172,6 +174,15 @@ namespace libtorrent void integrity_check(const torrent* t = 0) const; #endif + // functor that compares indices on downloading_pieces + struct has_index + { + has_index(int i): index(i) {} + bool operator()(const downloading_piece& p) const + { return p.index == index; } + int index; + }; + private: struct piece_pos @@ -199,15 +210,6 @@ namespace libtorrent }; - - struct has_index - { - has_index(int i): index(i) {} - bool operator()(const downloading_piece& p) const - { return p.index == index; } - int index; - }; - void move(bool downloading, int vec_index, int elem_index); void remove(bool downloading, int vec_index, int elem_index); diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 171f208ee..9285d5931 100755 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -72,7 +72,9 @@ namespace libtorrent std::fill(m_piece_map.begin(), m_piece_map.end(), piece_pos(0, 0xffffff)); } - void piece_picker::files_checked(const std::vector& pieces) + void piece_picker::files_checked( + const std::vector& pieces + , const std::vector& unfinished) { // build a vector of all the pieces we don't have std::vector piece_list; @@ -108,6 +110,25 @@ namespace libtorrent m_piece_map[index].index = m_piece_info[peer_count].size(); m_piece_info[peer_count].push_back(index); } + + // if we have fast resume info + // use it + if (!unfinished.empty()) + { + for (std::vector::const_iterator i + = unfinished.begin(); + i != unfinished.end(); + ++i) + { + peer_id peer; + std::fill(peer.begin(), peer.end(), 0); + for (int j = 0; j < m_blocks_per_piece; ++j) + { + if (i->finished_blocks[j]) + mark_as_finished(piece_block(i->index, j), peer); + } + } + } #ifndef NDEBUG // integrity_check(); #endif diff --git a/src/session.cpp b/src/session.cpp index 6f792202b..72a4f8c90 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -916,7 +916,7 @@ namespace libtorrent int num_unfinished = read_int(ptr); if (num_unfinished < 0) return; - if (data.size() != (3 + num_slots + 1 + num_unfinished) * 4) + if (data.size() != (1 + num_slots + 2 + num_unfinished * (num_blocks_per_piece / 32 + 1)) * 4) return; tmp_unfinished.reserve(num_unfinished); @@ -934,7 +934,12 @@ namespace libtorrent for (int j = 0; j < num_blocks_per_piece / 32; ++j) { unsigned int bits = read_int(ptr); - for (int k = 0; k < 32; ++k) p.finished_blocks[j * 32 + k] = true; + for (int k = 0; k < 32; ++k) + { + const int bit = j * 32 + k; + if (bits & (1 << bit)) + p.finished_blocks[bit] = true; + } } tmp_unfinished.push_back(p); } diff --git a/src/storage.cpp b/src/storage.cpp index 280f01530..f6c415808 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -513,6 +513,50 @@ namespace libtorrent { const std::size_t last_piece_size = m_info.piece_size( m_info.num_pieces() - 1); + // if we have fast-resume info + // use it instead of doingthe actual checking + if (!data.piece_map.empty() + && data.piece_map.size() <= m_slot_to_piece.size()) + { + for (int i = 0; i < data.piece_map.size(); ++i) + { + m_slot_to_piece[i] = data.piece_map[i]; + if (data.piece_map[i] >= 0) + { + m_piece_to_slot[data.piece_map[i]] = i; + int found_piece = data.piece_map[i]; + + // if the piece is not in the unfinished list + // we have all of it + if (std::find_if( + data.unfinished_pieces.begin() + , data.unfinished_pieces.end() + , piece_picker::has_index(found_piece)) + == data.unfinished_pieces.end()) + { + m_bytes_left -= m_info.piece_size(found_piece); + pieces[found_piece] = true; + } + } + else if (data.piece_map[i] == -2) + { + m_free_slots.push_back(i); + } + else + { + assert(data.piece_map[i] == -1); + m_unallocated_slots.push_back(i); + } + } + + for (int i = data.piece_map.size(); i < pieces.size(); ++i) + { + m_unallocated_slots.push_back(i); + } + + return; + } + bool changed_file = true; fs::ifstream in; @@ -658,6 +702,9 @@ namespace libtorrent { if (found_piece != -1) { + // if we have found this piece hash once already + // move it to the free pieces and don't decrease + // bytes_left if (pieces[found_piece]) { assert(m_piece_to_slot[found_piece] != -1); diff --git a/src/torrent.cpp b/src/torrent.cpp index 902d7c28b..81eb28fbd 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -571,7 +571,7 @@ namespace libtorrent , m_have_pieces.end() , 0); - m_picker.files_checked(m_have_pieces); + m_picker.files_checked(m_have_pieces, data.unfinished_pieces); #ifndef NDEBUG m_picker.integrity_check(this); #endif diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index cc9d0631e..4ca3f8daf 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -185,6 +185,7 @@ namespace libtorrent std::back_insert_iterator > out(buf); // TODO: write file header + // TODO: write modification-dates for all files // TODO: write info hash // number of slots