void tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block ) { const tr_torrent * tor = cp->tor; if( !tr_cpBlockIsComplete( cp, block ) ) { const tr_piece_index_t piece = tr_torBlockPiece( tor, block ); const int blockSize = tr_torBlockCountBytes( tor, block ); ++cp->completeBlocks[piece]; if( tr_cpPieceIsComplete( cp, piece ) ) tr_bitfieldAdd( cp->pieceBitfield, piece ); tr_bitfieldAdd( cp->blockBitfield, block ); cp->sizeNow += blockSize; cp->haveValidIsDirty = 1; cp->sizeWhenDoneIsDirty = 1; } }
tr_bool tr_cpFileIsComplete( const tr_completion * cp, tr_file_index_t fileIndex ) { tr_block_index_t block; const tr_torrent * tor = cp->tor; const tr_file * file = &tor->info.files[fileIndex]; const tr_block_index_t firstBlock = file->offset / tor->blockSize; const tr_block_index_t lastBlock = file->length ? ( ( file->offset + file->length - 1 ) / tor->blockSize ) : firstBlock; tr_assert( tr_torBlockPiece( tor, firstBlock ) == file->firstPiece, "file->offset %"PRIu64"; file->length %"PRIu64"; " "pieceSize %"PRIu32"; blockSize %"PRIu32"; " "firstBlock %"PRIu64"; lastBlock %"PRIu64, file->offset, file->length, tor->info.pieceSize, tor->blockSize, firstBlock, lastBlock ); tr_assert( tr_torBlockPiece( tor, lastBlock ) == file->lastPiece, "file->offset %"PRIu64"; file->length %"PRIu64"; " "pieceSize %"PRIu32"; blockSize %"PRIu32"; " "firstBlock %"PRIu64"; lastBlock %"PRIu64, file->offset, file->length, tor->info.pieceSize, tor->blockSize, firstBlock, lastBlock ); for( block=firstBlock; block<=lastBlock; ++block ) if( !tr_cpBlockIsComplete( cp, block ) ) return FALSE; return TRUE; }
void tr_cpPieceRem( tr_completion * cp, tr_piece_index_t piece ) { const tr_torrent * tor = cp->tor; const tr_block_index_t start = tr_torPieceFirstBlock( tor, piece ); const tr_block_index_t end = start + tr_torPieceCountBlocks( tor, piece ); tr_block_index_t block; assert( cp ); assert( piece < tor->info.pieceCount ); assert( start < tor->blockCount ); assert( start <= end ); assert( end <= tor->blockCount ); for( block = start; block < end; ++block ) if( tr_cpBlockIsComplete( cp, block ) ) cp->sizeNow -= tr_torBlockCountBytes( tor, block ); cp->sizeWhenDoneIsDirty = 1; cp->haveValidIsDirty = 1; cp->completeBlocks[piece] = 0; tr_bitfieldRemRange ( cp->blockBitfield, start, end ); tr_bitfieldRem( cp->pieceBitfield, piece ); }
uint64_t tr_cpSizeWhenDone( const tr_completion * ccp ) { if( ccp->sizeWhenDoneIsDirty ) { uint64_t size = 0; const tr_torrent * tor = ccp->tor; const tr_info * inf = tr_torrentInfo( tor ); tr_completion * cp = (tr_completion *) ccp; /* mutable */ if( tr_cpHasAll( ccp ) ) { size = inf->totalSize; } else { tr_piece_index_t p; for( p=0; p<inf->pieceCount; ++p ) { uint64_t n = 0; const uint64_t pieceSize = tr_torPieceCountBytes( tor, p ); if( !inf->pieces[p].dnd ) { n = pieceSize; } else { uint64_t o = 0; tr_block_index_t b, f, l; tr_torGetPieceBlockRange( cp->tor, p, &f, &l ); for( b=f; b<=l; ++b ) if( tr_cpBlockIsComplete( cp, b ) ) n += tr_torBlockCountBytes( tor, b ); o = tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 ); o *= cp->tor->blockSize; if( l == ( cp->tor->blockCount - 1 ) && tr_bitfieldHas( &cp->blockBitfield, l ) ) o -= ( cp->tor->blockSize - cp->tor->lastBlockSize ); assert( n == o ); } assert( n <= tr_torPieceCountBytes( tor, p ) ); size += n; } } assert( size <= inf->totalSize ); assert( size >= cp->sizeNow ); cp->sizeWhenDoneLazy = size; cp->sizeWhenDoneIsDirty = false; } return ccp->sizeWhenDoneLazy; }
void tr_cpDownloaderRem( tr_completion_t * cp, int block ) { tr_torrent_t * tor = cp->tor; (cp->blockDownloaders[block])--; if( !cp->blockDownloaders[block] && !tr_cpBlockIsComplete( cp, block ) ) { cp->missingBlocks[tr_blockPiece(block)]++; } }
void tr_cpBlockRem( tr_completion_t * cp, int block ) { tr_torrent_t * tor = cp->tor; if( tr_cpBlockIsComplete( cp, block ) ) { (cp->blockCount)--; if( !cp->blockDownloaders[block] ) { (cp->missingBlocks[tr_blockPiece(block)])++; } } tr_bitfieldRem( cp->blockBitfield, block ); }
void tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block ) { const tr_torrent * tor = cp->tor; if( !tr_cpBlockIsComplete( cp, block ) ) { tr_bitfieldAdd( &cp->blockBitfield, block ); cp->sizeNow += tr_torBlockCountBytes( tor, block ); cp->haveValidIsDirty = true; cp->sizeWhenDoneIsDirty = true; } }
void tr_cpBlockAdd(tr_completion* cp, tr_block_index_t block) { tr_torrent const* tor = cp->tor; if (!tr_cpBlockIsComplete(cp, block)) { tr_piece_index_t const piece = tr_torBlockPiece(cp->tor, block); tr_bitfieldAdd(&cp->blockBitfield, block); cp->sizeNow += tr_torBlockCountBytes(tor, block); cp->haveValidIsDirty = true; cp->sizeWhenDoneIsDirty |= tor->info.pieces[piece].dnd; } }
void tr_cpPieceRem( tr_completion * cp, tr_piece_index_t piece ) { tr_block_index_t i, f, l; const tr_torrent * tor = cp->tor; tr_torGetPieceBlockRange( cp->tor, piece, &f, &l ); for( i=f; i<=l; ++i ) if( tr_cpBlockIsComplete( cp, i ) ) cp->sizeNow -= tr_torBlockCountBytes( tor, i ); cp->haveValidIsDirty = true; cp->sizeWhenDoneIsDirty = true; tr_bitfieldRemRange( &cp->blockBitfield, f, l+1 ); }
int tr_cpMostMissingBlockInPiece( tr_completion_t * cp, int piece, int * downloaders ) { tr_torrent_t * tor = cp->tor; int start, count, end, i; int * pool, poolSize, min, ret; start = tr_pieceStartBlock( piece ); count = tr_pieceCountBlocks( piece ); end = start + count; pool = malloc( count * sizeof( int ) ); poolSize = 0; min = 255; for( i = start; i < end; i++ ) { if( tr_cpBlockIsComplete( cp, i ) || cp->blockDownloaders[i] > min ) { continue; } if( cp->blockDownloaders[i] < min ) { min = cp->blockDownloaders[i]; poolSize = 0; } if( cp->blockDownloaders[i] <= min ) { pool[poolSize++] = i; } } if( poolSize > 0 ) { ret = pool[0]; *downloaders = min; } else { ret = -1; } free( pool ); return ret; }
uint64_t tr_cpSizeWhenDone( const tr_completion * ccp ) { if( ccp->sizeWhenDoneIsDirty ) { tr_completion * cp = (tr_completion *) ccp; /* mutable */ const tr_torrent * tor = cp->tor; const tr_info * info = &tor->info; tr_piece_index_t i; uint64_t size = 0; for( i = 0; i < info->pieceCount; ++i ) { if( !info->pieces[i].dnd ) { /* we want the piece... */ size += tr_torPieceCountBytes( tor, i ); } else if( tr_cpPieceIsComplete( cp, i ) ) { /* we have the piece... */ size += tr_torPieceCountBytes( tor, i ); } else if( cp->completeBlocks[i] ) { /* we have part of the piece... */ const tr_block_index_t b = tr_torPieceFirstBlock( tor, i ); const tr_block_index_t e = b + tr_torPieceCountBlocks( tor, i ); tr_block_index_t j; for( j = b; j < e; ++j ) if( tr_cpBlockIsComplete( cp, j ) ) size += tr_torBlockCountBytes( tor, j ); } } cp->sizeWhenDoneLazy = size; cp->sizeWhenDoneIsDirty = 0; } assert( ccp->sizeWhenDoneLazy <= ccp->tor->info.totalSize ); assert( ccp->sizeWhenDoneLazy >= ccp->sizeNow ); return ccp->sizeWhenDoneLazy; }
int tr_cpMissingBlockInPiece( tr_completion_t * cp, int piece ) { tr_torrent_t * tor = cp->tor; int start, count, end, i; start = tr_pieceStartBlock( piece ); count = tr_pieceCountBlocks( piece ); end = start + count; for( i = start; i < end; i++ ) { if( tr_cpBlockIsComplete( cp, i ) || cp->blockDownloaders[i] ) { continue; } return i; } return -1; }