* 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:
Charles Kerr 2007-07-25 01:59:46 +00:00
parent a459ba3a74
commit 730d6df742
6 changed files with 61 additions and 73 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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 )

View File

@ -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;

View File

@ -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;

View File

@ -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);
}