diff --git a/ChangeLog b/ChangeLog index ed0e9227b..e15fe19d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 1.2.2 release + * fix updating of is_finished torrent status, when changing piece priorities * fix regression in &left= reporting when adding a seeding torrent * fix integer overflow in http parser * improve sanitation of symlinks, to support more complex link targets diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index 5bbf8634f..6574b49f5 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -434,8 +434,24 @@ namespace libtorrent { // been flushed to disk yet) int num_passed() const { return m_num_passed; } - // return true if we have all the pieces we wanted - bool is_finished() const { return m_num_have - m_num_have_filtered == num_pieces() - m_num_filtered; } + // return true if all the pieces we want have passed the hash check (but + // may not have been written to disk yet) + bool is_finished() const + { + // this expression warrants some explanation: + // if the number of pieces we *want* to download + // is less than or (more likely) equal to the number of pieces that + // have passed the hash check (discounting the pieces that have passed + // the check but then had their priority set to 0). Then we're + // finished. Note that any piece we *have* implies it's both passed the + // hash check *and* been written to disk. + // num_pieces() - m_num_filtered - m_num_have_filtered + // <= (num_passed() - m_num_have_filtered) + // this can be simplified. Note how m_num_have_filtered appears on both + // side of the equation. + // + return num_pieces() - m_num_filtered <= num_passed(); + } bool is_seeding() const { return m_num_have == num_pieces(); } diff --git a/simulation/setup_swarm.cpp b/simulation/setup_swarm.cpp index 50b9643e7..bb84c46a1 100644 --- a/simulation/setup_swarm.cpp +++ b/simulation/setup_swarm.cpp @@ -146,6 +146,15 @@ bool is_seed(lt::session& ses) return h.status().is_seeding; } +bool is_finished(lt::session& ses) +{ + auto handles = ses.get_torrents(); + TEST_EQUAL(handles.size(), 1); + if (handles.empty()) return false; + auto h = handles[0]; + return h.status().is_finished; +} + int completed_pieces(lt::session& ses) { auto handles = ses.get_torrents(); diff --git a/simulation/setup_swarm.hpp b/simulation/setup_swarm.hpp index 6c83b7b9e..876d6ae07 100644 --- a/simulation/setup_swarm.hpp +++ b/simulation/setup_swarm.hpp @@ -78,6 +78,7 @@ void setup_swarm(int num_nodes bool has_metadata(lt::session& ses); bool is_seed(lt::session& ses); +bool is_finished(lt::session& ses); int completed_pieces(lt::session& ses); void add_extra_peers(lt::session& ses); lt::torrent_status get_status(lt::session& ses); diff --git a/simulation/test_transfer.cpp b/simulation/test_transfer.cpp index a0110c13f..13cfb8f97 100644 --- a/simulation/test_transfer.cpp +++ b/simulation/test_transfer.cpp @@ -388,3 +388,24 @@ TORRENT_TEST(piece_extent_affinity) ); } +TORRENT_TEST(is_finished) +{ + using namespace lt; + run_test( + [](lt::session&, lt::session&) {}, + [](lt::session& ses, lt::alert const* a) { + if (alert_cast(a)) + { + TEST_EQUAL(is_finished(ses), false); + std::vector prio(4, dont_download); + ses.get_torrents()[0].prioritize_files(prio); + TEST_EQUAL(is_finished(ses), true); + } + }, + [](std::shared_ptr ses[2]) { + TEST_EQUAL(is_finished(*ses[0]), true); + TEST_EQUAL(is_finished(*ses[1]), true); + } + ); +} + diff --git a/src/torrent.cpp b/src/torrent.cpp index 9b1ac53aa..fee99a3bb 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -7604,12 +7604,7 @@ bool is_downloading_state(int const st) bool torrent::is_finished() const { if (is_seed()) return true; - - // this is slightly different from m_picker->is_finished() - // because any piece that has *passed* is considered here, - // which may be more than the piece we *have* (i.e. written to disk) - return valid_metadata() && has_picker() - && m_picker->want().num_pieces - m_picker->num_passed() == 0; + return valid_metadata() && has_picker() && m_picker->is_finished(); } bool torrent::is_inactive() const diff --git a/test/test_torrent.cpp b/test/test_torrent.cpp index 30d8cdb67..a0ca5e721 100644 --- a/test/test_torrent.cpp +++ b/test/test_torrent.cpp @@ -203,8 +203,7 @@ TORRENT_TEST(total_wanted) std::vector tmp; bencode(std::back_inserter(tmp), t.generate()); error_code ec; - auto info = std::make_shared( - tmp, std::ref(ec), from_span); + auto info = std::make_shared(tmp, std::ref(ec), from_span); settings_pack pack = settings(); pack.set_int(settings_pack::alert_mask, alert::storage_notification); @@ -220,8 +219,6 @@ TORRENT_TEST(total_wanted) p.file_priorities.resize(4, 0_pri); p.file_priorities[1] = 1_pri; - p.ti = info; - torrent_handle h = ses.add_torrent(std::move(p)); torrent_status st = h.status();