Feat: add tr_block_info::Location (#2649)

This commit is contained in:
Charles Kerr 2022-02-18 17:17:19 -06:00 committed by GitHub
parent 02b6cc76d1
commit f88f3c4b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 342 additions and 189 deletions

View File

@ -38,9 +38,9 @@ struct tr_block_info
return block_size;
}
// return the number of bytes in `block`
[[nodiscard]] constexpr auto blockSize(tr_block_index_t block) const
{
// how many bytes are in this block?
return block + 1 == n_blocks ? final_block_size : blockSize();
}
@ -49,86 +49,25 @@ struct tr_block_info
return n_pieces;
}
[[nodiscard]] constexpr tr_piece_index_t pieceForBlock(tr_block_index_t block) const
{
// if not initialized yet, don't divide by zero
if (n_blocks_in_piece == 0)
{
return 0;
}
return block / n_blocks_in_piece;
}
[[nodiscard]] constexpr auto pieceSize() const
{
return piece_size;
}
// return the number of bytes in `piece`
[[nodiscard]] constexpr auto pieceSize(tr_piece_index_t piece) const
{
// how many bytes are in this piece?
return piece + 1 == n_pieces ? final_piece_size : pieceSize();
}
[[nodiscard]] constexpr tr_piece_index_t pieceOf(uint64_t offset) const
{
// if not initialized yet, don't divide by zero
if (piece_size == 0)
{
return 0;
}
// handle 0-byte files at the end of a torrent
if (offset == total_size)
{
return n_pieces - 1;
}
return offset / piece_size;
}
[[nodiscard]] constexpr tr_block_index_t blockOf(uint64_t offset) const
{
// if not initialized yet, don't divide by zero
if (block_size == 0)
{
return 0;
}
// handle 0-byte files at the end of a torrent
if (offset == total_size)
{
return n_blocks - 1;
}
return offset / block_size;
}
[[nodiscard]] constexpr uint64_t offset(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
auto ret = piece_size;
ret *= piece;
ret += offset;
ret += length;
return ret;
}
[[nodiscard]] constexpr auto blockOf(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return blockOf(this->offset(piece, offset, length));
}
[[nodiscard]] constexpr tr_block_span_t blockSpanForPiece(tr_piece_index_t piece) const
{
if (block_size == 0)
if (!isInitialized())
{
return {};
}
auto const begin = blockOf(offset(piece, 0));
auto const end = 1 + blockOf(offset(piece, pieceSize(piece) - 1));
return { begin, end };
return { pieceLoc(piece).block, pieceLastLoc(piece).block + 1 };
}
[[nodiscard]] constexpr auto totalSize() const
@ -136,5 +75,95 @@ struct tr_block_info
return total_size;
}
static uint32_t bestBlockSize(uint64_t piece_size);
struct Location
{
uint64_t byte = 0;
tr_piece_index_t piece = 0;
uint32_t piece_offset = 0;
tr_block_index_t block = 0;
uint32_t block_offset = 0;
[[nodiscard]] bool operator==(Location const& that) const
{
return this->byte == that.byte;
}
[[nodiscard]] bool operator<(Location const& that) const
{
return this->byte < that.byte;
}
};
// Location of the first byte in `block`.
[[nodiscard]] Location constexpr blockLoc(tr_block_index_t block) const
{
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);
}
// 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
{
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);
}
// Location of the torrent's nth byte
[[nodiscard]] Location constexpr byteLoc(uint64_t byte) const
{
if (!isInitialized())
{
return {};
}
auto loc = Location{};
loc.byte = byte;
if (byte == totalSize()) // handle 0-byte files at the end of a torrent
{
loc.block = blockCount() - 1;
loc.piece = pieceCount() - 1;
}
else
{
loc.block = byte / blockSize();
loc.piece = byte / 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);
private:
[[nodiscard]] bool constexpr isInitialized() const
{
return n_blocks_in_piece != 0;
}
};

View File

@ -31,6 +31,7 @@ struct cache_block
{
tr_torrent* tor;
// TODO: use tr_block_info::Location
tr_piece_index_t piece;
uint32_t offset;
uint32_t length;
@ -304,9 +305,9 @@ static int cache_block_compare(void const* va, void const* vb)
static struct cache_block* findBlock(tr_cache* cache, tr_torrent* torrent, tr_piece_index_t piece, uint32_t offset)
{
struct cache_block key;
auto key = cache_block{};
key.tor = torrent;
key.block = torrent->blockOf(piece, offset);
key.block = torrent->pieceLoc(piece, offset).block;
return static_cast<struct cache_block*>(tr_ptrArrayFindSorted(&cache->blocks, &key, cache_block_compare));
}
@ -329,7 +330,7 @@ int tr_cacheWriteBlock(
cb->piece = piece;
cb->offset = offset;
cb->length = length;
cb->block = torrent->blockOf(piece, offset);
cb->block = torrent->pieceLoc(piece, offset).block;
cb->evbuf = evbuffer_new();
tr_ptrArrayInsertSorted(&cache->blocks, cb, cache_block_compare);
}

View File

@ -222,9 +222,8 @@ uint64_t tr_completion::countHasBytesInSpan(tr_byte_span_t span) const
}
// get the block span of the byte span
auto const begin_block = block_info_->blockOf(begin_byte);
auto const final_byte = end_byte - 1;
auto const final_block = block_info_->blockOf(final_byte);
auto const begin_block = block_info_->byteLoc(begin_byte).block;
auto const final_block = block_info_->byteLoc(end_byte - 1).block;
// if the entire span is in a single block
if (begin_block == final_block)

View File

@ -26,7 +26,7 @@ void tr_file_piece_map::reset(tr_block_info const& block_info, uint64_t const* f
{
auto const file_size = file_sizes[i];
auto const begin_byte = offset;
auto const begin_piece = block_info.pieceOf(begin_byte);
auto const begin_piece = block_info.byteLoc(begin_byte).piece;
auto end_byte = tr_byte_index_t{};
auto end_piece = tr_piece_index_t{};
@ -34,7 +34,7 @@ void tr_file_piece_map::reset(tr_block_info const& block_info, uint64_t const* f
{
end_byte = offset + file_size;
auto const final_byte = end_byte - 1;
auto const final_piece = block_info.pieceOf(final_byte);
auto const final_piece = block_info.byteLoc(final_byte).piece;
end_piece = final_piece + 1;
}
else

View File

@ -816,7 +816,7 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
break;
case TR_PEER_CLIENT_GOT_REJ:
s->active_requests.remove(s->tor->blockOf(e->pieceIndex, e->offset), peer);
s->active_requests.remove(s->tor->pieceLoc(e->pieceIndex, e->offset).block, peer);
break;
case TR_PEER_CLIENT_GOT_CHOKE:
@ -841,12 +841,11 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
case TR_PEER_CLIENT_GOT_BLOCK:
{
tr_torrent* tor = s->tor;
tr_piece_index_t const p = e->pieceIndex;
tr_block_index_t const block = tor->blockOf(p, e->offset);
cancelAllRequestsForBlock(s, block, peer);
auto* const tor = s->tor;
auto const loc = tor->pieceLoc(e->pieceIndex, e->offset);
cancelAllRequestsForBlock(s, loc.block, peer);
peer->blocksSentToClient.add(tr_time(), 1);
tr_torrentGotBlock(tor, block);
tr_torrentGotBlock(tor, loc.block);
break;
}

View File

@ -363,11 +363,6 @@ public:
return tr_peerIoGetAge(io);
}
[[nodiscard]] bool is_reading_block(tr_block_index_t block) const override
{
return state == AwaitingBt::Piece && block == torrent->blockOf(incoming.blockReq.index, incoming.blockReq.offset);
}
void cancel_block_request(tr_block_index_t block) override
{
protocolSendCancel(this, blockToReq(torrent, block));
@ -1888,8 +1883,8 @@ static int clientGotBlock(tr_peerMsgsImpl* msgs, struct evbuffer* data, struct p
TR_ASSERT(msgs != nullptr);
TR_ASSERT(req != nullptr);
tr_torrent* tor = msgs->torrent;
tr_block_index_t const block = tor->blockOf(req->index, req->offset);
tr_torrent* const tor = msgs->torrent;
auto const block = tor->pieceLoc(req->index, req->offset).block;
if (!requestIsValid(msgs, req))
{
@ -1952,7 +1947,7 @@ static ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
struct evbuffer* in = tr_peerIoGetReadBuffer(io);
size_t const inlen = evbuffer_get_length(in);
dbgmsg(msgs, "canRead: inlen is %zu, msgs->state is %d", inlen, msgs->state);
dbgmsg(msgs, "canRead: inlen is %zu, msgs->state is %d", inlen, int(msgs->state));
auto ret = ReadState{};
if (inlen == 0)

View File

@ -48,7 +48,6 @@ public:
virtual void update_active(tr_direction direction) = 0;
virtual time_t get_connection_age() const = 0;
virtual bool is_reading_block(tr_block_index_t block) const = 0;
virtual void cancel_block_request(tr_block_index_t block) = 0;

View File

@ -16,7 +16,6 @@
#include "magnet-metainfo.h"
struct tr_error;
struct tr_info;
struct tr_torrent_metainfo : public tr_magnet_metainfo
{
@ -45,13 +44,17 @@ public:
{
return blockInfo().blockCount();
}
[[nodiscard]] constexpr auto blockOf(uint64_t offset) const
[[nodiscard]] auto byteLoc(uint64_t byte) const
{
return blockInfo().blockOf(offset);
return blockInfo().byteLoc(byte);
}
[[nodiscard]] constexpr auto blockOf(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
[[nodiscard]] auto blockLoc(tr_block_index_t block) const
{
return blockInfo().blockOf(piece, offset, length);
return blockInfo().blockLoc(block);
}
[[nodiscard]] auto pieceLoc(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return blockInfo().pieceLoc(piece, offset, length);
}
[[nodiscard]] constexpr auto blockSize() const
{
@ -65,22 +68,10 @@ public:
{
return blockInfo().blockSpanForPiece(piece);
}
[[nodiscard]] constexpr auto offset(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return blockInfo().offset(piece, offset, length);
}
[[nodiscard]] constexpr auto pieceCount() const
{
return blockInfo().pieceCount();
}
[[nodiscard]] constexpr auto pieceForBlock(tr_block_index_t block) const
{
return blockInfo().pieceForBlock(block);
}
[[nodiscard]] constexpr auto pieceOf(uint64_t offset) const
{
return blockInfo().pieceOf(offset);
}
[[nodiscard]] constexpr auto pieceSize() const
{
return blockInfo().pieceSize();
@ -147,12 +138,12 @@ public:
return pieces_offset_;
}
std::string torrentFile(std::string_view torrent_dir) const
[[nodiscard]] std::string torrentFile(std::string_view torrent_dir) const
{
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".torrent");
}
std::string resumeFile(std::string_view resume_dir) const
[[nodiscard]] std::string resumeFile(std::string_view resume_dir) const
{
return makeFilename(resume_dir, name(), infoHashString(), BasenameFormat::Hash, ".resume");
}
@ -190,7 +181,7 @@ private:
BasenameFormat format,
std::string_view suffix);
std::string makeFilename(std::string_view dirname, BasenameFormat format, std::string_view suffix) const
[[nodiscard]] std::string makeFilename(std::string_view dirname, BasenameFormat format, std::string_view suffix) const
{
return makeFilename(dirname, name(), infoHashString(), format, suffix);
}
@ -198,7 +189,7 @@ private:
struct file_t
{
public:
std::string const& path() const
[[nodiscard]] std::string const& path() const
{
return path_;
}
@ -208,7 +199,7 @@ private:
path_ = subpath;
}
uint64_t size() const
[[nodiscard]] uint64_t size() const
{
return size_;
}

View File

@ -1977,7 +1977,7 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
{
err = 4;
}
else if (tor->offset(index, offset, length) > tor->totalSize())
else if (tor->pieceLoc(index, offset, length).byte > tor->totalSize())
{
err = 5;
}
@ -2001,14 +2001,14 @@ tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t i)
{
auto const [begin_byte, end_byte] = tor->fpm_.byteSpan(i);
auto const begin_block = tor->blockOf(begin_byte);
auto const begin_block = tor->byteLoc(begin_byte).block;
if (begin_byte >= end_byte)
{
return { begin_block, begin_block };
}
auto const final_byte = end_byte - 1;
auto const end_block = tor->blockOf(final_byte) + 1;
auto const final_block = tor->byteLoc(end_byte - 1).block;
auto const end_block = final_block + 1;
return { begin_block, end_block };
}
@ -2572,21 +2572,21 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
tor->completion.addBlock(block);
tor->setDirty();
tr_piece_index_t const p = tor->pieceForBlock(block);
auto const piece = tor->blockLoc(block).piece;
if (tor->hasPiece(p))
if (tor->hasPiece(piece))
{
if (tor->checkPiece(p))
if (tor->checkPiece(piece))
{
tr_torrentPieceCompleted(tor, p);
tr_torrentPieceCompleted(tor, piece);
}
else
{
uint32_t const n = tor->pieceSize(p);
tr_logAddTorErr(tor, _("Piece %" PRIu32 ", which was just downloaded, failed its checksum test"), p);
uint32_t const n = tor->pieceSize(piece);
tr_logAddTorErr(tor, _("Piece %" PRIu32 ", which was just downloaded, failed its checksum test"), piece);
tor->corruptCur += n;
tor->downloadedCur -= std::min(tor->downloadedCur, uint64_t{ n });
tr_peerMgrGotBadPiece(tor, p);
tr_peerMgrGotBadPiece(tor, piece);
}
}
}

View File

@ -155,13 +155,17 @@ public:
{
return metainfo_.blockCount();
}
[[nodiscard]] constexpr auto blockOf(uint64_t offset) const
[[nodiscard]] auto byteLoc(uint64_t byte) const
{
return metainfo_.blockOf(offset);
return metainfo_.byteLoc(byte);
}
[[nodiscard]] constexpr auto blockOf(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
[[nodiscard]] auto blockLoc(tr_block_index_t block) const
{
return metainfo_.blockOf(piece, offset, length);
return metainfo_.blockLoc(block);
}
[[nodiscard]] auto pieceLoc(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return metainfo_.pieceLoc(piece, offset, length);
}
[[nodiscard]] constexpr auto blockSize() const
{
@ -175,22 +179,10 @@ public:
{
return metainfo_.blockSpanForPiece(piece);
}
[[nodiscard]] constexpr auto offset(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return metainfo_.offset(piece, offset, length);
}
[[nodiscard]] constexpr auto pieceCount() const
{
return metainfo_.pieceCount();
}
[[nodiscard]] constexpr auto pieceForBlock(tr_block_index_t block) const
{
return metainfo_.pieceForBlock(block);
}
[[nodiscard]] constexpr auto pieceOf(uint64_t offset) const
{
return metainfo_.pieceOf(offset);
}
[[nodiscard]] constexpr auto pieceSize() const
{
return metainfo_.pieceSize();
@ -297,7 +289,7 @@ public:
[[nodiscard]] auto fileOffset(tr_piece_index_t piece, uint32_t piece_offset) const
{
return fpm_.fileOffset(this->offset(piece, piece_offset));
return fpm_.fileOffset(this->pieceLoc(piece, piece_offset).byte);
}
/// WANTED
@ -784,9 +776,6 @@ char* tr_torrentBuildPartial(tr_torrent const*, tr_file_index_t fileNo);
tr_peer_id_t const& tr_torrentGetPeerId(tr_torrent* tor);
/** @brief free a metainfo */
void tr_metainfoFree(tr_info* inf);
tr_torrent_metainfo&& tr_ctorStealMetainfo(tr_ctor* ctor);
bool tr_ctorSetMetainfoFromFile(tr_ctor* ctor, std::string const& filename, tr_error** error);

View File

@ -41,10 +41,9 @@ public:
tr_webseed_task(tr_torrent* tor, tr_webseed* webseed_in, tr_block_span_t span)
: webseed{ webseed_in }
, session{ tor->session }
, block{ span.begin }
, piece_index{ tor->pieceForBlock(this->block) }
, piece_offset{ static_cast<uint32_t>(
int64_t{ tor->blockSize() } * this->block - tor->pieceSize() * this->piece_index) }
, block{ span.begin } // TODO(ckerr): just own the loc
, piece_index{ tor->blockLoc(this->block).piece }
, piece_offset{ tor->blockLoc(this->block).piece_offset }
, block_size{ tor->blockSize() }
, length{ (span.end - 1 - span.begin) * tor->blockSize() + tor->blockSize(span.end - 1) }
{
@ -500,7 +499,7 @@ void task_request_next_chunk(tr_webseed_task* t)
auto const piece_size = tor->pieceSize();
uint64_t const remain = t->length - t->blocks_done * tor->blockSize() - evbuffer_get_length(t->content());
auto const total_offset = tor->offset(t->piece_index, t->piece_offset, t->length - remain);
auto const total_offset = tor->pieceLoc(t->piece_index, t->piece_offset, t->length - remain).byte;
tr_piece_index_t const step_piece = total_offset / piece_size;
uint64_t const step_piece_offset = total_offset - uint64_t(piece_size) * step_piece;

View File

@ -65,23 +65,6 @@ TEST_F(BlockInfoTest, handlesOddSize)
EXPECT_EQ(TotalSize, info.total_size);
}
TEST_F(BlockInfoTest, pieceForBlock)
{
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 = 4;
uint64_t constexpr TotalSize = PieceSize * PieceCount;
info.initSizes(TotalSize, PieceSize);
for (uint64_t i = 0; i < info.n_blocks; ++i)
{
EXPECT_EQ((i * ExpectedBlockSize) / PieceSize, info.pieceForBlock(i));
}
}
TEST_F(BlockInfoTest, pieceSize)
{
auto info = tr_block_info{};
@ -112,31 +95,6 @@ TEST_F(BlockInfoTest, blockSize)
EXPECT_EQ(1, info.blockSize(info.n_blocks - 1));
}
TEST_F(BlockInfoTest, offset)
{
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);
EXPECT_EQ(0, info.offset(0, 0));
EXPECT_EQ(1, info.offset(0, 0, 1));
EXPECT_EQ(PieceSize * 2 + 100 + 1, info.offset(2, 100, 1));
EXPECT_EQ(
info.total_size - 1,
info.offset(
info.n_pieces - 1,
((info.n_blocks_in_final_piece - 1) * info.block_size) + info.n_blocks_in_final_piece - 1));
EXPECT_EQ(info.n_blocks_in_piece, info.blockOf(info.offset(1, 0)));
EXPECT_EQ(info.n_blocks_in_piece, info.blockOf(info.offset(1, info.block_size - 1)));
EXPECT_EQ(info.n_blocks_in_piece + 1, info.blockOf(info.offset(1, info.block_size)));
EXPECT_EQ(info.n_blocks - 1, info.blockOf(info.total_size - 1));
}
TEST_F(BlockInfoTest, blockSpanForPiece)
{
auto info = tr_block_info{};
@ -160,3 +118,197 @@ TEST_F(BlockInfoTest, blockSpanForPiece)
EXPECT_EQ(0, info.blockSpanForPiece(0).begin);
EXPECT_EQ(0, info.blockSpanForPiece(0).end);
}
TEST_F(BlockInfoTest, blockLoc)
{
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);
// begin
auto loc = info.blockLoc(0);
EXPECT_EQ(tr_block_info::Location{}, loc);
// third block is halfway through the first piece
loc = info.blockLoc(2);
EXPECT_EQ(ExpectedBlockSize * 2, loc.byte);
EXPECT_EQ(2, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(ExpectedBlockSize * 2, loc.piece_offset);
// second piece aligns with fifth block
loc = info.blockLoc(4);
EXPECT_EQ(PieceSize, loc.byte);
EXPECT_EQ(4, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(1, loc.piece);
EXPECT_EQ(0, 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(0, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
EXPECT_EQ(0, 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{};
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);
// begin
auto loc = info.pieceLoc(0);
EXPECT_EQ(tr_block_info::Location{}, loc);
for (uint64_t i = 0; i < PieceCount; ++i)
{
loc = info.pieceLoc(i);
EXPECT_EQ(info.blockLoc(i * ExpectedBlocksPerPiece), loc);
EXPECT_EQ(PieceSize * i, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece * i, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(i, loc.piece);
EXPECT_EQ(0, loc.piece_offset);
}
loc = info.pieceLoc(0, PieceSize - 1);
EXPECT_EQ(PieceSize - 1, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece - 1, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(PieceSize - 1, loc.piece_offset);
loc = info.pieceLoc(0, PieceSize);
EXPECT_EQ(PieceSize, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(1, loc.piece);
EXPECT_EQ(0, loc.piece_offset);
loc = info.pieceLoc(0, PieceSize + 1);
EXPECT_EQ(PieceSize + 1, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece, loc.block);
EXPECT_EQ(1, loc.block_offset);
EXPECT_EQ(1, loc.piece);
EXPECT_EQ(1, 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(0, 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{};
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.byteLoc(0);
EXPECT_EQ(tr_block_info::Location{}, loc);
loc = info.byteLoc(1);
EXPECT_EQ(1, loc.byte);
EXPECT_EQ(0, loc.block);
EXPECT_EQ(1, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(1, loc.piece_offset);
auto n = ExpectedBlockSize - 1;
loc = info.byteLoc(n);
EXPECT_EQ(n, loc.byte);
EXPECT_EQ(0, loc.block);
EXPECT_EQ(n, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(n, loc.piece_offset);
n = ExpectedBlockSize;
loc = info.byteLoc(n);
EXPECT_EQ(n, loc.byte);
EXPECT_EQ(1, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(n, loc.piece_offset);
n = ExpectedBlockSize + 1;
loc = info.byteLoc(n);
EXPECT_EQ(n, loc.byte);
EXPECT_EQ(1, loc.block);
EXPECT_EQ(1, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(n, loc.piece_offset);
n = PieceSize - 1;
loc = info.byteLoc(n);
EXPECT_EQ(n, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece - 1, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1, loc.block_offset);
EXPECT_EQ(0, loc.piece);
EXPECT_EQ(n, loc.piece_offset);
n = PieceSize;
loc = info.byteLoc(n);
EXPECT_EQ(n, loc.byte);
EXPECT_EQ(ExpectedBlocksPerPiece, loc.block);
EXPECT_EQ(0, loc.block_offset);
EXPECT_EQ(1, loc.piece);
EXPECT_EQ(0, loc.piece_offset);
}