mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
refactor: tr_block_info (#2908)
This commit is contained in:
@@ -3,45 +3,72 @@
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <event2/util.h>
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
#include "block-info.h"
|
||||
#include "tr-assert.h"
|
||||
|
||||
void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in)
|
||||
void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in) noexcept
|
||||
{
|
||||
total_size = total_size_in;
|
||||
piece_size = piece_size_in;
|
||||
|
||||
TR_ASSERT(piece_size == 0 || piece_size >= BlockSize);
|
||||
|
||||
if (piece_size == 0)
|
||||
TR_ASSERT(piece_size_in == 0 || piece_size_in >= BlockSize);
|
||||
if (piece_size_in == 0)
|
||||
{
|
||||
*this = {};
|
||||
return;
|
||||
}
|
||||
|
||||
n_pieces = (total_size + piece_size - 1) / piece_size;
|
||||
total_size_ = total_size_in;
|
||||
piece_size_ = piece_size_in;
|
||||
n_pieces_ = (total_size_ + piece_size_ - 1) / piece_size_;
|
||||
n_blocks_ = (total_size_ + BlockSize - 1) / BlockSize;
|
||||
|
||||
auto remainder = total_size % piece_size;
|
||||
final_piece_size = remainder != 0U ? remainder : piece_size;
|
||||
auto remainder = total_size_ % piece_size_;
|
||||
final_piece_size_ = remainder != 0U ? remainder : piece_size_;
|
||||
|
||||
remainder = total_size % BlockSize;
|
||||
final_block_size = remainder != 0U ? remainder : BlockSize;
|
||||
|
||||
n_blocks = (total_size + BlockSize - 1) / BlockSize;
|
||||
|
||||
#ifdef TR_ENABLE_ASSERTS
|
||||
uint64_t t = n_pieces - 1;
|
||||
t *= piece_size;
|
||||
t += final_piece_size;
|
||||
TR_ASSERT(t == total_size);
|
||||
|
||||
t = n_blocks - 1;
|
||||
t *= BlockSize;
|
||||
t += final_block_size;
|
||||
TR_ASSERT(t == total_size);
|
||||
#endif
|
||||
remainder = total_size_ % BlockSize;
|
||||
final_block_size_ = remainder != 0U ? remainder : BlockSize;
|
||||
}
|
||||
|
||||
tr_block_info::Location tr_block_info::byteLoc(uint64_t byte_idx) const noexcept
|
||||
{
|
||||
TR_ASSERT(byte_idx <= totalSize());
|
||||
|
||||
if (!isInitialized())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto loc = Location{};
|
||||
|
||||
loc.byte = byte_idx;
|
||||
|
||||
if (byte_idx == totalSize()) // handle 0-byte files at the end of a torrent
|
||||
{
|
||||
loc.block = blockCount() - 1;
|
||||
loc.piece = pieceCount() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
loc.block = byte_idx / BlockSize;
|
||||
loc.piece = byte_idx / pieceSize();
|
||||
}
|
||||
|
||||
loc.block_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.block } * BlockSize));
|
||||
loc.piece_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.piece } * pieceSize()));
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
tr_block_info::Location tr_block_info::blockLoc(tr_block_index_t block) const noexcept
|
||||
{
|
||||
TR_ASSERT(block < blockCount());
|
||||
|
||||
return byteLoc(uint64_t{ block } * BlockSize);
|
||||
}
|
||||
|
||||
tr_block_info::Location tr_block_info::pieceLoc(tr_piece_index_t piece, uint32_t offset, uint32_t length) const noexcept
|
||||
{
|
||||
TR_ASSERT(piece < pieceCount());
|
||||
|
||||
return byteLoc(uint64_t{ piece } * pieceSize() + offset + length);
|
||||
}
|
||||
|
||||
@@ -9,56 +9,60 @@
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
#include "tr-assert.h"
|
||||
|
||||
struct tr_block_info
|
||||
{
|
||||
private:
|
||||
uint64_t total_size_ = 0;
|
||||
uint64_t piece_size_ = 0;
|
||||
uint64_t n_pieces_ = 0;
|
||||
|
||||
tr_block_index_t n_blocks_ = 0;
|
||||
uint32_t final_block_size_ = 0;
|
||||
uint32_t final_piece_size_ = 0;
|
||||
|
||||
public:
|
||||
static auto constexpr BlockSize = uint32_t{ 1024 * 16 };
|
||||
|
||||
uint64_t total_size = 0;
|
||||
uint64_t piece_size = 0;
|
||||
uint64_t n_pieces = 0;
|
||||
tr_block_info() noexcept = default;
|
||||
|
||||
tr_block_index_t n_blocks = 0;
|
||||
uint32_t final_block_size = 0;
|
||||
uint32_t final_piece_size = 0;
|
||||
|
||||
tr_block_info() = default;
|
||||
tr_block_info(uint64_t total_size_in, uint64_t piece_size_in)
|
||||
tr_block_info(uint64_t total_size_in, uint64_t piece_size_in) noexcept
|
||||
{
|
||||
initSizes(total_size_in, piece_size_in);
|
||||
}
|
||||
|
||||
void initSizes(uint64_t total_size_in, uint64_t piece_size_in);
|
||||
void initSizes(uint64_t total_size_in, uint64_t piece_size_in) noexcept;
|
||||
|
||||
[[nodiscard]] constexpr auto blockCount() const noexcept
|
||||
{
|
||||
return n_blocks;
|
||||
return n_blocks_;
|
||||
}
|
||||
|
||||
// return the number of bytes in `block`
|
||||
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const
|
||||
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const noexcept
|
||||
{
|
||||
return block + 1 == n_blocks ? final_block_size : BlockSize;
|
||||
return block + 1 == n_blocks_ ? final_block_size_ : BlockSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto pieceCount() const noexcept
|
||||
{
|
||||
return n_pieces;
|
||||
return n_pieces_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto pieceSize() const noexcept
|
||||
{
|
||||
return piece_size;
|
||||
return piece_size_;
|
||||
}
|
||||
|
||||
// return the number of bytes in `piece`
|
||||
[[nodiscard]] constexpr auto pieceSize(tr_piece_index_t piece) const noexcept
|
||||
{
|
||||
return piece + 1 == n_pieces ? final_piece_size : pieceSize();
|
||||
return piece + 1 == n_pieces_ ? final_piece_size_ : pieceSize();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr tr_block_span_t blockSpanForPiece(tr_piece_index_t piece) const
|
||||
[[nodiscard]] constexpr auto totalSize() const noexcept
|
||||
{
|
||||
return total_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] tr_block_span_t blockSpanForPiece(tr_piece_index_t piece) const noexcept
|
||||
{
|
||||
if (!isInitialized())
|
||||
{
|
||||
@@ -68,11 +72,6 @@ struct tr_block_info
|
||||
return { pieceLoc(piece).block, pieceLastLoc(piece).block + 1 };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto totalSize() const noexcept
|
||||
{
|
||||
return total_size;
|
||||
}
|
||||
|
||||
struct Location
|
||||
{
|
||||
uint64_t byte = 0;
|
||||
@@ -95,79 +94,23 @@ struct tr_block_info
|
||||
};
|
||||
|
||||
// Location of the first byte in `block`.
|
||||
[[nodiscard]] Location constexpr blockLoc(tr_block_index_t block) const
|
||||
{
|
||||
TR_ASSERT(block < n_blocks);
|
||||
|
||||
return byteLoc(uint64_t{ block } * BlockSize);
|
||||
}
|
||||
|
||||
// Location of the last byte in `block`.
|
||||
[[nodiscard]] Location constexpr blockLastLoc(tr_block_index_t block) const
|
||||
{
|
||||
if (!isInitialized())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return byteLoc(uint64_t{ block } * BlockSize + blockSize(block) - 1);
|
||||
}
|
||||
[[nodiscard]] Location blockLoc(tr_block_index_t block) const noexcept;
|
||||
|
||||
// Location of the first byte (+ optional offset and length) in `piece`
|
||||
[[nodiscard]] Location constexpr pieceLoc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const
|
||||
{
|
||||
TR_ASSERT(piece < n_pieces);
|
||||
|
||||
return byteLoc(uint64_t{ piece } * pieceSize() + offset + length);
|
||||
}
|
||||
|
||||
// Location of the last byte in `piece`.
|
||||
[[nodiscard]] Location constexpr pieceLastLoc(tr_piece_index_t piece) const
|
||||
{
|
||||
if (!isInitialized())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return byteLoc(uint64_t{ piece } * pieceSize() + pieceSize(piece) - 1);
|
||||
}
|
||||
[[nodiscard]] Location pieceLoc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const noexcept;
|
||||
|
||||
// Location of the torrent's nth byte
|
||||
[[nodiscard]] Location constexpr byteLoc(uint64_t byte_idx) const
|
||||
{
|
||||
TR_ASSERT(byte_idx <= total_size);
|
||||
|
||||
if (!isInitialized())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto loc = Location{};
|
||||
|
||||
loc.byte = byte_idx;
|
||||
|
||||
if (byte_idx == totalSize()) // handle 0-byte files at the end of a torrent
|
||||
{
|
||||
loc.block = blockCount() - 1;
|
||||
loc.piece = pieceCount() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
loc.block = byte_idx / BlockSize;
|
||||
loc.piece = byte_idx / pieceSize();
|
||||
}
|
||||
|
||||
loc.block_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.block } * BlockSize));
|
||||
loc.piece_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.piece } * pieceSize()));
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
[[nodiscard]] static uint32_t bestBlockSize(uint64_t piece_size);
|
||||
[[nodiscard]] Location byteLoc(uint64_t byte_idx) const noexcept;
|
||||
|
||||
private:
|
||||
// Location of the last byte in `piece`.
|
||||
[[nodiscard]] Location pieceLastLoc(tr_piece_index_t piece) const
|
||||
{
|
||||
return byteLoc(static_cast<uint64_t>(piece) * pieceSize() + pieceSize(piece) - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool constexpr isInitialized() const noexcept
|
||||
{
|
||||
return piece_size != 0;
|
||||
return piece_size_ != 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ uint64_t tr_completion::computeHasValid() const
|
||||
{
|
||||
uint64_t size = 0;
|
||||
|
||||
for (tr_piece_index_t piece = 0, n = block_info_->n_pieces; piece < n; ++piece)
|
||||
for (tr_piece_index_t piece = 0, n_pieces = block_info_->pieceCount(); piece < n_pieces; ++piece)
|
||||
{
|
||||
if (hasPiece(piece))
|
||||
{
|
||||
@@ -42,12 +42,12 @@ uint64_t tr_completion::computeSizeWhenDone() const
|
||||
{
|
||||
if (hasAll())
|
||||
{
|
||||
return block_info_->total_size;
|
||||
return block_info_->totalSize();
|
||||
}
|
||||
|
||||
// count bytes that we want or that we already have
|
||||
auto size = uint64_t{ 0 };
|
||||
for (tr_piece_index_t piece = 0; piece < block_info_->n_pieces; ++piece)
|
||||
for (tr_piece_index_t piece = 0, n_pieces = block_info_->pieceCount(); piece < n_pieces; ++piece)
|
||||
{
|
||||
if (tor_->pieceIsWanted(piece))
|
||||
{
|
||||
@@ -122,7 +122,7 @@ tr_completeness tr_completion::status() const
|
||||
|
||||
std::vector<uint8_t> tr_completion::createPieceBitfield() const
|
||||
{
|
||||
size_t const n = block_info_->n_pieces;
|
||||
size_t const n = block_info_->pieceCount();
|
||||
auto pieces = tr_bitfield{ n };
|
||||
|
||||
auto flags = std::make_unique<bool[]>(n);
|
||||
@@ -199,9 +199,9 @@ uint64_t tr_completion::countHasBytesInBlocks(tr_block_span_t span) const
|
||||
uint64_t n = blocks_.count(begin, end);
|
||||
n *= tr_block_info::BlockSize;
|
||||
|
||||
if (end == block_info_->n_blocks && blocks_.test(end - 1))
|
||||
if (end == block_info_->blockCount() && blocks_.test(end - 1))
|
||||
{
|
||||
n -= tr_block_info::BlockSize - block_info_->final_block_size;
|
||||
n -= tr_block_info::BlockSize - block_info_->blockSize(end - 1);
|
||||
}
|
||||
|
||||
return n;
|
||||
@@ -210,8 +210,8 @@ uint64_t tr_completion::countHasBytesInBlocks(tr_block_span_t span) const
|
||||
uint64_t tr_completion::countHasBytesInSpan(tr_byte_span_t span) const
|
||||
{
|
||||
// confirm the span is valid
|
||||
span.begin = std::clamp(span.begin, uint64_t{ 0 }, block_info_->total_size);
|
||||
span.end = std::clamp(span.end, uint64_t{ 0 }, block_info_->total_size);
|
||||
span.begin = std::clamp(span.begin, uint64_t{ 0 }, block_info_->totalSize());
|
||||
span.end = std::clamp(span.end, uint64_t{ 0 }, block_info_->totalSize());
|
||||
auto const [begin_byte, end_byte] = span;
|
||||
if (begin_byte >= end_byte)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ struct tr_completion
|
||||
explicit tr_completion(torrent_view const* tor, tr_block_info const* block_info)
|
||||
: tor_{ tor }
|
||||
, block_info_{ block_info }
|
||||
, blocks_{ block_info_->n_blocks }
|
||||
, blocks_{ block_info_->blockCount() }
|
||||
{
|
||||
blocks_.setHasNone();
|
||||
}
|
||||
@@ -67,7 +67,7 @@ struct tr_completion
|
||||
|
||||
[[nodiscard]] bool hasPiece(tr_piece_index_t piece) const
|
||||
{
|
||||
return block_info_->piece_size != 0 && countMissingBlocksInPiece(piece) == 0;
|
||||
return block_info_->pieceSize() != 0 && countMissingBlocksInPiece(piece) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr uint64_t hasTotal() const noexcept
|
||||
@@ -84,7 +84,7 @@ struct tr_completion
|
||||
|
||||
[[nodiscard]] constexpr double percentComplete() const
|
||||
{
|
||||
auto const denom = block_info_->total_size;
|
||||
auto const denom = block_info_->totalSize();
|
||||
return denom ? std::clamp(double(size_now_) / denom, 0.0, 1.0) : 0.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ public:
|
||||
void setPath(tr_file_index_t, std::string_view path);
|
||||
|
||||
void reserve(size_t);
|
||||
tr_file_index_t add(std::string_view path, uint64_t size);
|
||||
void shrinkToFit();
|
||||
void clear() noexcept;
|
||||
tr_file_index_t add(std::string_view path, uint64_t size);
|
||||
|
||||
struct FoundFile : public tr_sys_path_info
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ int readOrWriteBytes(
|
||||
// We didn't find the file that we want to write to.
|
||||
// Let's figure out where it goes so that we can create it.
|
||||
auto const base = tor->currentDir();
|
||||
auto const suffix = tor->session->isIncompleteFileNamingEnabled ? tr_torrent::PartialFileSuffix : ""sv;
|
||||
auto const suffix = tor->session->isIncompleteFileNamingEnabled ? tr_files::PartialFileSuffix : ""sv;
|
||||
found = { {}, tr_pathbuf{ base, "/"sv, tor->fileSubpath(file_index), suffix }, std::size(base) };
|
||||
}
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ std::string_view tr_torrent_metainfo::parseImpl(tr_torrent_metainfo& setme, tr_v
|
||||
|
||||
// do the size and piece size match up?
|
||||
setme.block_info_.initSizes(total_size, piece_size);
|
||||
if (setme.block_info_.n_pieces != std::size(setme.pieces_))
|
||||
if (setme.block_info_.pieceCount() != std::size(setme.pieces_))
|
||||
{
|
||||
return "piece count and file sizes do not match";
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
{
|
||||
return blockInfo().blockSize(block);
|
||||
}
|
||||
[[nodiscard]] constexpr auto blockSpanForPiece(tr_piece_index_t piece) const
|
||||
[[nodiscard]] auto blockSpanForPiece(tr_piece_index_t piece) const
|
||||
{
|
||||
return blockInfo().blockSpanForPiece(piece);
|
||||
}
|
||||
|
||||
@@ -645,7 +645,7 @@ static bool isNewTorrentASeed(tr_torrent* tor)
|
||||
}
|
||||
|
||||
// it's not a new seed if a file is partial
|
||||
if (tr_strvEndsWith(found->filename(), tr_torrent::PartialFileSuffix))
|
||||
if (tr_strvEndsWith(found->filename(), tr_files::PartialFileSuffix))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -2253,7 +2253,7 @@ static void deleteLocalData(tr_torrent const* tor, tr_fileFunc func)
|
||||
|
||||
if (!tr_sys_path_exists(filename.c_str()))
|
||||
{
|
||||
filename += tr_torrent::PartialFileSuffix;
|
||||
filename += tr_files::PartialFileSuffix;
|
||||
|
||||
if (!tr_sys_path_exists(filename.c_str()))
|
||||
{
|
||||
@@ -2863,14 +2863,14 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname)
|
||||
|
||||
if (!tr_sys_path_exists(src.c_str())) /* check for it as a partial */
|
||||
{
|
||||
src += tr_torrent::PartialFileSuffix;
|
||||
src += tr_files::PartialFileSuffix;
|
||||
}
|
||||
|
||||
if (tr_sys_path_exists(src.c_str()))
|
||||
{
|
||||
auto const parent = tr_sys_path_dirname(src);
|
||||
auto const tgt = tr_strvEndsWith(src, tr_torrent::PartialFileSuffix) ?
|
||||
tr_pathbuf{ parent, '/', newname, tr_torrent::PartialFileSuffix } :
|
||||
auto const tgt = tr_strvEndsWith(src, tr_files::PartialFileSuffix) ?
|
||||
tr_pathbuf{ parent, '/', newname, tr_files::PartialFileSuffix } :
|
||||
tr_pathbuf{ parent, '/', newname };
|
||||
|
||||
auto tmp = errno;
|
||||
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
{
|
||||
return metainfo_.blockSize(block);
|
||||
}
|
||||
[[nodiscard]] constexpr auto blockSpanForPiece(tr_piece_index_t piece) const
|
||||
[[nodiscard]] auto blockSpanForPiece(tr_piece_index_t piece) const
|
||||
{
|
||||
return metainfo_.blockSpanForPiece(piece);
|
||||
}
|
||||
@@ -582,8 +582,6 @@ public:
|
||||
torrent's content than any other mime-type. */
|
||||
[[nodiscard]] std::string_view primaryMimeType() const;
|
||||
|
||||
static constexpr std::string_view PartialFileSuffix = std::string_view{ ".part" };
|
||||
|
||||
tr_torrent_metainfo metainfo_;
|
||||
|
||||
// TODO(ckerr): make private once some of torrent.cc's `tr_torrentFoo()` methods are member functions
|
||||
|
||||
@@ -24,18 +24,18 @@ TEST_F(BlockInfoTest, fieldsAreSet)
|
||||
uint64_t constexpr TotalSize = PieceSize * PieceCount;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
EXPECT_EQ(ExpectedBlockSize, info.final_block_size);
|
||||
EXPECT_EQ(PieceCount, info.n_pieces);
|
||||
EXPECT_EQ(PieceSize, info.final_piece_size);
|
||||
EXPECT_EQ(PieceSize, info.piece_size);
|
||||
EXPECT_EQ(TotalSize, info.total_size);
|
||||
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.blockCount() - 1));
|
||||
EXPECT_EQ(PieceCount, info.pieceCount());
|
||||
EXPECT_EQ(PieceSize, info.pieceSize(info.pieceCount() - 1));
|
||||
EXPECT_EQ(PieceSize, info.pieceSize());
|
||||
EXPECT_EQ(TotalSize, info.totalSize());
|
||||
|
||||
info.initSizes(0, 0);
|
||||
EXPECT_EQ(0U, info.final_block_size);
|
||||
EXPECT_EQ(0U, info.n_pieces);
|
||||
EXPECT_EQ(0U, info.final_piece_size);
|
||||
EXPECT_EQ(0U, info.piece_size);
|
||||
EXPECT_EQ(0U, info.total_size);
|
||||
EXPECT_EQ(0U, info.blockSize(info.blockCount() - 1));
|
||||
EXPECT_EQ(0U, info.pieceCount());
|
||||
EXPECT_EQ(0U, info.pieceSize(info.pieceCount() - 1));
|
||||
EXPECT_EQ(0U, info.pieceSize());
|
||||
EXPECT_EQ(0U, info.totalSize());
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, handlesOddSize)
|
||||
@@ -49,11 +49,11 @@ TEST_F(BlockInfoTest, handlesOddSize)
|
||||
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
EXPECT_EQ(1U, info.final_block_size);
|
||||
EXPECT_EQ(1U, info.final_piece_size);
|
||||
EXPECT_EQ(PieceCount, info.n_pieces);
|
||||
EXPECT_EQ(PieceSize, info.piece_size);
|
||||
EXPECT_EQ(TotalSize, info.total_size);
|
||||
EXPECT_EQ(1U, info.blockSize(info.blockCount() - 1));
|
||||
EXPECT_EQ(1U, info.pieceSize(info.pieceCount() - 1));
|
||||
EXPECT_EQ(PieceCount, info.pieceCount());
|
||||
EXPECT_EQ(PieceSize, info.pieceSize());
|
||||
EXPECT_EQ(TotalSize, info.totalSize());
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, pieceSize)
|
||||
@@ -67,8 +67,8 @@ TEST_F(BlockInfoTest, pieceSize)
|
||||
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
EXPECT_EQ(PieceSize, info.pieceSize(info.n_pieces - 2));
|
||||
EXPECT_EQ(1U, info.pieceSize(info.n_pieces - 1));
|
||||
EXPECT_EQ(PieceSize, info.pieceSize(info.pieceCount() - 2));
|
||||
EXPECT_EQ(1U, info.pieceSize(info.pieceCount() - 1));
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, blockSize)
|
||||
@@ -82,8 +82,8 @@ TEST_F(BlockInfoTest, blockSize)
|
||||
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.n_blocks - 2));
|
||||
EXPECT_EQ(1U, info.blockSize(info.n_blocks - 1));
|
||||
EXPECT_EQ(ExpectedBlockSize, info.blockSize(info.blockCount() - 2));
|
||||
EXPECT_EQ(1U, info.blockSize(info.blockCount() - 1));
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, blockSpanForPiece)
|
||||
@@ -142,32 +142,6 @@ TEST_F(BlockInfoTest, blockLoc)
|
||||
EXPECT_EQ(0U, loc.piece_offset);
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, blockLastLoc)
|
||||
{
|
||||
auto info = tr_block_info{};
|
||||
|
||||
uint64_t constexpr ExpectedBlockSize = 1024 * 16;
|
||||
uint64_t constexpr ExpectedBlocksPerPiece = 4;
|
||||
uint64_t constexpr PieceSize = ExpectedBlockSize * ExpectedBlocksPerPiece;
|
||||
uint64_t constexpr PieceCount = 5;
|
||||
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
auto loc = info.blockLastLoc(0);
|
||||
EXPECT_EQ(ExpectedBlockSize - 1, loc.byte);
|
||||
EXPECT_EQ(0U, loc.block);
|
||||
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
|
||||
EXPECT_EQ(0U, loc.piece);
|
||||
EXPECT_EQ(ExpectedBlockSize - 1, loc.piece_offset);
|
||||
|
||||
loc = info.blockLastLoc(info.blockCount() - 1);
|
||||
EXPECT_EQ(info.totalSize() - 1, loc.byte);
|
||||
EXPECT_EQ(info.blockCount() - 1, loc.block);
|
||||
EXPECT_EQ(info.totalSize() - 1 - (ExpectedBlockSize * (info.blockCount() - 1)), loc.block_offset);
|
||||
EXPECT_EQ(info.pieceCount() - 1, loc.piece);
|
||||
EXPECT_EQ(info.totalSize() - 1 - PieceSize * (PieceCount - 1), loc.piece_offset);
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, pieceLoc)
|
||||
{
|
||||
auto info = tr_block_info{};
|
||||
@@ -216,32 +190,6 @@ TEST_F(BlockInfoTest, pieceLoc)
|
||||
EXPECT_EQ(1U, loc.piece_offset);
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, pieceLastLoc)
|
||||
{
|
||||
auto info = tr_block_info{};
|
||||
|
||||
uint64_t constexpr ExpectedBlockSize = 1024 * 16;
|
||||
uint64_t constexpr ExpectedBlocksPerPiece = 4;
|
||||
uint64_t constexpr PieceSize = ExpectedBlockSize * ExpectedBlocksPerPiece;
|
||||
uint64_t constexpr PieceCount = 5;
|
||||
uint64_t constexpr TotalSize = PieceSize * (PieceCount - 1) + 1;
|
||||
info.initSizes(TotalSize, PieceSize);
|
||||
|
||||
auto loc = info.pieceLastLoc(0);
|
||||
EXPECT_EQ(PieceSize - 1, loc.byte);
|
||||
EXPECT_EQ(ExpectedBlocksPerPiece - 1, loc.block);
|
||||
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
|
||||
EXPECT_EQ(0U, loc.piece);
|
||||
EXPECT_EQ(PieceSize - 1, loc.piece_offset);
|
||||
|
||||
loc = info.pieceLastLoc(info.pieceCount() - 1);
|
||||
EXPECT_EQ(info.totalSize() - 1, loc.byte);
|
||||
EXPECT_EQ(info.blockCount() - 1, loc.block);
|
||||
EXPECT_EQ(info.totalSize() - 1 - (ExpectedBlockSize * (info.blockCount() - 1)), loc.block_offset);
|
||||
EXPECT_EQ(info.pieceCount() - 1, loc.piece);
|
||||
EXPECT_EQ(info.totalSize() - 1 - PieceSize * (PieceCount - 1), loc.piece_offset);
|
||||
}
|
||||
|
||||
TEST_F(BlockInfoTest, byteLoc)
|
||||
{
|
||||
auto info = tr_block_info{};
|
||||
|
||||
@@ -66,14 +66,14 @@ TEST_F(CompletionTest, setBlocks)
|
||||
EXPECT_FALSE(completion.hasAll());
|
||||
EXPECT_EQ(0, completion.hasTotal());
|
||||
|
||||
auto bitfield = tr_bitfield{ block_info.n_blocks };
|
||||
auto bitfield = tr_bitfield{ block_info.blockCount() };
|
||||
bitfield.setHasAll();
|
||||
|
||||
// test that the bitfield did get replaced
|
||||
completion.setBlocks(bitfield);
|
||||
EXPECT_TRUE(completion.blocks().hasAll());
|
||||
EXPECT_TRUE(completion.hasAll());
|
||||
EXPECT_EQ(block_info.total_size, completion.hasTotal());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.hasTotal());
|
||||
}
|
||||
|
||||
TEST_F(CompletionTest, hasBlock)
|
||||
@@ -217,21 +217,21 @@ TEST_F(CompletionTest, hasTotalAndValid)
|
||||
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
|
||||
|
||||
// check that adding the final piece adjusts by block_info.final_piece_size
|
||||
completion.setHasPiece(block_info.n_pieces - 1, true);
|
||||
EXPECT_EQ(block_info.final_piece_size, completion.hasTotal());
|
||||
completion.setHasPiece(block_info.pieceCount() - 1, true);
|
||||
EXPECT_EQ(block_info.pieceSize(block_info.pieceCount() - 1), completion.hasTotal());
|
||||
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
|
||||
|
||||
// check that adding a non-final piece adjusts by block_info.piece_size
|
||||
// check that adding a non-final piece adjusts by block_info.pieceSize()
|
||||
completion.setHasPiece(0, true);
|
||||
EXPECT_EQ(block_info.final_piece_size + block_info.piece_size, completion.hasTotal());
|
||||
EXPECT_EQ(block_info.pieceSize(block_info.pieceCount() - 1) + block_info.pieceSize(), completion.hasTotal());
|
||||
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
|
||||
|
||||
// check that removing the final piece adjusts by block_info.final_piece_size
|
||||
completion.setHasPiece(block_info.n_pieces - 1, false);
|
||||
EXPECT_EQ(block_info.piece_size, completion.hasValid());
|
||||
completion.setHasPiece(block_info.pieceCount() - 1, false);
|
||||
EXPECT_EQ(block_info.pieceSize(), completion.hasValid());
|
||||
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
|
||||
|
||||
// check that removing a non-final piece adjusts by block_info.piece_size
|
||||
// check that removing a non-final piece adjusts by block_info.pieceSize()
|
||||
completion.setHasPiece(0, false);
|
||||
EXPECT_EQ(0, completion.hasValid());
|
||||
EXPECT_EQ(completion.hasValid(), completion.hasTotal());
|
||||
@@ -251,41 +251,43 @@ TEST_F(CompletionTest, leftUntilDone)
|
||||
|
||||
// check that the initial blank-slate state has nothing
|
||||
auto completion = tr_completion(&torrent, &block_info);
|
||||
EXPECT_EQ(block_info.total_size, completion.leftUntilDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.leftUntilDone());
|
||||
|
||||
// check that adding the final piece adjusts by block_info.final_piece_size
|
||||
completion.addPiece(block_info.n_pieces - 1);
|
||||
EXPECT_EQ(block_info.total_size - block_info.final_piece_size, completion.leftUntilDone());
|
||||
completion.addPiece(block_info.pieceCount() - 1);
|
||||
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(block_info.pieceCount() - 1), completion.leftUntilDone());
|
||||
|
||||
// check that adding a non-final piece adjusts by block_info.piece_size
|
||||
// check that adding a non-final piece adjusts by block_info.pieceSize()
|
||||
completion.addPiece(0);
|
||||
EXPECT_EQ(block_info.total_size - block_info.final_piece_size - block_info.piece_size, completion.leftUntilDone());
|
||||
EXPECT_EQ(
|
||||
block_info.totalSize() - block_info.pieceSize(block_info.pieceCount() - 1) - block_info.pieceSize(),
|
||||
completion.leftUntilDone());
|
||||
|
||||
// check that removing the final piece adjusts by block_info.final_piece_size
|
||||
completion.removePiece(block_info.n_pieces - 1);
|
||||
EXPECT_EQ(block_info.total_size - block_info.piece_size, completion.leftUntilDone());
|
||||
completion.removePiece(block_info.pieceCount() - 1);
|
||||
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(), completion.leftUntilDone());
|
||||
|
||||
// check that dnd-flagging a piece we already have affects nothing
|
||||
torrent.dnd_pieces.insert(0);
|
||||
completion.invalidateSizeWhenDone();
|
||||
EXPECT_EQ(block_info.total_size - block_info.piece_size, completion.leftUntilDone());
|
||||
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize(), completion.leftUntilDone());
|
||||
torrent.dnd_pieces.clear();
|
||||
completion.invalidateSizeWhenDone();
|
||||
|
||||
// check that dnd-flagging a piece we DON'T already have adjusts by block_info.piece_size
|
||||
// check that dnd-flagging a piece we DON'T already have adjusts by block_info.pieceSize()
|
||||
torrent.dnd_pieces.insert(1);
|
||||
completion.invalidateSizeWhenDone();
|
||||
EXPECT_EQ(block_info.total_size - block_info.piece_size * 2, completion.leftUntilDone());
|
||||
EXPECT_EQ(block_info.totalSize() - block_info.pieceSize() * 2, completion.leftUntilDone());
|
||||
torrent.dnd_pieces.clear();
|
||||
completion.invalidateSizeWhenDone();
|
||||
|
||||
// check that removing a non-final piece adjusts by block_info.piece_size
|
||||
// check that removing a non-final piece adjusts by block_info.pieceSize()
|
||||
completion.removePiece(0);
|
||||
EXPECT_EQ(block_info.total_size, completion.leftUntilDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.leftUntilDone());
|
||||
|
||||
// check that adding a block adjusts by block_info.block_size
|
||||
completion.addBlock(0);
|
||||
EXPECT_EQ(block_info.total_size - tr_block_info::BlockSize, completion.leftUntilDone());
|
||||
EXPECT_EQ(block_info.totalSize() - tr_block_info::BlockSize, completion.leftUntilDone());
|
||||
}
|
||||
|
||||
TEST_F(CompletionTest, sizeWhenDone)
|
||||
@@ -297,13 +299,13 @@ TEST_F(CompletionTest, sizeWhenDone)
|
||||
|
||||
// check that adding or removing blocks or pieces does not affect sizeWhenDone
|
||||
auto completion = tr_completion(&torrent, &block_info);
|
||||
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
|
||||
completion.addBlock(0);
|
||||
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
|
||||
completion.addPiece(0);
|
||||
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
|
||||
completion.removePiece(0);
|
||||
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
|
||||
|
||||
// check that flagging complete pieces as dnd does not affect sizeWhenDone
|
||||
for (size_t i = 0; i < 32; ++i)
|
||||
@@ -312,7 +314,7 @@ TEST_F(CompletionTest, sizeWhenDone)
|
||||
torrent.dnd_pieces.insert(i);
|
||||
}
|
||||
completion.invalidateSizeWhenDone();
|
||||
EXPECT_EQ(block_info.total_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize(), completion.sizeWhenDone());
|
||||
|
||||
// check that flagging missing pieces as dnd does not affect sizeWhenDone
|
||||
for (size_t i = 32; i < 48; ++i)
|
||||
@@ -320,7 +322,7 @@ TEST_F(CompletionTest, sizeWhenDone)
|
||||
torrent.dnd_pieces.insert(i);
|
||||
}
|
||||
completion.invalidateSizeWhenDone();
|
||||
EXPECT_EQ(block_info.total_size - 16 * block_info.piece_size, completion.sizeWhenDone());
|
||||
EXPECT_EQ(block_info.totalSize() - 16 * block_info.pieceSize(), completion.sizeWhenDone());
|
||||
}
|
||||
|
||||
TEST_F(CompletionTest, createPieceBitfield)
|
||||
@@ -335,7 +337,7 @@ TEST_F(CompletionTest, createPieceBitfield)
|
||||
auto buf = std::array<char, 65>{};
|
||||
ASSERT_EQ(std::size(buf), block_info.pieceCount());
|
||||
EXPECT_TRUE(tr_rand_buffer(std::data(buf), std::size(buf)));
|
||||
for (uint64_t i = 0; i < block_info.n_pieces; ++i)
|
||||
for (uint64_t i = 0; i < block_info.pieceCount(); ++i)
|
||||
{
|
||||
if ((buf[i] % 2) != 0)
|
||||
{
|
||||
@@ -346,9 +348,9 @@ TEST_F(CompletionTest, createPieceBitfield)
|
||||
// serialize it to a raw bitfield, read it back into a bitfield,
|
||||
// and test that the new bitfield matches
|
||||
auto const pieces_raw_bitfield = completion.createPieceBitfield();
|
||||
tr_bitfield pieces{ size_t(block_info.n_pieces) };
|
||||
tr_bitfield pieces{ size_t(block_info.pieceCount()) };
|
||||
pieces.setRaw(std::data(pieces_raw_bitfield), std::size(pieces_raw_bitfield));
|
||||
for (uint64_t i = 0; i < block_info.n_pieces; ++i)
|
||||
for (uint64_t i = 0; i < block_info.pieceCount(); ++i)
|
||||
{
|
||||
EXPECT_EQ(completion.hasPiece(i), pieces.test(i));
|
||||
}
|
||||
@@ -372,12 +374,11 @@ TEST_F(CompletionTest, countMissingBytesInPiece)
|
||||
completion.addPiece(0);
|
||||
EXPECT_EQ(0U, completion.countMissingBytesInPiece(0));
|
||||
|
||||
auto const final_piece = block_info.n_pieces - 1;
|
||||
auto const final_block = block_info.n_blocks - 1;
|
||||
auto const final_piece = block_info.pieceCount() - 1;
|
||||
auto const final_block = block_info.blockCount() - 1;
|
||||
EXPECT_EQ(block_info.pieceSize(final_piece), completion.countMissingBytesInPiece(final_piece));
|
||||
completion.addBlock(final_block);
|
||||
EXPECT_EQ(1U, block_info.final_piece_size);
|
||||
EXPECT_EQ(1U, block_info.final_block_size);
|
||||
EXPECT_EQ(1U, block_info.pieceSize(block_info.pieceCount() - 1));
|
||||
EXPECT_TRUE(completion.hasPiece(final_piece));
|
||||
EXPECT_EQ(0U, completion.countMissingBytesInPiece(final_piece));
|
||||
}
|
||||
@@ -393,7 +394,7 @@ TEST_F(CompletionTest, amountDone)
|
||||
// make bins s.t. each bin is a single piece
|
||||
auto bins = std::array<float, TotalSize / PieceSize>{};
|
||||
|
||||
for (tr_piece_index_t piece = 0; piece < block_info.n_pieces; ++piece)
|
||||
for (tr_piece_index_t piece = 0; piece < block_info.pieceCount(); ++piece)
|
||||
{
|
||||
completion.removePiece(piece);
|
||||
}
|
||||
@@ -412,7 +413,7 @@ TEST_F(CompletionTest, amountDone)
|
||||
EXPECT_DOUBLE_EQ(0.0, bins[1]);
|
||||
|
||||
// all pieces
|
||||
for (tr_piece_index_t piece = 0; piece < block_info.n_pieces; ++piece)
|
||||
for (tr_piece_index_t piece = 0; piece < block_info.pieceCount(); ++piece)
|
||||
{
|
||||
completion.addPiece(piece);
|
||||
}
|
||||
@@ -435,7 +436,7 @@ TEST_F(CompletionTest, countHasBytesInSpan)
|
||||
auto completion = tr_completion(&torrent, &block_info);
|
||||
|
||||
// torrent is complete
|
||||
auto blocks = tr_bitfield{ block_info.n_blocks };
|
||||
auto blocks = tr_bitfield{ block_info.blockCount() };
|
||||
blocks.setHasAll();
|
||||
completion.setBlocks(blocks);
|
||||
|
||||
|
||||
@@ -50,9 +50,9 @@ protected:
|
||||
FileSizes[14] + FileSizes[15] + FileSizes[16] ==
|
||||
TotalSize);
|
||||
|
||||
EXPECT_EQ(11, block_info_.n_pieces);
|
||||
EXPECT_EQ(PieceSize, block_info_.piece_size);
|
||||
EXPECT_EQ(TotalSize, block_info_.total_size);
|
||||
EXPECT_EQ(11, block_info_.pieceCount());
|
||||
EXPECT_EQ(PieceSize, block_info_.pieceSize());
|
||||
EXPECT_EQ(TotalSize, block_info_.totalSize());
|
||||
EXPECT_EQ(TotalSize, std::accumulate(std::begin(FileSizes), std::end(FileSizes), uint64_t{ 0 }));
|
||||
}
|
||||
};
|
||||
@@ -123,7 +123,7 @@ TEST_F(FilePieceMapTest, pieceSpan)
|
||||
offset += FileSizes[file];
|
||||
}
|
||||
EXPECT_EQ(TotalSize, offset);
|
||||
EXPECT_EQ(block_info_.n_pieces, fpm.pieceSpan(std::size(FileSizes) - 1).end);
|
||||
EXPECT_EQ(block_info_.pieceCount(), fpm.pieceSpan(std::size(FileSizes) - 1).end);
|
||||
}
|
||||
|
||||
TEST_F(FilePieceMapTest, priorities)
|
||||
@@ -134,14 +134,14 @@ TEST_F(FilePieceMapTest, priorities)
|
||||
|
||||
// make a helper to compare file & piece priorities
|
||||
auto expected_file_priorities = std::vector<tr_priority_t>(n_files, TR_PRI_NORMAL);
|
||||
auto expected_piece_priorities = std::vector<tr_priority_t>(block_info_.n_pieces, TR_PRI_NORMAL);
|
||||
auto expected_piece_priorities = std::vector<tr_priority_t>(block_info_.pieceCount(), TR_PRI_NORMAL);
|
||||
auto const compare_to_expected = [&, this]()
|
||||
{
|
||||
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||
{
|
||||
EXPECT_EQ(int(expected_file_priorities[i]), int(file_priorities.filePriority(i)));
|
||||
}
|
||||
for (tr_piece_index_t i = 0; i < block_info_.n_pieces; ++i)
|
||||
for (tr_piece_index_t i = 0; i < block_info_.pieceCount(); ++i)
|
||||
{
|
||||
EXPECT_EQ(int(expected_piece_priorities[i]), int(file_priorities.piecePriority(i)));
|
||||
}
|
||||
@@ -265,14 +265,14 @@ TEST_F(FilePieceMapTest, wanted)
|
||||
|
||||
// make a helper to compare file & piece priorities
|
||||
auto expected_files_wanted = tr_bitfield(n_files);
|
||||
auto expected_pieces_wanted = tr_bitfield(block_info_.n_pieces);
|
||||
auto expected_pieces_wanted = tr_bitfield(block_info_.pieceCount());
|
||||
auto const compare_to_expected = [&, this]()
|
||||
{
|
||||
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||
{
|
||||
EXPECT_EQ(int(expected_files_wanted.test(i)), int(files_wanted.fileWanted(i)));
|
||||
}
|
||||
for (tr_piece_index_t i = 0; i < block_info_.n_pieces; ++i)
|
||||
for (tr_piece_index_t i = 0; i < block_info_.pieceCount(); ++i)
|
||||
{
|
||||
EXPECT_EQ(int(expected_pieces_wanted.test(i)), int(files_wanted.pieceWanted(i)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user