* fix overflow error from earlier today. (this was the crash talked about in IRC)
* fix long-standing error that occurred when pieceSize isn't evenly divisible by blockSize * speed up and macro-ize piece-to-block conversions
This commit is contained in:
parent
a459ba3a74
commit
730d6df742
|
@ -40,17 +40,8 @@ struct tr_completion_s
|
|||
|
||||
/* a block is complete if and only if we have it */
|
||||
int * completeBlocks;
|
||||
|
||||
/* rather than calculating these over and over again in loops,
|
||||
just calculate them once */
|
||||
int nBlocksInPiece;
|
||||
int nBlocksInLastPiece;
|
||||
};
|
||||
|
||||
#define tr_cpCountBlocks(cp,piece) (piece==cp->tor->info.pieceCount-1 \
|
||||
? cp->nBlocksInLastPiece \
|
||||
: cp->nBlocksInPiece)
|
||||
|
||||
tr_completion_t * tr_cpInit( tr_torrent_t * tor )
|
||||
{
|
||||
tr_completion_t * cp;
|
||||
|
@ -62,10 +53,6 @@ tr_completion_t * tr_cpInit( tr_torrent_t * tor )
|
|||
cp->pieceBitfield = tr_bitfieldNew( tor->info.pieceCount );
|
||||
cp->completeBlocks = tr_new( int, tor->info.pieceCount );
|
||||
|
||||
cp->nBlocksInLastPiece = tr_pieceCountBlocks( tor->info.pieceCount - 1 );
|
||||
cp->nBlocksInPiece = tor->info.pieceCount==1 ? cp->nBlocksInLastPiece
|
||||
: tr_pieceCountBlocks( 0 );
|
||||
|
||||
tr_cpReset( cp );
|
||||
|
||||
return cp;
|
||||
|
@ -99,7 +86,7 @@ int tr_cpPieceHasAllBlocks( const tr_completion_t * cp, int piece )
|
|||
|
||||
int tr_cpPieceIsComplete( const tr_completion_t * cp, int piece )
|
||||
{
|
||||
return cp->completeBlocks[piece] >= tr_cpCountBlocks(cp,piece);
|
||||
return cp->completeBlocks[piece] >= TR_BLOCKS_IN_PIECE(cp->tor,piece);
|
||||
}
|
||||
|
||||
const tr_bitfield_t * tr_cpPieceBitfield( const tr_completion_t * cp )
|
||||
|
@ -110,8 +97,8 @@ const tr_bitfield_t * tr_cpPieceBitfield( const tr_completion_t * cp )
|
|||
void tr_cpPieceAdd( tr_completion_t * cp, int piece )
|
||||
{
|
||||
const tr_torrent_t * tor = cp->tor;
|
||||
const int n_blocks = tr_cpCountBlocks( cp, piece );
|
||||
const int startBlock = tr_pieceStartBlock( piece );
|
||||
const int n_blocks = TR_BLOCKS_IN_PIECE(tor,piece);
|
||||
const int startBlock = TOR_PIECE_FIRST_BLOCK(tor,piece);
|
||||
const int endBlock = startBlock + n_blocks;
|
||||
|
||||
cp->completeBlocks[piece] = n_blocks;
|
||||
|
@ -122,8 +109,8 @@ void tr_cpPieceAdd( tr_completion_t * cp, int piece )
|
|||
void tr_cpPieceRem( tr_completion_t * cp, int piece )
|
||||
{
|
||||
const tr_torrent_t * tor = cp->tor;
|
||||
const int n_blocks = tr_cpCountBlocks( cp, piece );
|
||||
const int startBlock = tr_pieceStartBlock( piece );
|
||||
const int n_blocks = TR_BLOCKS_IN_PIECE(tor,piece);
|
||||
const int startBlock = TOR_PIECE_FIRST_BLOCK(tor,piece);
|
||||
const int endBlock = startBlock + n_blocks;
|
||||
|
||||
assert( cp != NULL );
|
||||
|
@ -132,7 +119,7 @@ void tr_cpPieceRem( tr_completion_t * cp, int piece )
|
|||
assert( 0 <= startBlock );
|
||||
assert( startBlock < tor->blockCount );
|
||||
assert( startBlock <= endBlock );
|
||||
assert( endBlock < tor->blockCount );
|
||||
assert( endBlock <= tor->blockCount );
|
||||
|
||||
cp->completeBlocks[piece] = 0;
|
||||
tr_bitfieldRemRange ( cp->blockBitfield, startBlock, endBlock );
|
||||
|
@ -157,21 +144,15 @@ int tr_cpBlockIsComplete( const tr_completion_t * cp, int block )
|
|||
|
||||
void tr_cpBlockAdd( tr_completion_t * cp, int block )
|
||||
{
|
||||
const tr_torrent_t * tor;
|
||||
|
||||
assert( cp != NULL );
|
||||
assert( cp->tor != NULL );
|
||||
assert( 0 <= block );
|
||||
|
||||
tor = cp->tor;
|
||||
const tr_torrent_t * tor = cp->tor;
|
||||
|
||||
if( !tr_cpBlockIsComplete( cp, block ) )
|
||||
{
|
||||
const int piece = block / cp->nBlocksInPiece;
|
||||
const int piece = TOR_BLOCK_PIECE(tor, block);
|
||||
|
||||
++cp->completeBlocks[piece];
|
||||
|
||||
if( cp->completeBlocks[piece] == tr_cpCountBlocks( cp, piece ) )
|
||||
if( cp->completeBlocks[piece] == TR_BLOCKS_IN_PIECE(tor,piece) )
|
||||
tr_bitfieldAdd( cp->pieceBitfield, piece );
|
||||
|
||||
tr_bitfieldAdd( cp->blockBitfield, block );
|
||||
|
@ -204,7 +185,7 @@ float tr_cpPercentBlocksInPiece( const tr_completion_t * cp, int piece )
|
|||
{
|
||||
assert( cp != NULL );
|
||||
|
||||
return cp->completeBlocks[piece] / (double)tr_cpCountBlocks( cp, piece );
|
||||
return cp->completeBlocks[piece] / (double)TR_BLOCKS_IN_PIECE(cp->tor,piece);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -213,8 +194,8 @@ tr_cpMissingBlocksForPiece( const tr_completion_t * cp, int piece )
|
|||
int i;
|
||||
int n;
|
||||
const tr_torrent_t * tor = cp->tor;
|
||||
const int start = tr_pieceStartBlock( piece );
|
||||
const int end = start + tr_cpCountBlocks( cp, piece );
|
||||
const int start = TOR_PIECE_FIRST_BLOCK(tor,piece);
|
||||
const int end = start + TR_BLOCKS_IN_PIECE(tor,piece);
|
||||
|
||||
n = 0;
|
||||
for( i = start; i < end; ++i )
|
||||
|
@ -228,8 +209,8 @@ int tr_cpMissingBlockInPiece( const tr_completion_t * cp, int piece )
|
|||
{
|
||||
int i;
|
||||
const tr_torrent_t * tor = cp->tor;
|
||||
const int start = tr_pieceStartBlock( piece );
|
||||
const int end = start + tr_cpCountBlocks( cp, piece );
|
||||
const int start = TOR_PIECE_FIRST_BLOCK(tor,piece);
|
||||
const int end = start + TR_BLOCKS_IN_PIECE(tor,piece);
|
||||
|
||||
for( i = start; i < end; ++i )
|
||||
if( !tr_cpBlockIsComplete( cp, i ) && !cp->blockDownloaders[i] )
|
||||
|
@ -279,7 +260,7 @@ tr_cpLeftUntilComplete ( const tr_completion_t * cp )
|
|||
info = &tor->info;
|
||||
for( i=0; i<info->pieceCount; ++i )
|
||||
if( !tr_cpPieceIsComplete( cp, i ) )
|
||||
b += ( tr_cpCountBlocks( cp, i ) - cp->completeBlocks[ i ] );
|
||||
b += ( TR_BLOCKS_IN_PIECE(tor,i) - cp->completeBlocks[ i ] );
|
||||
|
||||
b *= tor->blockSize;
|
||||
|
||||
|
@ -305,7 +286,7 @@ tr_cpLeftUntilDone ( const tr_completion_t * cp )
|
|||
|
||||
for( i=0; i<info->pieceCount; ++i )
|
||||
if( !tr_cpPieceIsComplete( cp, i ) && !info->pieces[i].dnd )
|
||||
b += ( tr_cpCountBlocks( cp, i ) - cp->completeBlocks[ i ] );
|
||||
b += ( TR_BLOCKS_IN_PIECE(tor,i) - cp->completeBlocks[ i ] );
|
||||
|
||||
b *= tor->blockSize;
|
||||
|
||||
|
|
|
@ -121,18 +121,19 @@ void tr_torrentReaderUnlock ( const tr_torrent_t * );
|
|||
void tr_torrentWriterLock ( tr_torrent_t * );
|
||||
void tr_torrentWriterUnlock ( tr_torrent_t * );
|
||||
|
||||
#define tr_blockPiece(a) _tr_blockPiece(tor,a)
|
||||
int _tr_blockPiece( const tr_torrent_t * tor, int block );
|
||||
|
||||
#define TOR_BLOCK_PIECE(tor,block) \
|
||||
( (block) / ( (tor)->info.pieceSize / (tor)->blockSize ) )
|
||||
|
||||
#define TOR_PIECE_FIRST_BLOCK(tor,piece) \
|
||||
( (tor)->info.pieces[(piece)].firstBlock )
|
||||
|
||||
#define TR_BLOCKS_IN_PIECE(tor,piece) \
|
||||
( (tor)->info.pieces[(piece)].blockCount )
|
||||
|
||||
#define tr_blockSize(a) _tr_blockSize(tor,a)
|
||||
int _tr_blockSize( const tr_torrent_t * tor, int block );
|
||||
|
||||
#define tr_pieceCountBlocks(a) _tr_pieceCountBlocks(tor,a)
|
||||
int _tr_pieceCountBlocks( const tr_torrent_t * tor, int piece );
|
||||
|
||||
#define tr_pieceStartBlock(a) _tr_pieceStartBlock(tor,a)
|
||||
int _tr_pieceStartBlock( const tr_torrent_t * tor, int piece );
|
||||
|
||||
#define tr_pieceSize(a) _tr_pieceSize(tor,a)
|
||||
int _tr_pieceSize( const tr_torrent_t * tor, int piece );
|
||||
|
||||
|
|
|
@ -680,8 +680,8 @@ writeEnd:
|
|||
for( ; openSlots>0 && piecesLeft>0; --piecesLeft, p=(p+1)%poolSize )
|
||||
{
|
||||
const int piece = pool[p];
|
||||
const int firstBlock = tr_pieceStartBlock( piece );
|
||||
const int n = tr_pieceCountBlocks( piece );
|
||||
const int firstBlock = TOR_PIECE_FIRST_BLOCK( tor, piece );
|
||||
const int n = TR_BLOCKS_IN_PIECE( tor, piece );
|
||||
const int end = firstBlock + n;
|
||||
int block;
|
||||
for( block=firstBlock; block<end; ++block )
|
||||
|
|
|
@ -168,7 +168,28 @@ tr_torrentInitFilePieces( tr_torrent_t * tor )
|
|||
}
|
||||
|
||||
for( i=0; i<tor->info.pieceCount; ++i )
|
||||
tor->info.pieces[i].priority = calculatePiecePriority( tor, i );
|
||||
{
|
||||
tr_piece_t * piece = tor->info.pieces + i;
|
||||
uint64_t lastByte;
|
||||
int lastBlock;
|
||||
if( i == (tor->info.pieceCount-1))
|
||||
lastByte = tor->info.totalSize;
|
||||
else {
|
||||
lastByte = i + 1;
|
||||
lastByte *= tor->info.pieceSize;
|
||||
--lastByte;
|
||||
}
|
||||
lastBlock = lastByte / tor->blockSize;
|
||||
|
||||
piece->priority = calculatePiecePriority( tor, i );
|
||||
piece->firstBlock = i * (tor->info.pieceSize / tor->blockSize);
|
||||
piece->blockCount = lastBlock + 1 - piece->firstBlock;
|
||||
|
||||
assert( 0 <= piece->firstBlock );
|
||||
assert( piece->firstBlock <= lastBlock );
|
||||
assert( lastBlock < tor->blockCount );
|
||||
assert( piece->firstBlock + piece->blockCount <= tor->blockCount );
|
||||
}
|
||||
}
|
||||
|
||||
static void torrentThreadLoop( void * );
|
||||
|
@ -190,8 +211,6 @@ torrentRealInit( tr_handle_t * h,
|
|||
|
||||
tor->destination = tr_strdup( destination );
|
||||
|
||||
tr_torrentInitFilePieces( tor );
|
||||
|
||||
tor->handle = h;
|
||||
tor->key = h->key;
|
||||
tor->azId = h->azId;
|
||||
|
@ -213,6 +232,8 @@ torrentRealInit( tr_handle_t * h,
|
|||
tor->blockSize;
|
||||
tor->completion = tr_cpInit( tor );
|
||||
|
||||
tr_torrentInitFilePieces( tor );
|
||||
|
||||
tor->thread = THREAD_EMPTY;
|
||||
tr_rwInit( &tor->lock );
|
||||
|
||||
|
@ -685,8 +706,8 @@ fileBytesCompleted ( const tr_torrent_t * tor, int fileIndex )
|
|||
assert( (int)firstBlock < tor->blockCount );
|
||||
assert( (int)lastBlock < tor->blockCount );
|
||||
assert( firstBlock <= lastBlock );
|
||||
assert( tr_blockPiece( firstBlock ) == file->firstPiece );
|
||||
assert( tr_blockPiece( lastBlock ) == file->lastPiece );
|
||||
assert( TOR_BLOCK_PIECE( tor, firstBlock ) == file->firstPiece );
|
||||
assert( TOR_BLOCK_PIECE( tor, lastBlock ) == file->lastPiece );
|
||||
|
||||
if( firstBlock == lastBlock )
|
||||
{
|
||||
|
@ -1367,16 +1388,6 @@ tr_torrentSetFileDLs ( tr_torrent_t * tor,
|
|||
****
|
||||
***/
|
||||
|
||||
int _tr_blockPiece( const tr_torrent_t * tor, int block )
|
||||
{
|
||||
return (block * tor->blockSize) / tor->info.pieceSize;
|
||||
}
|
||||
|
||||
int _tr_pieceStartBlock( const tr_torrent_t * tor, int piece )
|
||||
{
|
||||
return (piece * tor->info.pieceSize) / tor->blockSize;
|
||||
}
|
||||
|
||||
int _tr_blockSize( const tr_torrent_t * tor, int block )
|
||||
{
|
||||
const tr_info_t * inf = &tor->info;
|
||||
|
@ -1391,17 +1402,6 @@ int _tr_blockSize( const tr_torrent_t * tor, int block )
|
|||
return dummy;
|
||||
}
|
||||
|
||||
int _tr_pieceCountBlocks( const tr_torrent_t * tor, int piece )
|
||||
{
|
||||
const tr_info_t * inf = &tor->info;
|
||||
if( piece < inf->pieceCount - 1 ||
|
||||
!( tor->blockCount % ( inf->pieceSize / tor->blockSize ) ) )
|
||||
{
|
||||
return inf->pieceSize / tor->blockSize;
|
||||
}
|
||||
return tor->blockCount % ( inf->pieceSize / tor->blockSize );
|
||||
}
|
||||
|
||||
int _tr_pieceSize( const tr_torrent_t * tor, int piece )
|
||||
{
|
||||
const tr_info_t * inf = &tor->info;
|
||||
|
|
|
@ -514,7 +514,9 @@ typedef struct tr_piece_s
|
|||
{
|
||||
uint8_t hash[SHA_DIGEST_LENGTH]; /* pieces hash */
|
||||
int8_t priority; /* TR_PRI_HIGH, _NORMAL, or _LOW */
|
||||
int8_t dnd; /* nonzero if the piece shouldn't be downloaded */
|
||||
int8_t dnd; /* nonzero if the piece shouldn't be downloaded */
|
||||
int firstBlock; /* this piece's first byte is in this block */
|
||||
int blockCount; /* number of blocks this piece is in */
|
||||
}
|
||||
tr_piece_t;
|
||||
|
||||
|
|
|
@ -574,7 +574,7 @@ tr_bitfieldIsEmpty( const tr_bitfield_t * bitfield )
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define BIN(nth) (nth>>3)
|
||||
#define BIN(nth) ((nth>>3))
|
||||
#define BIT(nth) (1<<(7-(nth%8)))
|
||||
|
||||
int
|
||||
|
@ -587,6 +587,10 @@ tr_bitfieldHas( const tr_bitfield_t * bitfield,
|
|||
void
|
||||
tr_bitfieldAdd( tr_bitfield_t * bitfield, size_t nth )
|
||||
{
|
||||
assert( bitfield != NULL );
|
||||
assert( 0 <= nth);
|
||||
assert( 0 <= BIN(nth) );
|
||||
assert( BIN(nth) < bitfield->len );
|
||||
bitfield->bits[ BIN(nth) ] |= BIT(nth);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue