fix: assertion failed "s->leftUntilDone <= s->sizeWhenDone" (#3406)
This commit is contained in:
parent
707fce44da
commit
513f4bc91b
|
@ -74,6 +74,17 @@ public:
|
|||
return { pieceLoc(piece).block, pieceLastLoc(piece).block + 1 };
|
||||
}
|
||||
|
||||
[[nodiscard]] tr_byte_span_t byteSpanForPiece(tr_piece_index_t piece) const noexcept
|
||||
{
|
||||
if (!isInitialized())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto const offset = pieceLoc(piece).byte;
|
||||
return { offset, offset + pieceSize(piece) };
|
||||
}
|
||||
|
||||
struct Location
|
||||
{
|
||||
uint64_t byte = 0;
|
||||
|
|
|
@ -57,7 +57,7 @@ uint64_t tr_completion::computeSizeWhenDone() const
|
|||
}
|
||||
else
|
||||
{
|
||||
size += countHasBytesInBlocks(block_info_->blockSpanForPiece(piece));
|
||||
size += countHasBytesInPiece(piece);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ size_t tr_completion::countMissingBlocksInPiece(tr_piece_index_t piece) const
|
|||
|
||||
size_t tr_completion::countMissingBytesInPiece(tr_piece_index_t piece) const
|
||||
{
|
||||
return block_info_->pieceSize(piece) - countHasBytesInBlocks(block_info_->blockSpanForPiece(piece));
|
||||
return block_info_->pieceSize(piece) - countHasBytesInPiece(piece);
|
||||
}
|
||||
|
||||
tr_completeness tr_completion::status() const
|
||||
|
@ -151,6 +151,7 @@ void tr_completion::addBlock(tr_block_index_t block)
|
|||
blocks_.set(block);
|
||||
size_now_ += block_info_->blockSize(block);
|
||||
|
||||
size_when_done_.reset();
|
||||
has_valid_.reset();
|
||||
}
|
||||
|
||||
|
@ -159,7 +160,7 @@ void tr_completion::setBlocks(tr_bitfield blocks)
|
|||
TR_ASSERT(std::size(blocks_) == std::size(blocks));
|
||||
|
||||
blocks_ = std::move(blocks);
|
||||
size_now_ = countHasBytesInBlocks({ 0, tr_block_index_t(std::size(blocks_)) });
|
||||
size_now_ = countHasBytesInSpan({ 0, block_info_->totalSize() });
|
||||
size_when_done_.reset();
|
||||
has_valid_.reset();
|
||||
}
|
||||
|
@ -187,30 +188,12 @@ void tr_completion::addPiece(tr_piece_index_t piece)
|
|||
void tr_completion::removePiece(tr_piece_index_t piece)
|
||||
{
|
||||
auto const [begin, end] = block_info_->blockSpanForPiece(piece);
|
||||
size_now_ -= countHasBytesInBlocks(block_info_->blockSpanForPiece(piece));
|
||||
size_now_ -= countHasBytesInPiece(piece);
|
||||
size_when_done_.reset();
|
||||
has_valid_.reset();
|
||||
blocks_.unsetSpan(begin, end);
|
||||
}
|
||||
|
||||
uint64_t tr_completion::countHasBytesInBlocks(tr_block_span_t span) const
|
||||
{
|
||||
auto const [begin, end] = span;
|
||||
if (begin >= end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t n = blocks_.count(begin, end);
|
||||
n *= tr_block_info::BlockSize;
|
||||
|
||||
if (end == block_info_->blockCount() && blocks_.test(end - 1))
|
||||
{
|
||||
n -= tr_block_info::BlockSize - block_info_->blockSize(end - 1);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
uint64_t tr_completion::countHasBytesInSpan(tr_byte_span_t span) const
|
||||
{
|
||||
// confirm the span is valid
|
||||
|
|
|
@ -140,7 +140,11 @@ struct tr_completion
|
|||
private:
|
||||
[[nodiscard]] uint64_t computeHasValid() const;
|
||||
[[nodiscard]] uint64_t computeSizeWhenDone() const;
|
||||
[[nodiscard]] uint64_t countHasBytesInBlocks(tr_block_span_t) const;
|
||||
|
||||
[[nodiscard]] uint64_t countHasBytesInPiece(tr_piece_index_t piece) const
|
||||
{
|
||||
return countHasBytesInSpan(block_info_->byteSpanForPiece(piece));
|
||||
}
|
||||
|
||||
torrent_view const* tor_;
|
||||
tr_block_info const* block_info_;
|
||||
|
|
|
@ -471,6 +471,36 @@ TEST_F(CompletionTest, countHasBytesInSpan)
|
|||
EXPECT_EQ(BlockSize * 1.5, completion.countHasBytesInSpan({ BlockSize / 2, BlockSize * 2 + BlockSize / 2 }));
|
||||
}
|
||||
|
||||
TEST_F(CompletionTest, status)
|
||||
TEST_F(CompletionTest, wantNone)
|
||||
{
|
||||
auto torrent = TestTorrent{};
|
||||
auto constexpr TotalSize = uint64_t{ BlockSize * 4096 };
|
||||
auto constexpr PieceSize = uint64_t{ BlockSize * 64 };
|
||||
auto const block_info = tr_block_info{ TotalSize, PieceSize };
|
||||
auto completion = tr_completion(&torrent, &block_info);
|
||||
|
||||
// we have some data
|
||||
completion.addBlock(0);
|
||||
|
||||
// and want nothing
|
||||
for (tr_piece_index_t i = 0, n = block_info.blockCount(); i < n; ++i)
|
||||
{
|
||||
torrent.dnd_pieces.insert(i);
|
||||
}
|
||||
completion.invalidateSizeWhenDone();
|
||||
|
||||
EXPECT_LE(completion.hasTotal(), completion.sizeWhenDone());
|
||||
EXPECT_EQ(completion.hasTotal(), block_info.BlockSize);
|
||||
EXPECT_EQ(completion.sizeWhenDone(), block_info.BlockSize);
|
||||
EXPECT_LE(completion.leftUntilDone(), completion.sizeWhenDone());
|
||||
EXPECT_EQ(completion.leftUntilDone(), 0);
|
||||
|
||||
// but we magically get a block anyway
|
||||
completion.addBlock(1);
|
||||
|
||||
EXPECT_LE(completion.hasTotal(), completion.sizeWhenDone());
|
||||
EXPECT_EQ(completion.hasTotal(), 2 * block_info.BlockSize);
|
||||
EXPECT_EQ(completion.sizeWhenDone(), 2 * block_info.BlockSize);
|
||||
EXPECT_LE(completion.leftUntilDone(), completion.sizeWhenDone());
|
||||
EXPECT_EQ(completion.leftUntilDone(), 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue