refactor: tr_block_info class (#2210)

* refactor: add tr_block_info with tests
This commit is contained in:
Charles Kerr 2021-11-24 08:48:52 -06:00 committed by GitHub
parent 449b83e340
commit 843e486d2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 442 additions and 216 deletions

View File

@ -49,6 +49,7 @@
558699542570759E00F77A43 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55869925257074EC00F77A43 /* libcurl.tbd */; };
558699602570759F00F77A43 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55869925257074EC00F77A43 /* libcurl.tbd */; };
5586996C2570759F00F77A43 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55869925257074EC00F77A43 /* libcurl.tbd */; };
62F644738FE3D8788EBF73A9 /* block-info.cc in Sources */ = {isa = PBXBuildFile; fileRef = A54D44C6A7AAF131D9AE29F5 /* block-info.cc */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.mm */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
@ -366,6 +367,7 @@
ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; };
ED8A16422735A8AA000D61F9 /* peer-mgr-wishlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */; };
EDBDFA9E25AFCCA60093D9C1 /* evutil_time.c in Sources */ = {isa = PBXBuildFile; fileRef = EDBDFA9D25AFCCA60093D9C1 /* evutil_time.c */; };
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A044CBD8C049AFCBD4DB411 /* block-info.h */; settings = {ATTRIBUTES = (Project, ); }; };
F63480631E1D7274005B9E09 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F63480621E1D7274005B9E09 /* Images.xcassets */; };
/* End PBXBuildFile section */
@ -518,10 +520,6 @@
4D36BA660CA2F00800A63CA5 /* peer-io.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "peer-io.h"; sourceTree = "<group>"; };
4D36BA680CA2F00800A63CA5 /* peer-mgr.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr.cc"; sourceTree = "<group>"; };
4D36BA690CA2F00800A63CA5 /* peer-mgr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "peer-mgr.h"; sourceTree = "<group>"; };
ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-active-requests.h"; sourceTree = "<group>"; };
ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-active-requests.cc"; sourceTree = "<group>"; };
ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; };
ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-wishlist.cc"; sourceTree = "<group>"; };
4D36BA6A0CA2F00800A63CA5 /* peer-msgs.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-msgs.cc"; sourceTree = "<group>"; };
4D36BA6B0CA2F00800A63CA5 /* peer-msgs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "peer-msgs.h"; sourceTree = "<group>"; };
4D36BA6C0CA2F00800A63CA5 /* ptrarray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptrarray.h; sourceTree = "<group>"; };
@ -544,6 +542,7 @@
4DFBC2DD09C0970D00D5C571 /* Torrent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Torrent.h; sourceTree = "<group>"; };
4DFBC2DE09C0970D00D5C571 /* Torrent.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Torrent.mm; sourceTree = "<group>"; };
55869925257074EC00F77A43 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; };
6A044CBD8C049AFCBD4DB411 /* block-info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "block-info.h"; path = "block-info.h"; sourceTree = SOURCE_ROOT; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Transmission.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Transmission.app; sourceTree = BUILT_PRODUCTS_DIR; };
A200B8390A2263BA007BBB1E /* InfoWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoWindowController.h; sourceTree = "<group>"; };
@ -938,6 +937,7 @@
A2FB07F115F8208300933543 /* nl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
A2FB701A0D95CAEA0001F331 /* GroupsController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupsController.h; sourceTree = "<group>"; };
A2FB701B0D95CAEA0001F331 /* GroupsController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GroupsController.mm; sourceTree = "<group>"; };
A54D44C6A7AAF131D9AE29F5 /* block-info.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = block-info.cc; sourceTree = "<group>"; };
BE1183480CE160960002D0F3 /* libminiupnp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminiupnp.a; sourceTree = BUILT_PRODUCTS_DIR; };
BE11834E0CE160C50002D0F3 /* miniupnpc_declspec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = miniupnpc_declspec.h; sourceTree = "<group>"; };
BE11834F0CE160C50002D0F3 /* igd_desc_parse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = igd_desc_parse.h; sourceTree = "<group>"; };
@ -1028,6 +1028,10 @@
CAB35C62252F6F5E00552A55 /* mime-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mime-types.h"; sourceTree = "<group>"; };
E138A9750C04D88F00C5426C /* ProgressGradients.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProgressGradients.h; sourceTree = "<group>"; };
E138A9760C04D88F00C5426C /* ProgressGradients.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ProgressGradients.mm; sourceTree = "<group>"; };
ED8A163B2735A8AA000D61F9 /* peer-mgr-active-requests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-active-requests.h"; sourceTree = "<group>"; };
ED8A163C2735A8AA000D61F9 /* peer-mgr-active-requests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-active-requests.cc"; sourceTree = "<group>"; };
ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; };
ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "peer-mgr-wishlist.cc"; sourceTree = "<group>"; };
EDBDFA9D25AFCCA60093D9C1 /* evutil_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = evutil_time.c; sourceTree = "<group>"; };
F63480621E1D7274005B9E09 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -1374,6 +1378,8 @@
4D1838DC09DEC04A0047D688 /* libtransmission */ = {
isa = PBXGroup;
children = (
A54D44C6A7AAF131D9AE29F5 /* block-info.cc */,
6A044CBD8C049AFCBD4DB411 /* block-info.h */,
C17740D3273A002C00E455D2 /* web-utils.cc */,
C17740D4273A002C00E455D2 /* web-utils.h */,
CAB35C62252F6F5E00552A55 /* mime-types.h */,
@ -1898,6 +1904,7 @@
A2EA52321686AC0D00180493 /* quark.h in Headers */,
A2AF23C916B44FA0003BC59E /* log.h in Headers */,
A23FAE55178BC2950053DC5B /* platform-quota.h in Headers */,
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2493,6 +2500,7 @@
A2EA52311686AC0D00180493 /* quark.cc in Sources */,
A2AF23C816B44FA0003BC59E /* log.cc in Sources */,
A23FAE54178BC2950053DC5B /* platform-quota.cc in Sources */,
62F644738FE3D8788EBF73A9 /* block-info.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -6,27 +6,28 @@ configure_file(
)
set(PROJECT_FILES
announcer.cc
announcer-http.cc
announcer-udp.cc
announcer.cc
bandwidth.cc
bitfield.cc
block-info.cc
blocklist.cc
cache.cc
clients.cc
completion.cc
crypto.cc
crypto-utils.cc
crypto-utils-ccrypto.cc
crypto-utils-cyassl.cc
crypto-utils-fallback.cc
crypto-utils-openssl.cc
crypto-utils-polarssl.cc
crypto-utils.cc
crypto.cc
error.cc
fdlimit.cc
file.cc
file-posix.cc
file-win32.cc
file.cc
handshake.cc
inout.cc
log.cc
@ -36,46 +37,46 @@ set(PROJECT_FILES
natpmp.cc
net.cc
peer-io.cc
peer-mgr.cc
peer-mgr-active-requests.cc
peer-mgr-wishlist.cc
peer-mgr.cc
peer-msgs.cc
platform.cc
platform-quota.cc
platform.cc
port-forwarding.cc
ptrarray.cc
quark.cc
resume.cc
rpcimpl.cc
rpc-server.cc
session.cc
rpcimpl.cc
session-id.cc
session.cc
stats.cc
subprocess-posix.cc
subprocess-win32.cc
stats.cc
torrent.cc
torrent-ctor.cc
torrent-magnet.cc
tr-dht.cc
trevent.cc
torrent.cc
tr-assert.cc
tr-dht.cc
tr-getopt.cc
tr-lpd.cc
tr-udp.cc
tr-utp.cc
trevent.cc
upnp.cc
utils.cc
variant-benc.cc
variant.cc
variant-json.cc
variant.cc
verify.cc
watchdir.cc
watchdir-generic.cc
watchdir-inotify.cc
watchdir-kqueue.cc
watchdir-win32.cc
web.cc
watchdir.cc
web-utils.cc
web.cc
webseed.cc
)
@ -147,6 +148,7 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
announcer.h
bandwidth.h
bitfield.h
block-info.h
blocklist.h
cache.h
clients.h
@ -164,9 +166,9 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
net.h
peer-common.h
peer-io.h
peer-mgr.h
peer-mgr-active-requests.h
peer-mgr-wishlist.h
peer-mgr.h
peer-msgs.h
peer-socket.h
platform-quota.h

View File

@ -0,0 +1,87 @@
/*
* This file Copyright (C) 2007-2014 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#include <algorithm>
#include <iterator>
#include <event2/util.h>
#include "transmission.h"
#include "block-info.h"
// Decide on a block size. Constraints:
// (1) most clients decline requests over 16 KiB
// (2) pieceSize must be a multiple of block size
uint32_t tr_block_info::bestBlockSize(uint64_t piece_size)
{
uint32_t b = piece_size;
auto constexpr MaxBlockSize = uint32_t{ 1024 * 16 };
while (b > MaxBlockSize)
{
b /= 2U;
}
if (b == 0 || piece_size % b != 0) // not cleanly divisible
{
return 0;
}
return b;
}
void tr_block_info::initSizes(uint64_t total_size_in, uint64_t piece_size_in)
{
total_size = total_size_in;
piece_size = piece_size_in;
block_size = bestBlockSize(piece_size);
if (piece_size == 0 || block_size == 0)
{
return;
}
n_pieces = (total_size + piece_size - 1) / piece_size;
auto remainder = total_size % piece_size;
final_piece_size = remainder ? remainder : piece_size;
remainder = total_size % block_size;
final_block_size = remainder ? remainder : block_size;
if (block_size != 0)
{
n_blocks = (total_size + block_size - 1) / block_size;
n_blocks_in_piece = piece_size / block_size;
n_blocks_in_final_piece = (final_piece_size + block_size - 1) / block_size;
}
#ifdef TR_ENABLE_ASSERTS
// check our work
if (block_size != 0)
{
TR_ASSERT(piece_size % block_size == 0);
}
uint64_t t = n_pieces - 1;
t *= piece_size;
t += final_piece_size;
TR_ASSERT(t == total_size);
t = n_blocks - 1;
t *= block_size;
t += final_block_size;
TR_ASSERT(t == total_size);
t = n_pieces - 1;
t *= n_blocks_in_piece;
t += n_blocks_in_final_piece;
TR_ASSERT(t == n_blocks);
#endif
}

View File

@ -0,0 +1,93 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#pragma once
#ifndef __TRANSMISSION__
#error only libtransmission should #include this header.
#endif
#include "transmission.h"
#include "metainfo.h"
struct tr_block_info
{
uint64_t total_size = 0;
uint64_t piece_size = 0;
uint64_t n_pieces = 0;
tr_block_index_t n_blocks = 0;
tr_block_index_t n_blocks_in_piece = 0;
tr_block_index_t n_blocks_in_final_piece = 0;
uint32_t block_size = 0;
uint32_t final_block_size = 0;
uint32_t final_piece_size = 0;
tr_block_info() = default;
tr_block_info(uint64_t total_size, uint64_t piece_size)
{
initSizes(total_size, piece_size);
}
void initSizes(uint64_t total_size_in, uint64_t piece_size_in);
constexpr tr_piece_index_t pieceForBlock(tr_block_index_t block) const
{
return n_blocks_in_piece ? block / n_blocks_in_piece : 0;
}
constexpr uint32_t countBytesInPiece(tr_piece_index_t piece) const
{
// how many bytes are in this piece?
return piece + 1 == n_pieces ? final_piece_size : piece_size;
}
constexpr uint32_t countBytesInBlock(tr_block_index_t block) const
{
// how many bytes are in this block?
return block + 1 == n_blocks ? final_block_size : block_size;
}
constexpr tr_block_index_t blockOf(uint64_t offset) const
{
return offset / block_size;
}
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;
}
constexpr tr_block_index_t blockOf(tr_piece_index_t piece, uint32_t offset, uint32_t length = 0) const
{
return blockOf(this->offset(piece, offset, length));
}
constexpr tr_block_range_t blockRangeForPiece(tr_piece_index_t piece) const
{
if (block_size == 0)
{
return {};
}
uint64_t offset = piece_size;
offset *= piece;
tr_block_index_t const first_block = offset / block_size;
offset += countBytesInPiece(piece) - 1;
tr_block_index_t const final_block = offset / block_size;
return { first_block, final_block };
}
static uint32_t bestBlockSize(uint64_t piece_size);
};

View File

@ -309,7 +309,7 @@ static struct cache_block* findBlock(tr_cache* cache, tr_torrent* torrent, tr_pi
{
struct cache_block key;
key.tor = torrent;
key.block = _tr_block(torrent, piece, offset);
key.block = torrent->blockOf(piece, offset);
return static_cast<struct cache_block*>(tr_ptrArrayFindSorted(&cache->blocks, &key, cache_block_compare));
}
@ -332,7 +332,7 @@ int tr_cacheWriteBlock(
cb->piece = piece;
cb->offset = offset;
cb->length = length;
cb->block = _tr_block(torrent, piece, offset);
cb->block = torrent->blockOf(piece, offset);
cb->evbuf = evbuffer_new();
tr_ptrArrayInsertSorted(&cache->blocks, cb, cache_block_compare);
}

View File

@ -29,7 +29,7 @@ static void tr_cpReset(tr_completion* cp)
void tr_cpConstruct(tr_completion* cp, tr_torrent* tor)
{
cp->tor = tor;
cp->blockBitfield = new tr_bitfield(tor->blockCount);
cp->blockBitfield = new tr_bitfield(tor->n_blocks);
tr_cpReset(cp);
}
@ -42,12 +42,12 @@ void tr_cpBlockInit(tr_completion* cp, tr_bitfield const& b)
// set sizeNow
cp->sizeNow = cp->blockBitfield->count();
TR_ASSERT(cp->sizeNow <= cp->tor->blockCount);
cp->sizeNow *= cp->tor->blockSize;
TR_ASSERT(cp->sizeNow <= cp->tor->n_blocks);
cp->sizeNow *= cp->tor->block_size;
if (b.test(cp->tor->blockCount - 1))
if (b.test(cp->tor->n_blocks - 1))
{
cp->sizeNow -= (cp->tor->blockSize - cp->tor->lastBlockSize);
cp->sizeNow -= (cp->tor->block_size - cp->tor->final_block_size);
}
TR_ASSERT(cp->sizeNow <= cp->tor->info.totalSize);
@ -80,12 +80,12 @@ tr_completeness tr_cpGetStatus(tr_completion const* cp)
void tr_cpPieceRem(tr_completion* cp, tr_piece_index_t piece)
{
tr_torrent const* tor = cp->tor;
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, piece);
for (tr_block_index_t i = first; i <= last; ++i)
auto const [first, last] = cp->tor->blockRangeForPiece(piece);
for (tr_block_index_t block = first; block <= last; ++block)
{
if (tr_cpBlockIsComplete(cp, i))
if (tr_cpBlockIsComplete(cp, block))
{
cp->sizeNow -= tr_torBlockCountBytes(tor, i);
cp->sizeNow -= tor->countBytesInBlock(block);
}
}
@ -96,7 +96,7 @@ void tr_cpPieceRem(tr_completion* cp, tr_piece_index_t piece)
void tr_cpPieceAdd(tr_completion* cp, tr_piece_index_t piece)
{
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, piece);
auto const [first, last] = cp->tor->blockRangeForPiece(piece);
for (tr_block_index_t i = first; i <= last; ++i)
{
tr_cpBlockAdd(cp, i);
@ -109,10 +109,10 @@ void tr_cpBlockAdd(tr_completion* cp, tr_block_index_t block)
if (!tr_cpBlockIsComplete(cp, block))
{
tr_piece_index_t const piece = tr_torBlockPiece(cp->tor, block);
tr_piece_index_t const piece = cp->tor->pieceForBlock(block);
cp->blockBitfield->set(block);
cp->sizeNow += tr_torBlockCountBytes(tor, block);
cp->sizeNow += tor->countBytesInBlock(block);
cp->haveValidIsDirty = true;
cp->sizeWhenDoneIsDirty = cp->sizeWhenDoneIsDirty || tor->pieceIsDnd(piece);
@ -136,7 +136,7 @@ uint64_t tr_cpHaveValid(tr_completion const* ccp)
{
if (tr_cpPieceIsComplete(ccp, i))
{
size += tr_torPieceCountBytes(tor, i);
size += tor->countBytesInPiece(i);
}
}
@ -165,7 +165,7 @@ uint64_t tr_cpSizeWhenDone(tr_completion const* ccp)
for (tr_piece_index_t p = 0; p < inf->pieceCount; ++p)
{
uint64_t n = 0;
uint64_t const pieceSize = tr_torPieceCountBytes(tor, p);
uint64_t const pieceSize = tor->countBytesInPiece(p);
if (!tor->pieceIsDnd(p))
{
@ -173,18 +173,17 @@ uint64_t tr_cpSizeWhenDone(tr_completion const* ccp)
}
else
{
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, p);
auto const [first, last] = cp->tor->blockRangeForPiece(p);
n = cp->blockBitfield->count(first, last + 1);
n *= cp->tor->blockSize;
n *= cp->tor->block_size;
if (last == cp->tor->blockCount - 1 && cp->blockBitfield->test(last))
if (last == cp->tor->n_blocks - 1 && cp->blockBitfield->test(last))
{
n -= cp->tor->blockSize - cp->tor->lastBlockSize;
n -= cp->tor->block_size - cp->tor->final_block_size;
}
}
TR_ASSERT(n <= tr_torPieceCountBytes(tor, p));
TR_ASSERT(n <= tor->countBytesInPiece(p));
size += n;
}
}
@ -222,7 +221,7 @@ void tr_cpGetAmountDone(tr_completion const* cp, float* tab, int tabCount)
else
{
tr_piece_index_t const piece = (tr_piece_index_t)i * interval;
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, piece);
auto const [first, last] = cp->tor->blockRangeForPiece(piece);
tab[i] = cp->blockBitfield->count(first, last + 1) / (float)(last + 1 - first);
}
}
@ -235,7 +234,7 @@ size_t tr_cpMissingBlocksInPiece(tr_completion const* cp, tr_piece_index_t piece
return 0;
}
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, piece);
auto const [first, last] = cp->tor->blockRangeForPiece(piece);
return (last + 1 - first) - cp->blockBitfield->count(first, last + 1);
}
@ -246,8 +245,8 @@ size_t tr_cpMissingBytesInPiece(tr_completion const* cp, tr_piece_index_t piece)
return 0;
}
size_t const pieceByteSize = tr_torPieceCountBytes(cp->tor, piece);
auto const [first, last] = tr_torGetPieceBlockRange(cp->tor, piece);
size_t const pieceByteSize = cp->tor->countBytesInPiece(piece);
auto const [first, last] = cp->tor->blockRangeForPiece(piece);
auto haveBytes = size_t{};
if (first != last)
@ -256,12 +255,12 @@ size_t tr_cpMissingBytesInPiece(tr_completion const* cp, tr_piece_index_t piece)
It's faster to handle the last block separately because its size
needs to be checked separately. */
haveBytes = cp->blockBitfield->count(first, last);
haveBytes *= cp->tor->blockSize;
haveBytes *= cp->tor->block_size;
}
if (cp->blockBitfield->test(last)) /* handle the last block */
{
haveBytes += tr_torBlockCountBytes(cp->tor, last);
haveBytes += cp->tor->countBytesInBlock(last);
}
TR_ASSERT(haveBytes <= pieceByteSize);

View File

@ -260,12 +260,12 @@ static std::optional<tr_sha1_digest_t> recalculateHash(tr_torrent* tor, tr_piece
TR_ASSERT(tor != nullptr);
TR_ASSERT(piece < tor->info.pieceCount);
auto bytes_left = size_t{ tr_torPieceCountBytes(tor, piece) };
auto bytes_left = size_t{ tor->countBytesInPiece(piece) };
auto offset = uint32_t{};
tr_ioPrefetch(tor, piece, offset, bytes_left);
auto sha = tr_sha1_init();
auto buffer = std::vector<uint8_t>(tor->blockSize);
auto buffer = std::vector<uint8_t>(tor->block_size);
while (bytes_left != 0)
{
size_t const len = std::min(bytes_left, std::size(buffer));

View File

@ -225,7 +225,7 @@ tr_peer::tr_peer(tr_torrent const* tor, peer_atom* atom_in)
: session{ tor->session }
, atom{ atom_in }
, swarm{ tor->swarm }
, blame{ tor->blockCount }
, blame{ tor->n_blocks }
, have{ tor->info.pieceCount }
{
}
@ -554,7 +554,7 @@ static void updateEndgame(tr_swarm* s)
{
/* we consider ourselves to be in endgame if the number of bytes
we've got requested is >= the number of bytes left to download */
s->endgame = uint64_t(std::size(s->active_requests)) * s->tor->blockSize >= tr_torrentGetLeftUntilDone(s->tor);
s->endgame = uint64_t(std::size(s->active_requests)) * s->tor->block_size >= tr_torrentGetLeftUntilDone(s->tor);
}
std::vector<tr_block_range_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_peer* peer, size_t numwant)
@ -596,7 +596,7 @@ std::vector<tr_block_range_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_
tr_block_range_t blockRange(tr_piece_index_t piece) const override
{
return tr_torGetPieceBlockRange(torrent_, piece);
return torrent_->blockRangeForPiece(piece);
}
tr_piece_index_t countAllPieces() const override
@ -725,14 +725,14 @@ static void peerSuggestedPiece(tr_swarm* /*s*/, tr_peer* /*peer*/, tr_piece_inde
/* request the blocks that we don't have in this piece */
{
tr_torrent const* tor = t->tor;
auto const [first, last] = tr_torGetPieceBlockRange(t->tor, pieceIndex);
auto const [first, last] = tor->blockRangeForPiece(pieceIndex);
for (tr_block_index_t b = first; b <= last; ++b)
{
if (tr_torrentBlockIsComplete(tor, b))
{
uint32_t const offset = getBlockOffsetInPiece(tor, b);
uint32_t const length = tr_torBlockCountBytes(tor, b);
uint32_t const length = tor->countBytesInBlock(b);
tr_peerMsgsAddRequest(peer->msgs, pieceIndex, offset, length);
incrementPieceRequests(t, pieceIndex);
}
@ -762,7 +762,7 @@ void tr_peerMgrPieceCompleted(tr_torrent* tor, tr_piece_index_t p)
if (pieceCameFromPeers) /* webseed downloads don't belong in announce totals */
{
tr_announcerAddBytes(tor, TR_ANN_DOWN, tr_torPieceCountBytes(tor, p));
tr_announcerAddBytes(tor, TR_ANN_DOWN, tor->countBytesInPiece(p));
}
/* bookkeeping */
@ -824,7 +824,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(_tr_block(s->tor, e->pieceIndex, e->offset), peer);
s->active_requests.remove(s->tor->blockOf(e->pieceIndex, e->offset), peer);
break;
case TR_PEER_CLIENT_GOT_CHOKE:
@ -851,7 +851,7 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
{
tr_torrent* tor = s->tor;
tr_piece_index_t const p = e->pieceIndex;
tr_block_index_t const block = _tr_block(tor, p, e->offset);
tr_block_index_t const block = tor->blockOf(p, e->offset);
cancelAllRequestsForBlock(s, block, peer);
peer->blocksSentToClient.add(tr_time(), 1);
tr_torrentGotBlock(tor, block);
@ -1243,7 +1243,7 @@ tr_pex* tr_peerMgrCompact6ToPex(
void tr_peerMgrGotBadPiece(tr_torrent* tor, tr_piece_index_t pieceIndex)
{
tr_swarm* s = tor->swarm;
uint32_t const byteCount = tr_torPieceCountBytes(tor, pieceIndex);
uint32_t const byteCount = tor->countBytesInPiece(pieceIndex);
for (int i = 0, n = tr_ptrArraySize(&s->peers); i != n; ++i)
{

View File

@ -358,7 +358,7 @@ public:
bool is_reading_block(tr_block_index_t block) const override
{
return state == AwaitingBtPiece && block == _tr_block(torrent, incoming.blockReq.index, incoming.blockReq.offset);
return state == AwaitingBtPiece && block == torrent->blockOf(incoming.blockReq.index, incoming.blockReq.offset);
}
void cancel_block_request(tr_block_index_t block) override
@ -1885,7 +1885,7 @@ static int clientGotBlock(tr_peerMsgsImpl* msgs, struct evbuffer* data, struct p
TR_ASSERT(req != nullptr);
tr_torrent* tor = msgs->torrent;
tr_block_index_t const block = _tr_block(tor, req->index, req->offset);
tr_block_index_t const block = tor->blockOf(req->index, req->offset);
if (!requestIsValid(msgs, req))
{
@ -1893,9 +1893,9 @@ static int clientGotBlock(tr_peerMsgsImpl* msgs, struct evbuffer* data, struct p
return EBADMSG;
}
if (req->length != tr_torBlockCountBytes(msgs->torrent, block))
if (req->length != msgs->torrent->countBytesInBlock(block))
{
dbgmsg(msgs, "wrong block size -- expected %u, got %d", tr_torBlockCountBytes(msgs->torrent, block), req->length);
dbgmsg(msgs, "wrong block size -- expected %u, got %d", msgs->torrent->countBytesInBlock(block), req->length);
return EMSGSIZE;
}
@ -2027,7 +2027,7 @@ static void updateDesiredRequestCount(tr_peerMsgsImpl* msgs)
* many requests we should send to this peer */
size_t constexpr Floor = 32;
size_t constexpr Seconds = RequestBufSecs;
size_t const estimated_blocks_in_period = (rate_Bps * Seconds) / torrent->blockSize;
size_t const estimated_blocks_in_period = (rate_Bps * Seconds) / torrent->block_size;
size_t const ceil = msgs->reqq ? *msgs->reqq : 250;
msgs->desired_request_count = std::clamp(estimated_blocks_in_period, Floor, ceil);
}
@ -2194,7 +2194,7 @@ static size_t fillOutputBuffer(tr_peerMsgsImpl* msgs, time_t now)
*** Data Blocks
**/
if (tr_peerIoGetWriteBufferSpace(msgs->io, now) >= msgs->torrent->blockSize && popNextRequest(msgs, &req))
if (tr_peerIoGetWriteBufferSpace(msgs->io, now) >= msgs->torrent->block_size && popNextRequest(msgs, &req))
{
--msgs->prefetchCount;

View File

@ -615,7 +615,7 @@ static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
/// COMPLETION
auto blocks = tr_bitfield{ tor->blockCount };
auto blocks = tr_bitfield{ tor->n_blocks };
char const* err = nullptr;
auto sv = std::string_view{};
tr_variant const* const b = tr_variantDictFind(prog, TR_KEY_blocks);

View File

@ -721,63 +721,10 @@ uint32_t tr_getBlockSize(uint32_t pieceSize)
return b;
}
static void refreshCurrentDir(tr_torrent* tor);
static void torrentInitFromInfo(tr_torrent* tor)
{
tr_info const* const info = &tor->info;
tor->blockSize = tr_getBlockSize(info->pieceSize);
if (info->pieceSize != 0)
{
tor->lastPieceSize = (uint32_t)(info->totalSize % info->pieceSize);
}
if (tor->lastPieceSize == 0)
{
tor->lastPieceSize = info->pieceSize;
}
if (tor->blockSize != 0)
{
tor->lastBlockSize = info->totalSize % tor->blockSize;
}
if (tor->lastBlockSize == 0)
{
tor->lastBlockSize = tor->blockSize;
}
tor->blockCount = tor->blockSize != 0 ? (info->totalSize + tor->blockSize - 1) / tor->blockSize : 0;
tor->blockCountInPiece = tor->blockSize != 0 ? info->pieceSize / tor->blockSize : 0;
tor->blockCountInLastPiece = tor->blockSize != 0 ? (tor->lastPieceSize + tor->blockSize - 1) / tor->blockSize : 0;
#ifdef TR_ENABLE_ASSERTS
/* check our work */
if (tor->blockSize != 0)
{
TR_ASSERT(info->pieceSize % tor->blockSize == 0);
}
uint64_t t = info->pieceCount - 1;
t *= info->pieceSize;
t += tor->lastPieceSize;
TR_ASSERT(t == info->totalSize);
t = tor->blockCount - 1;
t *= tor->blockSize;
t += tor->lastBlockSize;
TR_ASSERT(t == info->totalSize);
t = info->pieceCount - 1;
t *= tor->blockCountInPiece;
t += tor->blockCountInLastPiece;
TR_ASSERT(t == (uint64_t)tor->blockCount);
#endif
tor->initSizes(tor->info.totalSize, tor->info.pieceSize);
tr_cpConstruct(&tor->completion, tor);
tr_torrentInitFilePieces(tor);
}
@ -836,6 +783,8 @@ static void callScriptIfEnabled(tr_torrent const* tor, TrScript type)
}
}
static void refreshCurrentDir(tr_torrent* tor);
static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
{
auto const lock = tor->unique_lock();
@ -1374,21 +1323,21 @@ static uint64_t countFileBytesCompleted(tr_torrent const* tor, tr_file_index_t i
// the first block
if (tr_torrentBlockIsComplete(tor, first))
{
total += tor->blockSize - f.offset % tor->blockSize;
total += tor->block_size - f.offset % tor->block_size;
}
// the middle blocks
if (first + 1 < last)
{
uint64_t u = tor->completion.blockBitfield->count(first + 1, last);
u *= tor->blockSize;
u *= tor->block_size;
total += u;
}
// the last block
if (tr_torrentBlockIsComplete(tor, last))
{
total += f.offset + f.length - (uint64_t)tor->blockSize * last;
total += f.offset + f.length - (uint64_t)tor->block_size * last;
}
return total;
@ -2372,33 +2321,12 @@ void tr_torrentGetBlockLocation(
uint32_t* length)
{
uint64_t pos = block;
pos *= tor->blockSize;
pos *= tor->block_size;
*piece = pos / tor->info.pieceSize;
uint64_t piece_begin = tor->info.pieceSize;
piece_begin *= *piece;
*offset = pos - piece_begin;
*length = tr_torBlockCountBytes(tor, block);
}
tr_block_index_t _tr_block(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset)
{
TR_ASSERT(tr_isTorrent(tor));
tr_block_index_t ret = 0;
if (tor->blockSize > 0)
{
ret = index;
ret *= tor->info.pieceSize / tor->blockSize;
ret += offset / tor->blockSize;
}
else
{
tr_logAddTorErr(tor, "Cannot calculate block number when blockSize is zero");
TR_ASSERT(tor->blockSize > 0);
}
return ret;
*length = tor->countBytesInBlock(block);
}
bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset, uint32_t length)
@ -2415,7 +2343,7 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
{
err = 2;
}
else if (offset + length > tr_torPieceCountBytes(tor, index))
else if (offset + length > tor->countBytesInPiece(index))
{
err = 3;
}
@ -2459,25 +2387,14 @@ tr_block_range_t tr_torGetFileBlockRange(tr_torrent const* tor, tr_file_index_t
tr_file const* f = &tor->info.files[file];
uint64_t offset = f->offset;
tr_block_index_t const first = offset / tor->blockSize;
tr_block_index_t const first = offset / tor->block_size;
if (f->length == 0)
{
return { first, first };
}
offset += f->length - 1;
tr_block_index_t const last = offset / tor->blockSize;
return { first, last };
}
tr_block_range_t tr_torGetPieceBlockRange(tr_torrent const* tor, tr_piece_index_t const piece)
{
uint64_t offset = tor->info.pieceSize;
offset *= piece;
tr_block_index_t const first = offset / tor->blockSize;
offset += tr_torPieceCountBytes(tor, piece) - 1;
tr_block_index_t const last = offset / tor->blockSize;
tr_block_index_t const last = offset / tor->block_size;
return { first, last };
}
@ -3159,7 +3076,7 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
tr_cpBlockAdd(&tor->completion, block);
tr_torrentSetDirty(tor);
tr_piece_index_t const p = tr_torBlockPiece(tor, block);
tr_piece_index_t const p = tor->pieceForBlock(block);
if (tr_torrentPieceIsComplete(tor, p))
{
@ -3169,7 +3086,7 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
}
else
{
uint32_t const n = tr_torPieceCountBytes(tor, p);
uint32_t const n = tor->countBytesInPiece(p);
tr_logAddTorErr(tor, _("Piece %" PRIu32 ", which was just downloaded, failed its checksum test"), p);
tor->corruptCur += n;
tor->downloadedCur -= std::min(tor->downloadedCur, uint64_t{ n });
@ -3179,7 +3096,7 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
}
else
{
uint32_t const n = tr_torBlockCountBytes(tor, block);
uint32_t const n = tor->countBytesInBlock(block);
tor->downloadedCur -= std::min(tor->downloadedCur, uint64_t{ n });
tr_logAddTorDbg(tor, "we have this block already...");
}

View File

@ -19,8 +19,11 @@
#include <unordered_set>
#include <vector>
#include "transmission.h"
#include "bandwidth.h"
#include "bitfield.h"
#include "block-info.h"
#include "completion.h"
#include "file.h"
#include "quark.h"
@ -76,10 +79,6 @@ tr_torrent* tr_torrentFindFromObfuscatedHash(tr_session* session, uint8_t const*
bool tr_torrentIsPieceTransferAllowed(tr_torrent const* torrent, tr_direction direction);
#define tr_block(a, b) _tr_block(tor, a, b)
tr_block_index_t _tr_block(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset);
bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset, uint32_t length);
uint64_t tr_pieceOffset(tr_torrent const* tor, tr_piece_index_t index, uint32_t offset, uint32_t length);
@ -93,8 +92,6 @@ void tr_torrentGetBlockLocation(
tr_block_range_t tr_torGetFileBlockRange(tr_torrent const* tor, tr_file_index_t const file);
tr_block_range_t tr_torGetPieceBlockRange(tr_torrent const* tor, tr_piece_index_t const piece);
void tr_torrentInitFilePriority(tr_torrent* tor, tr_file_index_t fileIndex, tr_priority_t priority);
void tr_torrentCheckSeedLimit(tr_torrent* tor);
@ -128,7 +125,7 @@ tr_torrent_activity tr_torrentGetActivity(tr_torrent const* tor);
struct tr_incomplete_metadata;
/** @brief Torrent object */
struct tr_torrent
struct tr_torrent : public tr_block_info
{
public:
void setLocation(
@ -320,16 +317,6 @@ public:
* This pointer will be equal to downloadDir or incompleteDir */
char const* currentDir;
/* How many bytes we ask for per request */
uint32_t blockSize;
tr_block_index_t blockCount;
uint32_t lastBlockSize;
uint32_t lastPieceSize;
uint32_t blockCountInPiece;
uint32_t blockCountInLastPiece;
struct tr_completion completion;
tr_completeness completeness;
@ -428,24 +415,6 @@ private:
mutable std::vector<tr_sha1_digest_t> piece_checksums_;
};
/* what piece index is this block in? */
constexpr tr_piece_index_t tr_torBlockPiece(tr_torrent const* tor, tr_block_index_t const block)
{
return block / tor->blockCountInPiece;
}
/* how many bytes are in this piece? */
constexpr uint32_t tr_torPieceCountBytes(tr_torrent const* tor, tr_piece_index_t const piece)
{
return piece + 1 == tor->info.pieceCount ? tor->lastPieceSize : tor->info.pieceSize;
}
/* how many bytes are in this block? */
constexpr uint32_t tr_torBlockCountBytes(tr_torrent const* tor, tr_block_index_t const block)
{
return block + 1 == tor->blockCount ? tor->lastBlockSize : tor->blockSize;
}
static inline bool tr_torrentExists(tr_session const* session, uint8_t const* torrentHash)
{
return tr_torrentFindFromHash((tr_session*)session, torrentHash) != nullptr;

View File

@ -70,7 +70,7 @@ static bool verifyTorrent(tr_torrent* tor, bool* stopFlag)
}
/* figure out how much we can read this pass */
uint64_t leftInPiece = tr_torPieceCountBytes(tor, pieceIndex) - piecePos;
uint64_t leftInPiece = tor->countBytesInPiece(pieceIndex) - piecePos;
uint64_t leftInFile = file->length - filePos;
uint64_t bytesThisPass = std::min(leftInFile, leftInPiece);
bytesThisPass = std::min(bytesThisPass, uint64_t{ buflen });

View File

@ -147,7 +147,7 @@ static void fire_client_got_rejs(tr_torrent* tor, tr_webseed* w, tr_block_index_
{
if (i == count)
{
e.length = tr_torBlockCountBytes(tor, block + count - 1);
e.length = tor->countBytesInBlock(block + count - 1);
}
publish(w, &e);
@ -165,7 +165,7 @@ static void fire_client_got_blocks(tr_torrent* tor, tr_webseed* w, tr_block_inde
{
if (i == count)
{
e.length = tr_torBlockCountBytes(tor, block + count - 1);
e.length = tor->countBytesInBlock(block + count - 1);
}
publish(w, &e);
@ -206,7 +206,7 @@ static void write_block_func(void* vdata)
auto* const tor = tr_torrentFindFromId(data->session, data->torrent_id);
if (tor != nullptr)
{
uint32_t const block_size = tor->blockSize;
uint32_t const block_size = tor->block_size;
uint32_t len = evbuffer_get_length(buf);
uint32_t const offset_end = data->block_offset + len;
tr_cache* cache = data->session->cache;
@ -371,12 +371,12 @@ static void on_idle(tr_webseed* w)
task->session = tor->session;
task->webseed = w;
task->block = first;
task->piece_index = tr_torBlockPiece(tor, first);
task->piece_offset = tor->blockSize * first - tor->info.pieceSize * task->piece_index;
task->length = (last - first) * tor->blockSize + tr_torBlockCountBytes(tor, last);
task->piece_index = tor->pieceForBlock(first);
task->piece_offset = tor->block_size * first - tor->info.pieceSize * task->piece_index;
task->length = (last - first) * tor->block_size + tor->countBytesInBlock(last);
task->blocks_done = 0;
task->response_code = 0;
task->block_size = tor->blockSize;
task->block_size = tor->block_size;
task->content = evbuffer_new();
evbuffer_add_cb(task->content, on_content_changed, task);
w->tasks.insert(task);
@ -425,7 +425,7 @@ static void web_response_func(
if (!success)
{
tr_block_index_t const blocks_remain = (t->length + tor->blockSize - 1) / tor->blockSize - t->blocks_done;
tr_block_index_t const blocks_remain = (t->length + tor->block_size - 1) / tor->block_size - t->blocks_done;
if (blocks_remain != 0)
{
@ -448,7 +448,7 @@ static void web_response_func(
}
else
{
uint32_t const bytes_done = t->blocks_done * tor->blockSize;
uint32_t const bytes_done = t->blocks_done * tor->block_size;
uint32_t const buf_len = evbuffer_get_length(t->content);
if (bytes_done + buf_len < t->length)
@ -508,7 +508,7 @@ static void task_request_next_chunk(struct tr_webseed_task* t)
auto& urls = t->webseed->file_urls;
tr_info const* inf = tr_torrentInfo(tor);
uint64_t const remain = t->length - t->blocks_done * tor->blockSize - evbuffer_get_length(t->content);
uint64_t const remain = t->length - t->blocks_done * tor->block_size - evbuffer_get_length(t->content);
uint64_t const total_offset = tr_pieceOffset(tor, t->piece_index, t->piece_offset, t->length - remain);
tr_piece_index_t const step_piece = total_offset / inf->pieceSize;

View File

@ -1,5 +1,6 @@
add_executable(libtransmission-test
bitfield-test.cc
block-info-test.cc
blocklist-test.cc
clients-test.cc
copy-test.cc
@ -14,9 +15,9 @@ add_executable(libtransmission-test
makemeta-test.cc
metainfo-test.cc
move-test.cc
peer-msgs-test.cc
peer-mgr-wishlist-test.cc
peer-mgr-active-requests-test.cc
peer-mgr-wishlist-test.cc
peer-msgs-test.cc
quark-test.cc
rename-test.cc
rpc-test.cc

View File

@ -0,0 +1,150 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#include <cstdint>
#include "transmission.h"
#include "block-info.h"
#include "gtest/gtest.h"
using BlockInfoTest = ::testing::Test;
TEST_F(BlockInfoTest, fieldsAreSet)
{
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);
EXPECT_EQ(ExpectedBlockSize, info.block_size);
EXPECT_EQ(ExpectedBlockSize, info.final_block_size);
EXPECT_EQ(ExpectedBlocksPerPiece, info.n_blocks_in_final_piece);
EXPECT_EQ(ExpectedBlocksPerPiece, info.n_blocks_in_piece);
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);
}
TEST_F(BlockInfoTest, handlesOddSize)
{
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(1, info.final_block_size);
EXPECT_EQ(1, info.final_piece_size);
EXPECT_EQ(1, info.n_blocks_in_final_piece);
EXPECT_EQ(ExpectedBlockSize, info.block_size);
EXPECT_EQ(ExpectedBlocksPerPiece, info.n_blocks_in_piece);
EXPECT_EQ(PieceCount, info.n_pieces);
EXPECT_EQ(PieceSize, info.piece_size);
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, countBytesInPiece)
{
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(PieceSize, info.countBytesInPiece(info.n_pieces - 2));
EXPECT_EQ(1, info.countBytesInPiece(info.n_pieces - 1));
}
TEST_F(BlockInfoTest, countBytesInBlock)
{
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(ExpectedBlockSize, info.countBytesInBlock(info.n_blocks - 2));
EXPECT_EQ(1, info.countBytesInBlock(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, blockRangeForPiece)
{
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.blockRangeForPiece(0).first);
EXPECT_EQ(3, info.blockRangeForPiece(0).last);
EXPECT_EQ(12, info.blockRangeForPiece(3).first);
EXPECT_EQ(15, info.blockRangeForPiece(3).last);
EXPECT_EQ(16, info.blockRangeForPiece(4).first);
EXPECT_EQ(16, info.blockRangeForPiece(4).last);
}

View File

@ -80,28 +80,28 @@ TEST_P(IncompleteDirTest, incompleteDir)
auto const test_incomplete_dir_threadfunc = [](void* vdata) noexcept
{
auto* data = static_cast<TestIncompleteDirData*>(vdata);
tr_cacheWriteBlock(data->session->cache, data->tor, 0, data->offset, data->tor->blockSize, data->buf);
tr_cacheWriteBlock(data->session->cache, data->tor, 0, data->offset, data->tor->block_size, data->buf);
tr_torrentGotBlock(data->tor, data->block);
data->done = true;
};
// now finish writing it
{
char* zero_block = tr_new0(char, tor->blockSize);
char* zero_block = tr_new0(char, tor->block_size);
struct TestIncompleteDirData data = {};
data.session = session_;
data.tor = tor;
data.buf = evbuffer_new();
auto const [first, last] = tr_torGetPieceBlockRange(tor, data.pieceIndex);
auto const [first, last] = tor->blockRangeForPiece(data.pieceIndex);
for (tr_block_index_t block_index = first; block_index <= last; ++block_index)
{
evbuffer_add(data.buf, zero_block, tor->blockSize);
evbuffer_add(data.buf, zero_block, tor->block_size);
data.block = block_index;
data.done = false;
data.offset = data.block * tor->blockSize;
data.offset = data.block * tor->block_size;
tr_runInEventThread(session_, test_incomplete_dir_threadfunc, &data);
auto const test = [&data]()