From 7f691246aa58d756fbcdc2f3a03b1623055148ac Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 31 Oct 2024 10:03:07 +0100 Subject: [PATCH] update piece picker. rename 'have' -> 'flushed' and 'passed' -> 'have' to make it clearer that a piece that has passed the hash check, we 'have', and is available to be picked by peers. This addresses an issue where we would wait for pieces to be written to disk before advertizing it to peers --- include/libtorrent/piece_picker.hpp | 46 +++++-- include/libtorrent/torrent.hpp | 23 +--- src/peer_connection.cpp | 22 ++-- src/piece_picker.cpp | 176 ++++++++++++++----------- src/torrent.cpp | 63 +++++---- test/test_file_progress.cpp | 4 +- test/test_piece_picker.cpp | 191 ++++++++++++++-------------- 7 files changed, 289 insertions(+), 236 deletions(-) diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index e493e1d8a2b..761a297f823 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -88,6 +88,20 @@ namespace libtorrent { bool last_piece; }; + // the piece picker tracks: + // 1. The blocks in which pieces we have sent requests for + // 2. Which peers we sent the requests to + // 3. The availability of each piece + // 4. The priority of each piece + // 5. Which blocks and pieces have been written to disk (versus being in the cache) + // 6. Which pieces have passed the hash check (i.e. we have them) + // 7. Cursors for sequential download + // 8. The number of pad-bytes in each piece + // All this in a data structure to make it cheap to pick the next piece to + // request from a peer. + // If we "have" a piece, it means it has passed the hash check. If a piece + // has been "flushed", it means it's been stored to disk. + // When saving resume data, we only care about "flushed" pieces. struct TORRENT_EXTRA_EXPORT piece_picker { // only defined when TORRENT_PICKER_LOG is defined, used for debugging @@ -247,11 +261,13 @@ namespace libtorrent { // seed void we_have_all(); - // This indicates that we just received this piece - // it means that the refcounter will indicate that + // A piece completes when it has passed the hash check *and* been + // completely written to disk. The piece picker no longer need to track + // the state of individual blocks + // The refcounter will indicate that // we are not interested in this piece anymore // (i.e. we don't have to maintain a refcount) - void we_have(piece_index_t); + void piece_flushed(piece_index_t); void we_dont_have(piece_index_t); // the lowest piece index we do not have @@ -264,8 +280,14 @@ namespace libtorrent { void resize(std::int64_t total_size, int piece_size); int num_pieces() const { return int(m_piece_map.size()); } + // returns true if we have the piece or if the piece + // has passed the hash check bool have_piece(piece_index_t) const; + // returns true if the piece has been completely downloaded and + // successfully flushed to disk (i.e. "finished"). + bool is_piece_flushed(piece_index_t) const; + bool is_downloading(piece_index_t const index) const { TORRENT_ASSERT(index >= piece_index_t(0)); @@ -403,10 +425,6 @@ namespace libtorrent { // only valid for v2 torrents bool is_hashing(piece_index_t piece) const; - // returns true if we have the piece or if the piece - // has passed the hash check - bool has_piece_passed(piece_index_t) const; - // returns the number of blocks there is in the given piece int blocks_in_piece(piece_index_t) const; @@ -457,7 +475,7 @@ namespace libtorrent { // number of pieces whose hash has passed (but haven't necessarily // been flushed to disk yet) - int num_passed() const { return m_num_passed; } + int num_have() const { return m_num_have; } // return true if all the pieces we want have passed the hash check (but // may not have been written to disk yet) @@ -471,11 +489,11 @@ namespace libtorrent { // 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) + // <= (m_num_have - 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(); + return num_pieces() - m_num_filtered <= m_num_have; } bool is_seeding() const { return m_num_have == num_pieces(); } @@ -535,6 +553,9 @@ namespace libtorrent { int blocks_per_piece() const; int piece_size(piece_index_t p) const; + void account_have(piece_index_t); + void account_lost(piece_index_t); + piece_extent_t extent_for(piece_index_t) const; index_range extent_for(piece_extent_t) const; @@ -830,9 +851,6 @@ namespace libtorrent { // the availability counters of the pieces int m_seeds = 0; - // the number of pieces that have passed the hash check - int m_num_passed = 0; - // this vector contains all piece indices that are pickable // sorted by priority. Pieces are in random random order // among pieces with the same priority @@ -890,7 +908,7 @@ namespace libtorrent { // all the subsequent pieces piece_index_t m_reverse_cursor{0}; - // the number of pieces we have (i.e. passed + flushed). + // the number of pieces we have (i.e. passed hash check). // This includes pieces that we have filtered but still have int m_num_have = 0; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 0de5168bd09..226b6a92cae 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -856,6 +856,7 @@ namespace libtorrent { #endif // returns true if we have downloaded the given piece + // but not necessarily flushed it to disk bool have_piece(piece_index_t index) const { if (!valid_metadata()) return false; @@ -872,15 +873,6 @@ namespace libtorrent { return m_picker->have_piece(index); } - // returns true if we have downloaded the given piece - bool has_piece_passed(piece_index_t index) const - { - if (!valid_metadata()) return false; - if (index < piece_index_t(0) || index >= torrent_file().end_piece()) return false; - if (!has_picker()) return m_have_all; - return m_picker->has_piece_passed(index); - } - #ifndef TORRENT_DISABLE_PREDICTIVE_PIECES // a predictive piece is a piece that we might // not have yet, but still announced to peers, anticipating that @@ -903,6 +895,9 @@ namespace libtorrent { public: + // the number of pieces that have passed + // hash check, but aren't necessarily + // flushed to disk yet int num_have() const { // pretend we have every piece when in seed mode @@ -912,16 +907,6 @@ namespace libtorrent { return 0; } - // the number of pieces that have passed - // hash check, but aren't necessarily - // flushed to disk yet - int num_passed() const - { - if (has_picker()) return m_picker->num_passed(); - if (m_have_all) return m_torrent_file->num_pieces(); - return 0; - } - // when we get a have message, this is called for that piece void peer_has(piece_index_t index, peer_connection const* peer); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index d019088ff01..d3a1278eafc 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -542,7 +542,7 @@ namespace libtorrent { { if (m_have_piece[j] && t->piece_priority(j) > dont_download - && !p.has_piece_passed(j)) + && !p.have_piece(j)) { interested = true; #ifndef TORRENT_DISABLE_LOGGING @@ -2084,7 +2084,7 @@ namespace libtorrent { // it's important to update whether we're interested in this peer before // calling disconnect_if_redundant, otherwise we may disconnect even if // we are interested - if (!t->has_piece_passed(index) + if (!t->have_piece(index) && !t->is_upload_only() && !is_interesting() && (!t->has_picker() || t->picker().piece_priority(index) != dont_download)) @@ -2418,7 +2418,7 @@ namespace libtorrent { , valid_piece_index ? t->torrent_file().piece_size(r.piece) : -1 , t->torrent_file().num_pieces() - , valid_piece_index ? t->has_piece_passed(r.piece) : 0 + , valid_piece_index ? t->have_piece(r.piece) : 0 , static_cast(m_superseed_piece[0]) , static_cast(m_superseed_piece[1])); } @@ -2433,7 +2433,7 @@ namespace libtorrent { bool const peer_interested = bool(m_peer_interested); t->alerts().emplace_alert( t->get_handle(), m_remote, m_peer_id, r - , t->has_piece_passed(r.piece), peer_interested, true); + , t->user_have_piece(r.piece), peer_interested, true); } return; } @@ -2502,7 +2502,7 @@ namespace libtorrent { { t->alerts().emplace_alert( t->get_handle(), m_remote, m_peer_id, r - , t->has_piece_passed(r.piece) + , t->user_have_piece(r.piece) , false, false); } @@ -2515,7 +2515,7 @@ namespace libtorrent { // is not choked if (r.piece < piece_index_t(0) || r.piece >= t->torrent_file().end_piece() - || (!t->has_piece_passed(r.piece) + || (!t->user_have_piece(r.piece) #ifndef TORRENT_DISABLE_PREDICTIVE_PIECES && !t->is_predictive_piece(r.piece) #endif @@ -2537,7 +2537,7 @@ namespace libtorrent { , valid_piece_index ? t->torrent_file().piece_size(r.piece) : -1 , ti.num_pieces() - , t->has_piece_passed(r.piece) + , t->user_have_piece(r.piece) , t->block_size()); } #endif @@ -2553,7 +2553,7 @@ namespace libtorrent { bool const peer_interested = bool(m_peer_interested); t->alerts().emplace_alert( t->get_handle(), m_remote, m_peer_id, r - , t->has_piece_passed(r.piece), peer_interested, false); + , t->user_have_piece(r.piece), peer_interested, false); } // every ten invalid request, remind the peer that it's choked @@ -3516,7 +3516,7 @@ namespace libtorrent { // to download it, request it if (index < m_have_piece.end_index() && m_have_piece[index] - && !t->has_piece_passed(index) + && !t->have_piece(index) && t->valid_metadata() && t->has_picker() && t->picker().piece_priority(index) > dont_download) @@ -4001,7 +4001,7 @@ namespace libtorrent { { std::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); - TORRENT_ASSERT(t->has_piece_passed(piece)); + TORRENT_ASSERT(t->have_piece(piece)); TORRENT_ASSERT(piece < t->torrent_file().end_piece()); } #endif @@ -5354,7 +5354,7 @@ namespace libtorrent { continue; } - if (!t->has_piece_passed(r.piece) && !seed_mode) + if (!t->have_piece(r.piece) && !seed_mode) { #ifndef TORRENT_DISABLE_PREDICTIVE_PIECES // we don't have this piece yet, but we anticipate to have diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index fb8819db435..e7e10040f3a 100644 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -197,7 +197,6 @@ namespace libtorrent { m_have_pad_bytes = 0; m_filtered_pad_bytes += m_have_filtered_pad_bytes; m_have_filtered_pad_bytes = 0; - m_num_passed = 0; m_dirty = true; for (auto& m : m_piece_map) { @@ -633,31 +632,42 @@ namespace libtorrent { { piece_pos const& p = *i; + int const pad_bytes = pad_bytes_in_piece(piece); if (p.filtered()) { - if (p.index != piece_pos::we_have_index) + if (p.downloading()) { - ++num_filtered; - num_filtered_pad_bytes += pad_bytes_in_piece(piece); + auto dl = find_dl_piece(p.download_queue(), piece); + if (dl->passed_hash_check) + { + ++num_have_filtered; + num_have_filtered_pad_bytes += pad_bytes; + } + else + { + ++num_filtered; + num_filtered_pad_bytes += pad_bytes; + } } - else + else if (p.have()) { ++num_have_filtered; - num_have_filtered_pad_bytes += pad_bytes_in_piece(piece); + num_have_filtered_pad_bytes += pad_bytes; + } + else + { + ++num_filtered; + num_filtered_pad_bytes += pad_bytes; } } #ifdef TORRENT_DEBUG_REFCOUNTS TORRENT_ASSERT(int(p.have_peers.size()) == p.peer_count + m_seeds); #endif - if (p.index == piece_pos::we_have_index) + if (p.have()) { ++num_have; - num_have_pad_bytes += pad_bytes_in_piece(piece); - } - - if (p.index == piece_pos::we_have_index) - { + num_have_pad_bytes += pad_bytes; TORRENT_ASSERT(t == nullptr || t->have_piece(piece)); TORRENT_ASSERT(p.downloading() == false); } @@ -669,6 +679,12 @@ namespace libtorrent { if (p.downloading()) { + auto dl = find_dl_piece(p.download_queue(), piece); + if (dl->passed_hash_check) + { + ++num_have; + num_have_pad_bytes += pad_bytes; + } if (p.reverse()) TORRENT_ASSERT(prio == -1 || (prio % piece_picker::prio_factor == 2)); else @@ -1615,11 +1631,12 @@ namespace libtorrent { TORRENT_ASSERT(!i->passed_hash_check); i->passed_hash_check = true; - ++m_num_passed; + + account_have(index); if (i->finished < blocks_in_piece(index)) return; - we_have(index); + piece_flushed(index); } void piece_picker::we_dont_have(piece_index_t const index) @@ -1632,7 +1649,8 @@ namespace libtorrent { << index << ")" << std::endl; #endif - if (!p.have()) + bool have_piece = p.have(); + if (!have_piece) { // even though we don't have the piece, it // might still have passed hash check @@ -1640,29 +1658,14 @@ namespace libtorrent { if (download_state == piece_pos::piece_open) return; auto const i = find_dl_piece(download_state, index); - if (i->passed_hash_check) - { - i->passed_hash_check = false; - TORRENT_ASSERT(m_num_passed > 0); - --m_num_passed; - } + have_piece = i->passed_hash_check; erase_download_piece(i); - return; } - TORRENT_ASSERT(m_num_passed > 0); - --m_num_passed; - if (p.filtered()) - { - m_filtered_pad_bytes += pad_bytes_in_piece(index); - ++m_num_filtered; + if (have_piece) + account_lost(index); - TORRENT_ASSERT(m_have_filtered_pad_bytes >= pad_bytes_in_piece(index)); - m_have_filtered_pad_bytes -= pad_bytes_in_piece(index); - TORRENT_ASSERT(m_num_have_filtered > 0); - --m_num_have_filtered; - } - else + if (!p.filtered()) { // update cursors if (index < m_cursor) m_cursor = index; @@ -1674,9 +1677,6 @@ namespace libtorrent { } } - --m_num_have; - m_have_pad_bytes -= pad_bytes_in_piece(index); - TORRENT_ASSERT(m_have_pad_bytes >= 0); p.set_not_have(); if (m_dirty) return; @@ -1687,13 +1687,11 @@ namespace libtorrent { // downloaded a piece, and that no further attempts // to pick that piece should be made. The piece will // be removed from the available piece list. - void piece_picker::we_have(piece_index_t const index) + void piece_picker::piece_flushed(piece_index_t const index) { -#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS INVARIANT_CHECK; -#endif #ifdef TORRENT_PICKER_LOG - std::cerr << "[" << this << "] " << "piece_picker::we_have(" + std::cerr << "[" << this << "] " << "piece_picker::piece_flushed(" << index << ")" << std::endl; #endif piece_pos& p = m_piece_map[index]; @@ -1704,31 +1702,27 @@ namespace libtorrent { if (p.have()) return; auto const state = p.download_queue(); - if (state != piece_pos::piece_open) + bool passed_hash_check = false; + if (p.downloading()) { auto const i = find_dl_piece(state, index); TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i->hashing == 0); - // decrement num_passed here to compensate - // for the unconditional increment further down - if (i->passed_hash_check) --m_num_passed; + passed_hash_check = i->passed_hash_check; + TORRENT_ASSERT(i->locked == false); + if (i->locked) return; erase_download_piece(i); } - if (p.filtered()) + if (!passed_hash_check) { - TORRENT_ASSERT(m_filtered_pad_bytes >= pad_bytes_in_piece(index)); - m_filtered_pad_bytes -= pad_bytes_in_piece(index); - TORRENT_ASSERT(m_num_filtered > 0); - --m_num_filtered; - - m_have_filtered_pad_bytes += pad_bytes_in_piece(index); - ++m_num_have_filtered; + // if we go straight from open to flushed, we need to make sure we + // maintain the accounting as-if we had downloaded it and checked + // the hash first. e.g. when we load resume data, we set up the + // piece states to indicate they're already on disk + account_have(index); } - ++m_num_have; - ++m_num_passed; - m_have_pad_bytes += pad_bytes_in_piece(index); - TORRENT_ASSERT(m_have_pad_bytes <= num_pad_bytes()); + p.set_have(); if (m_cursor == prev(m_reverse_cursor) && m_cursor == index) @@ -1783,7 +1777,6 @@ namespace libtorrent { m_filtered_pad_bytes = 0; m_cursor = m_piece_map.end_index(); m_reverse_cursor = piece_index_t{0}; - m_num_passed = num_pieces(); m_num_have = num_pieces(); for (auto& queue : m_downloads) queue.clear(); @@ -2538,12 +2531,13 @@ namespace { return ret; } - // have piece means that the piece passed hash check - // AND has been successfully written to disk - bool piece_picker::have_piece(piece_index_t const index) const + bool piece_picker::is_piece_flushed(piece_index_t const index) const { + TORRENT_ASSERT(index < m_piece_map.end_index()); + TORRENT_ASSERT(index >= piece_index_t(0)); + piece_pos const& p = m_piece_map[index]; - return p.index == piece_pos::we_have_index; + return p.have(); } int piece_picker::blocks_in_piece(piece_index_t const index) const @@ -2912,13 +2906,13 @@ namespace { return i->hashing > 0; } - bool piece_picker::has_piece_passed(piece_index_t const index) const + bool piece_picker::have_piece(piece_index_t const index) const { TORRENT_ASSERT(index < m_piece_map.end_index()); TORRENT_ASSERT(index >= piece_index_t(0)); piece_pos const& p = m_piece_map[index]; - if (p.index == piece_pos::we_have_index) return true; + if (p.have()) return true; auto const state = p.download_queue(); if (state == piece_pos::piece_open) @@ -3474,8 +3468,7 @@ namespace { // but it seems reasonable to not break the // accounting over it. i->passed_hash_check = false; - TORRENT_ASSERT(m_num_passed > 0); - --m_num_passed; + account_lost(piece); } // prevent this piece from being picked until it's restored @@ -3483,7 +3476,7 @@ namespace { } // TODO: 2 it would be nice if this could be folded into lock_piece() - // the main distinction is that this also maintains the m_num_passed + // the main distinction is that this also maintains the m_num_have // counter and the passed_hash_check member // Is there ever a case where we call write failed without also locking // the piece? Perhaps write_failed() should imply locking it. @@ -3526,8 +3519,7 @@ namespace { // some of the blocks to disk, which means we // can't consider the piece complete i->passed_hash_check = false; - TORRENT_ASSERT(m_num_passed > 0); - --m_num_passed; + account_lost(block.piece_index); } // prevent this hash job from actually completing @@ -3697,7 +3689,7 @@ namespace { return; if (i->passed_hash_check && i->hashing == 0) - we_have(i->index); + piece_flushed(i->index); } #if TORRENT_USE_INVARIANT_CHECKS @@ -3715,6 +3707,8 @@ namespace { TORRENT_ASSERT(bytes <= piece_size(piece)); m_num_pad_bytes += bytes; + // We don't support *changing* the number of pad bytes in a piece + TORRENT_ASSERT(m_pads_in_piece.count(piece) == 0); m_pads_in_piece[piece] = bytes; piece_pos& p = m_piece_map[piece]; @@ -3734,7 +3728,7 @@ namespace { if (piece_size(piece) == bytes) { // the entire piece is a pad file - we_have(piece); + piece_flushed(piece); } } @@ -3931,4 +3925,44 @@ namespace { return ret; } + void piece_picker::account_have(piece_index_t const index) + { + ++m_num_have; + piece_pos& p = m_piece_map[index]; + TORRENT_ASSERT(!p.have()); + int const pad_bytes = pad_bytes_in_piece(index); + if (p.filtered()) + { + TORRENT_ASSERT(m_filtered_pad_bytes >= pad_bytes); + m_filtered_pad_bytes -= pad_bytes; + TORRENT_ASSERT(m_num_filtered > 0); + --m_num_filtered; + + m_have_filtered_pad_bytes += pad_bytes; + ++m_num_have_filtered; + } + m_have_pad_bytes += pad_bytes; + TORRENT_ASSERT(m_have_pad_bytes <= num_pad_bytes()); + } + + void piece_picker::account_lost(piece_index_t const index) + { + TORRENT_ASSERT(m_num_have > 0); + --m_num_have; + piece_pos& p = m_piece_map[index]; + int const pad_bytes = pad_bytes_in_piece(index); + if (p.filtered()) + { + m_filtered_pad_bytes += pad_bytes; + TORRENT_ASSERT(m_filtered_pad_bytes <= num_pad_bytes()); + ++m_num_filtered; + + TORRENT_ASSERT(m_have_filtered_pad_bytes >= pad_bytes); + m_have_filtered_pad_bytes -= pad_bytes; + TORRENT_ASSERT(m_num_have_filtered > 0); + --m_num_have_filtered; + } + TORRENT_ASSERT(m_have_pad_bytes >= pad_bytes); + m_have_pad_bytes -= pad_bytes; + } } diff --git a/src/torrent.cpp b/src/torrent.cpp index af5487214e7..d47a5ab94b9 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -755,7 +755,7 @@ bool is_downloading_state(int const st) { ec.assign(errors::no_metadata, libtorrent_category()); } - else if (!has_piece_passed(piece)) + else if (!user_have_piece(piece)) { ec.assign(errors::invalid_piece_index, libtorrent_category()); } @@ -1298,14 +1298,18 @@ bool is_downloading_state(int const st) piece_refcount(piece_refcount const&) = delete; piece_refcount& operator=(piece_refcount const&) = delete; + void disarm() { m_armed = false; } + ~piece_refcount() { - m_picker.dec_refcount(m_piece, nullptr); + if (m_armed) + m_picker.dec_refcount(m_piece, nullptr); } private: piece_picker& m_picker; piece_index_t m_piece; + bool m_armed = true; }; void torrent::add_piece_async(piece_index_t const piece @@ -1413,6 +1417,10 @@ bool is_downloading_state(int const st) } } m_ses.deferred_submit_jobs(); + // if we don't have a picker anymore, we don't need to (and shouldn't) + // decrement the refcount + if (!m_picker) + refcount.disarm(); } void torrent::on_disk_write_complete(storage_error const& error @@ -2210,7 +2218,7 @@ bool is_downloading_state(int const st) { if (!m_add_torrent_params->have_pieces[i]) continue; need_picker(); - m_picker->we_have(i); + m_picker->piece_flushed(i); inc_stats_counter(counters::num_piece_passed); update_gauge(); we_have(i, true); @@ -2230,7 +2238,7 @@ bool is_downloading_state(int const st) continue; } - if (has_piece_passed(piece)) + if (have_piece(piece)) continue; // being in seed mode and missing a piece is not compatible. @@ -2557,7 +2565,7 @@ bool is_downloading_state(int const st) if (has_picker() || !m_have_all) { need_picker(); - m_picker->we_have(piece); + m_picker->piece_flushed(piece); set_need_save_resume(torrent_handle::if_download_progress); update_gauge(); } @@ -3915,17 +3923,17 @@ namespace { if (m_seed_mode) return std::int64_t(0); if (!has_picker()) return is_seed() ? std::int64_t(0) : m_torrent_file->total_size(); + piece_count const pc = m_picker->have(); std::int64_t left = m_torrent_file->total_size() - - std::int64_t(m_picker->num_passed()) * m_torrent_file->piece_length(); + - std::int64_t(pc.num_pieces) * m_torrent_file->piece_length(); // if we have the last piece, we may have subtracted too much, as it can // be smaller than the normal piece size. // we have to correct it - piece_index_t const last_piece = prev(m_torrent_file->end_piece()); - if (m_picker->has_piece_passed(last_piece)) + if (pc.last_piece) { - left += m_torrent_file->piece_length() - m_torrent_file->piece_size(last_piece); + left += m_torrent_file->piece_length() - m_torrent_file->piece_size(m_torrent_file->last_piece()); } return left; @@ -4166,7 +4174,7 @@ namespace { void torrent::we_have(piece_index_t const index, bool const loading_resume) { TORRENT_ASSERT(is_single_thread()); - TORRENT_ASSERT(!has_picker() || m_picker->has_piece_passed(index)); + TORRENT_ASSERT(!has_picker() || m_picker->have_piece(index)); inc_stats_counter(counters::num_have_pieces); @@ -4348,11 +4356,11 @@ namespace { if (!has_picker() || verified_piece == piece || !m_picker->is_piece_finished(verified_piece) - || m_picker->has_piece_passed(verified_piece)) + || m_picker->have_piece(verified_piece)) continue; TORRENT_ASSERT(get_hash_picker().piece_verified(verified_piece)); - m_picker->we_have(verified_piece); + m_picker->piece_flushed(verified_piece); update_gauge(); we_have(verified_piece); } @@ -4401,11 +4409,11 @@ namespace { { // INVARIANT_CHECK; TORRENT_ASSERT(is_single_thread()); - TORRENT_ASSERT(!m_picker->has_piece_passed(index)); + TORRENT_ASSERT(!m_picker->have_piece(index)); #ifndef TORRENT_DISABLE_LOGGING if (should_log()) - debug_log("PIECE_PASSED (%d)", int(index)); + debug_log("PIECE_PASSED (%d) (num_have: %d)", int(index), num_have()); #endif // std::fprintf(stderr, "torrent::piece_passed piece:%d\n", index); @@ -4465,6 +4473,10 @@ namespace { update_gauge(); we_have(index); +#ifndef TORRENT_DISABLE_LOGGING + if (should_log()) + debug_log("we_have(%d) (num_have: %d)", int(index), num_have()); +#endif #ifndef TORRENT_DISABLE_STREAMING remove_time_critical_piece(index, true); #endif @@ -5138,7 +5150,7 @@ namespace { // if we already have the piece, no need to set the deadline. // however, if the user asked to get the piece data back, we still // need to read it and post it back to the user - if (is_seed() || (has_picker() && m_picker->has_piece_passed(piece))) + if (is_seed() || (has_picker() && m_picker->have_piece(piece))) { if (flags & torrent_handle::alert_when_available) read_piece(piece); @@ -7030,8 +7042,7 @@ namespace { auto const info = m_picker->blocks_for_piece(dp); for (int i = 0; i < int(info.size()); ++i) { - if (info[i].state == piece_picker::block_info::state_finished - || info[i].state == piece_picker::block_info::state_writing) + if (info[i].state == piece_picker::block_info::state_finished) bitmask.set_bit(i); } ret.unfinished_pieces.emplace(dp.index, std::move(bitmask)); @@ -7086,7 +7097,7 @@ namespace { { ret.have_pieces.resize(static_cast(max_piece), false); for (auto const i : ret.have_pieces.range()) - if (m_picker->have_piece(i)) ret.have_pieces.set_bit(i); + if (m_picker->is_piece_flushed(i)) ret.have_pieces.set_bit(i); } if (m_seed_mode) @@ -8647,7 +8658,7 @@ namespace { if (!valid_metadata()) return false; if (m_seed_mode) return true; if (m_have_all) return true; - if (m_picker && m_picker->num_passed() == m_picker->num_pieces()) return true; + if (m_picker && m_picker->is_seeding()) return true; return m_state == torrent_status::seeding; } @@ -11510,7 +11521,7 @@ namespace { file_storage const& fs = m_torrent_file->files(); for (auto const& dp : q) { - if (has_piece_passed(dp.index)) + if (have_piece(dp.index)) { // in this case this piece has already been accounted for in fp continue; @@ -12013,7 +12024,7 @@ namespace { { st->pieces.resize(num_pieces, false); for (auto const i : st->pieces.range()) - if (m_picker->has_piece_passed(i)) st->pieces.set_bit(i); + if (m_picker->have_piece(i)) st->pieces.set_bit(i); } else if (m_have_all) { @@ -12024,16 +12035,20 @@ namespace { st->pieces.resize(num_pieces, false); } } - st->num_pieces = num_passed(); + st->num_pieces = num_have(); #if TORRENT_USE_INVARIANT_CHECKS { // The documentation states that `num_pieces` is the count of number // of bits set in `pieces`. Ensure that invariant holds. int num_have_pieces = 0; - if (has_picker()) + if (m_seed_mode) + { + num_have_pieces = m_torrent_file->num_pieces(); + } + else if (has_picker()) { for (auto const i : m_torrent_file->piece_range()) - if (m_picker->has_piece_passed(i)) ++num_have_pieces; + if (m_picker->have_piece(i)) ++num_have_pieces; } else if (m_have_all) { diff --git a/test/test_file_progress.cpp b/test/test_file_progress.cpp index b8f8821eaa6..6176455d064 100644 --- a/test/test_file_progress.cpp +++ b/test/test_file_progress.cpp @@ -58,7 +58,7 @@ TORRENT_TEST(init) for (auto const idx : fs.piece_range()) { piece_picker picker(fs.total_size(), fs.piece_length()); - picker.we_have(idx); + picker.piece_flushed(idx); aux::file_progress fp; fp.init(picker, fs); @@ -90,7 +90,7 @@ TORRENT_TEST(init2) for (auto const idx : fs.piece_range()) { piece_picker picker(fs.total_size(), fs.piece_length()); - picker.we_have(idx); + picker.piece_flushed(idx); aux::vector vec; aux::file_progress fp; diff --git a/test/test_piece_picker.cpp b/test/test_piece_picker.cpp index 35c3487ab1f..ddee1db7464 100644 --- a/test/test_piece_picker.cpp +++ b/test/test_piece_picker.cpp @@ -197,7 +197,7 @@ std::shared_ptr setup_picker( for (auto i = 0_piece; i < piece_index_t(num_pieces); ++i) { if (!have[i]) continue; - p->we_have(i); + p->piece_flushed(i); for (int j = 0; j < blocks_per_piece; ++j) TEST_CHECK(p->is_finished(piece_block(i, j))); } @@ -579,12 +579,12 @@ TORRENT_TEST(we_dont_have) { // make sure we_dont_have works auto p = setup_picker("1111111", "*******", "0100000", ""); - TEST_CHECK(p->have_piece(1_piece)); - TEST_CHECK(p->have_piece(2_piece)); + TEST_CHECK(p->is_piece_flushed(1_piece)); + TEST_CHECK(p->is_piece_flushed(2_piece)); p->we_dont_have(1_piece); p->we_dont_have(2_piece); - TEST_CHECK(!p->have_piece(1_piece)); - TEST_CHECK(!p->have_piece(2_piece)); + TEST_CHECK(!p->is_piece_flushed(1_piece)); + TEST_CHECK(!p->is_piece_flushed(2_piece)); auto picked = pick_pieces(p, "*** ** ", 1, 0, nullptr, options, empty_vector); TEST_CHECK(int(picked.size()) > 0); TEST_CHECK(picked.front().piece_index == 1_piece); @@ -639,7 +639,7 @@ TORRENT_TEST(resize) TEST_EQUAL(p->have().num_pieces, 0); TEST_EQUAL(p->have().pad_bytes, 0); - p->we_have(0_piece); + p->piece_flushed(0_piece); TEST_EQUAL(p->want().num_pieces, 6); TEST_EQUAL(p->want().pad_bytes, 20); @@ -855,13 +855,13 @@ TORRENT_TEST(priority_sequential_download) TORRENT_TEST(cursors_sweep_up_we_have) { - // sweep up, we_have() + // sweep up, piece_flushed() auto p = setup_picker("7654321", " ", "", ""); for (auto i = 0_piece; i < 7_piece; ++i) { TEST_EQUAL(p->cursor(), i); TEST_EQUAL(p->reverse_cursor(), 7_piece); - p->we_have(i); + p->piece_flushed(i); } TEST_CHECK(p->is_finished()); TEST_CHECK(p->is_seeding()); @@ -887,13 +887,13 @@ TORRENT_TEST(cursors_sweep_up_set_piece_priority) TORRENT_TEST(cursors_sweep_down_we_have) { - // sweep down, we_have() + // sweep down, piece_flushed() auto p = setup_picker("7654321", " ", "", ""); for (auto i = 6_piece; i >= 0_piece; --i) { TEST_EQUAL(p->cursor(), 0_piece); TEST_EQUAL(p->reverse_cursor(), next(i)); - p->we_have(i); + p->piece_flushed(i); } TEST_CHECK(p->is_finished()); TEST_CHECK(p->is_seeding()); @@ -937,15 +937,15 @@ TORRENT_TEST(cursors_sweep_in_set_priority) TORRENT_TEST(cursors_sweep_in_we_have) { - // sweep in, we_have() + // sweep in, piece_flushed() auto p = setup_picker("7654321", " ", "", ""); for (piece_index_t left(0), right(6); left <= 3_piece && right >= 3_piece; ++left, --right) { TEST_EQUAL(p->cursor(), left); TEST_EQUAL(p->reverse_cursor(), next(right)); - p->we_have(left); - p->we_have(right); + p->piece_flushed(left); + p->piece_flushed(right); } TEST_CHECK(p->is_finished()); TEST_CHECK(p->is_seeding()); @@ -1019,21 +1019,21 @@ TORRENT_TEST(cursors) auto p = setup_picker("7654321", " ", "", ""); TEST_EQUAL(p->cursor(), 0_piece); TEST_EQUAL(p->reverse_cursor(), 7_piece); - p->we_have(1_piece); + p->piece_flushed(1_piece); TEST_EQUAL(p->cursor(), 0_piece); TEST_EQUAL(p->reverse_cursor(), 7_piece); - p->we_have(0_piece); + p->piece_flushed(0_piece); TEST_EQUAL(p->cursor(), 2_piece); TEST_EQUAL(p->reverse_cursor(), 7_piece); - p->we_have(5_piece); + p->piece_flushed(5_piece); TEST_EQUAL(p->cursor(), 2_piece); TEST_EQUAL(p->reverse_cursor(), 7_piece); - p->we_have(6_piece); + p->piece_flushed(6_piece); TEST_EQUAL(p->cursor(), 2_piece); TEST_EQUAL(p->reverse_cursor(), 5_piece); - p->we_have(4_piece); - p->we_have(3_piece); - p->we_have(2_piece); + p->piece_flushed(4_piece); + p->piece_flushed(3_piece); + p->piece_flushed(2_piece); TEST_EQUAL(p->cursor(), 7_piece); TEST_EQUAL(p->reverse_cursor(), 0_piece); @@ -1072,7 +1072,7 @@ TORRENT_TEST(piece_priorities) TEST_EQUAL(p->want().num_pieces, 6); TEST_EQUAL(p->have_want().num_pieces, 0); p->mark_as_finished({0_piece, 0}, nullptr); - p->we_have(0_piece); + p->piece_flushed(0_piece); TEST_EQUAL(p->want().num_pieces, 6); TEST_EQUAL(p->have_want().num_pieces, 0); TEST_EQUAL(p->have().num_pieces, 1); @@ -1088,7 +1088,7 @@ TORRENT_TEST(piece_priorities) TEST_CHECK(picked[std::size_t(i)] == piece_block(piece_index_t(i / blocks_per_piece), i % blocks_per_piece)); // test changing priority on a piece we have - p->we_have(0_piece); + p->piece_flushed(0_piece); p->set_piece_priority(0_piece, dont_download); p->set_piece_priority(0_piece, low_priority); p->set_piece_priority(0_piece, dont_download); @@ -1238,7 +1238,7 @@ TORRENT_TEST(random_pick) for (int i = 0; i < 7; ++i) { piece_index_t const piece = test_pick(p, {}); - p->we_have(piece); + p->piece_flushed(piece); random_pieces.insert(piece); } TEST_CHECK(random_pieces.size() == 7); @@ -1694,49 +1694,50 @@ TORRENT_TEST(piece_passed) { auto p = setup_picker("1111111", "* ", "", "0300000"); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->num_passed(), 1); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->num_have(), 1); TEST_EQUAL(p->have().num_pieces, 1); p->piece_passed(1_piece); - TEST_EQUAL(p->num_passed(), 2); - TEST_EQUAL(p->have().num_pieces, 1); + TEST_EQUAL(p->num_have(), 2); + TEST_EQUAL(p->have().num_pieces, 2); - p->we_have(1_piece); + p->piece_flushed(1_piece); TEST_EQUAL(p->have().num_pieces, 2); p->mark_as_finished({2_piece, 0}, &tmp1); p->piece_passed(2_piece); - TEST_EQUAL(p->num_passed(), 3); - // just because the hash check passed doesn't mean - // we "have" the piece. We need to write it to disk first - TEST_EQUAL(p->have().num_pieces, 2); + TEST_EQUAL(p->num_have(), 3); + // since the hash check passed we "have" the piece. + TEST_EQUAL(p->have().num_pieces, 3); + TEST_EQUAL(p->is_piece_flushed(0_piece), true); + TEST_EQUAL(p->is_piece_flushed(1_piece), true); + TEST_EQUAL(p->is_piece_flushed(2_piece), false); // piece 2 already passed the hash check, as soon as we've // written all the blocks to disk, we should have that piece too p->mark_as_finished({2_piece, 1}, &tmp1); p->mark_as_finished({2_piece, 2}, &tmp1); p->mark_as_finished({2_piece, 3}, &tmp1); - TEST_EQUAL(p->have().num_pieces, 3); - TEST_EQUAL(p->have_piece(2_piece), true); + TEST_EQUAL(p->is_piece_flushed(2_piece), true); } TORRENT_TEST(piece_passed_causing_we_have) { auto p = setup_picker("1111111", "* ", "", "0700000"); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->num_passed(), 1); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->num_have(), 1); TEST_EQUAL(p->have().num_pieces, 1); p->mark_as_finished({1_piece, 3}, &tmp1); - TEST_EQUAL(p->num_passed(), 1); + TEST_EQUAL(p->num_have(), 1); TEST_EQUAL(p->have().num_pieces, 1); p->piece_passed(1_piece); - TEST_EQUAL(p->num_passed(), 2); + TEST_EQUAL(p->num_have(), 2); TEST_EQUAL(p->have().num_pieces, 2); } @@ -1760,38 +1761,38 @@ TORRENT_TEST(break_one_seed) TORRENT_TEST(we_dont_have2) { auto p = setup_picker("1111111", "* * ", "1101111", ""); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->has_piece_passed(2_piece), true); - TEST_EQUAL(p->num_passed(), 2); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(2_piece), true); + TEST_EQUAL(p->num_have(), 2); TEST_EQUAL(p->have().num_pieces, 2); TEST_EQUAL(p->have_want().num_pieces, 1); TEST_EQUAL(p->want().num_pieces, 6); p->we_dont_have(0_piece); - TEST_EQUAL(p->has_piece_passed(0_piece), false); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->has_piece_passed(2_piece), true); - TEST_EQUAL(p->num_passed(), 1); + TEST_EQUAL(p->have_piece(0_piece), false); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(2_piece), true); + TEST_EQUAL(p->num_have(), 1); TEST_EQUAL(p->have().num_pieces, 1); TEST_EQUAL(p->have_want().num_pieces, 0); p = setup_picker("1111111", "* * ", "1101111", ""); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->has_piece_passed(2_piece), true); - TEST_EQUAL(p->num_passed(), 2); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(2_piece), true); + TEST_EQUAL(p->num_have(), 2); TEST_EQUAL(p->have().num_pieces, 2); TEST_EQUAL(p->have_want().num_pieces, 1); TEST_EQUAL(p->want().num_pieces, 6); p->we_dont_have(2_piece); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); - TEST_EQUAL(p->has_piece_passed(2_piece), false); - TEST_EQUAL(p->num_passed(), 1); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(2_piece), false); + TEST_EQUAL(p->num_have(), 1); TEST_EQUAL(p->have().num_pieces, 1); TEST_EQUAL(p->have_want().num_pieces, 1); TEST_EQUAL(p->want().num_pieces, 6); @@ -1801,44 +1802,44 @@ TORRENT_TEST(dont_have_but_passed_hash_check) { auto p = setup_picker("1111111", "* * ", "1101111", "0200000"); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); TEST_EQUAL(p->have_piece(0_piece), true); TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->is_piece_flushed(0_piece), true); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); p->piece_passed(1_piece); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), true); - TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), true); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); p->we_dont_have(1_piece); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); + TEST_EQUAL(p->have_piece(0_piece), true); TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); } TORRENT_TEST(write_failed) { auto p = setup_picker("1111111", "* * ", "1101111", "0200000"); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); + TEST_EQUAL(p->have_piece(0_piece), true); TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); p->piece_passed(1_piece); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), true); - TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->have_piece(0_piece), true); + TEST_EQUAL(p->have_piece(1_piece), true); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); p->mark_as_writing({1_piece, 0}, &tmp1); p->write_failed({1_piece, 0}); - TEST_EQUAL(p->has_piece_passed(0_piece), true); - TEST_EQUAL(p->has_piece_passed(1_piece), false); + TEST_EQUAL(p->have_piece(0_piece), true); TEST_EQUAL(p->have_piece(1_piece), false); + TEST_EQUAL(p->is_piece_flushed(1_piece), false); // make sure write_failed() and lock_piece() actually // locks the piece, and that it won't be picked. @@ -2164,7 +2165,7 @@ TORRENT_TEST(num_pad_bytes_want_filter) TORRENT_TEST(num_pad_bytes_want_have) { auto p = setup_picker("111", " ", "444", ""); - p->we_have(1_piece); + p->piece_flushed(1_piece); TEST_CHECK((p->want() == piece_count{3, 0, true})); TEST_CHECK((p->have_want() == piece_count{1, 0, false})); TEST_CHECK((p->have() == piece_count{1, 0, false})); @@ -2193,7 +2194,7 @@ TORRENT_TEST(num_pad_bytes_we_have) p->set_pad_bytes(1_piece, 2); p->set_pad_bytes(0_piece, 0x4000); - p->we_have(1_piece); + p->piece_flushed(1_piece); TEST_CHECK((p->want() == piece_count{3, 0x4003, true})); TEST_CHECK((p->have_want() == piece_count{1, 2, false})); TEST_CHECK((p->have() == piece_count{1, 2, false})); @@ -2208,7 +2209,7 @@ TORRENT_TEST(num_pad_bytes_dont_want_have) p->set_pad_bytes(0_piece, 0x4000); p->set_piece_priority(1_piece, dont_download); - p->we_have(1_piece); + p->piece_flushed(1_piece); TEST_CHECK((p->want() == piece_count{2, 0x4001, true})); TEST_CHECK((p->have_want() == piece_count{0, 0, false})); TEST_CHECK((p->have() == piece_count{1, 2, false})); @@ -2222,7 +2223,7 @@ TORRENT_TEST(num_pad_bytes_have_dont_want) p->set_pad_bytes(1_piece, 2); p->set_pad_bytes(0_piece, 0x4000); - p->we_have(1_piece); + p->piece_flushed(1_piece); p->set_piece_priority(1_piece, dont_download); TEST_CHECK((p->want() == piece_count{2, 0x4001, true})); TEST_CHECK((p->have_want() == piece_count{0, 0, false})); @@ -2233,7 +2234,7 @@ TORRENT_TEST(num_pad_bytes_have_dont_want) TORRENT_TEST(have_dont_want_pad_bytes) { auto p = setup_picker("111", " ", "444", ""); - p->we_have(1_piece); + p->piece_flushed(1_piece); p->set_piece_priority(1_piece, dont_download); p->set_pad_bytes(2_piece, 1); p->set_pad_bytes(1_piece, 2); @@ -2250,38 +2251,38 @@ TORRENT_TEST(pad_bytes_have) { auto p = setup_picker("1111111", " ", "4444444", ""); p->set_pad_bytes(2_piece, 10); - TEST_CHECK(!p->have_piece(0_piece)); - TEST_CHECK(!p->have_piece(1_piece)); - TEST_CHECK(!p->have_piece(2_piece)); - TEST_CHECK(!p->have_piece(3_piece)); + TEST_CHECK(!p->is_piece_flushed(0_piece)); + TEST_CHECK(!p->is_piece_flushed(1_piece)); + TEST_CHECK(!p->is_piece_flushed(2_piece)); + TEST_CHECK(!p->is_piece_flushed(3_piece)); } { auto p = setup_picker("1111111", " ", "4444444", ""); p->set_pad_bytes(2_piece, default_block_size); - TEST_CHECK(!p->have_piece(0_piece)); - TEST_CHECK(!p->have_piece(1_piece)); - TEST_CHECK(!p->have_piece(2_piece)); - TEST_CHECK(!p->have_piece(3_piece)); + TEST_CHECK(!p->is_piece_flushed(0_piece)); + TEST_CHECK(!p->is_piece_flushed(1_piece)); + TEST_CHECK(!p->is_piece_flushed(2_piece)); + TEST_CHECK(!p->is_piece_flushed(3_piece)); } { auto p = setup_picker("1111111", " ", "4444444", ""); p->set_pad_bytes(2_piece, blocks_per_piece * default_block_size); - TEST_CHECK(!p->have_piece(0_piece)); - TEST_CHECK(!p->have_piece(1_piece)); - TEST_CHECK(p->have_piece(2_piece)); - TEST_CHECK(!p->have_piece(3_piece)); + TEST_CHECK(!p->is_piece_flushed(0_piece)); + TEST_CHECK(!p->is_piece_flushed(1_piece)); + TEST_CHECK(p->is_piece_flushed(2_piece)); + TEST_CHECK(!p->is_piece_flushed(3_piece)); } { auto p = setup_picker("1111111", " ", "4444444", ""); p->set_pad_bytes(2_piece, blocks_per_piece * default_block_size); p->set_pad_bytes(1_piece, default_block_size); - TEST_CHECK(!p->have_piece(0_piece)); - TEST_CHECK(!p->have_piece(1_piece)); - TEST_CHECK(p->have_piece(2_piece)); - TEST_CHECK(!p->have_piece(3_piece)); + TEST_CHECK(!p->is_piece_flushed(0_piece)); + TEST_CHECK(!p->is_piece_flushed(1_piece)); + TEST_CHECK(p->is_piece_flushed(2_piece)); + TEST_CHECK(!p->is_piece_flushed(3_piece)); } } @@ -2431,7 +2432,7 @@ TORRENT_TEST(pad_blocks_some_wanted_odd_blocks) auto p = std::make_shared( 3 * piece_size, piece_size); - p->we_have(1_piece); + p->piece_flushed(1_piece); p->set_piece_priority(1_piece, dont_download); p->set_pad_bytes(2_piece, 1); p->set_pad_bytes(1_piece, 2); @@ -2484,7 +2485,7 @@ TORRENT_TEST(mark_as_pad_whole_piece_seeding) { auto p = setup_picker("11", " ", "44", ""); p->set_pad_bytes(0_piece, 0x4000 * 4); - TEST_CHECK(p->have_piece(0_piece)); + TEST_CHECK(p->is_piece_flushed(0_piece)); TEST_CHECK(!p->is_seeding()); @@ -2772,8 +2773,8 @@ TORRENT_TEST(piece_extent_affinity_clear_done) // now all 5 extents are in use, if we finish a whole extent, it should be // removed from the list - p->we_have(0_piece); - p->we_have(1_piece); + p->piece_flushed(0_piece); + p->piece_flushed(1_piece); // we need to invoke the piece picker once to detect and reap this full // extent