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; } }
static int test_bitfields (void) { unsigned int i; unsigned int bitcount = 500; tr_bitfield field; tr_bitfieldConstruct (&field, bitcount); /* test tr_bitfieldAdd */ for (i=0; i<bitcount; i++) if (! (i % 7)) tr_bitfieldAdd (&field, i); for (i=0; i<bitcount; i++) check (tr_bitfieldHas (&field, i) == (! (i % 7))); /* test tr_bitfieldAddRange */ tr_bitfieldAddRange (&field, 0, bitcount); for (i=0; i<bitcount; i++) check (tr_bitfieldHas (&field, i)); /* test tr_bitfieldRemRange in the middle of a boundary */ tr_bitfieldRemRange (&field, 4, 21); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((i < 4) || (i >= 21))); /* test tr_bitfieldRemRange on the boundaries */ tr_bitfieldAddRange (&field, 0, 64); tr_bitfieldRemRange (&field, 8, 24); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((i < 8) || (i >= 24))); /* test tr_bitfieldRemRange when begin & end is on the same word */ tr_bitfieldAddRange (&field, 0, 64); tr_bitfieldRemRange (&field, 4, 5); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((i < 4) || (i >= 5))); /* test tr_bitfieldAddRange */ tr_bitfieldRemRange (&field, 0, 64); tr_bitfieldAddRange (&field, 4, 21); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((4 <= i) && (i < 21))); /* test tr_bitfieldAddRange on the boundaries */ tr_bitfieldRemRange (&field, 0, 64); tr_bitfieldAddRange (&field, 8, 24); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((8 <= i) && (i < 24))); /* test tr_bitfieldAddRange when begin & end is on the same word */ tr_bitfieldRemRange (&field, 0, 64); tr_bitfieldAddRange (&field, 4, 5); for (i=0; i<64; i++) check (tr_bitfieldHas (&field, i) == ((4 <= i) && (i < 5))); tr_bitfieldDestruct (&field); return 0; }
void tr_cpBlockAdd( 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_bitfieldAdd( 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_cpPieceAdd( tr_completion_t * cp, int piece ) { tr_torrent_t * tor = cp->tor; int startBlock, endBlock, i; startBlock = tr_pieceStartBlock( piece ); endBlock = startBlock + tr_pieceCountBlocks( piece ); for( i = startBlock; i < endBlock; i++ ) { tr_cpBlockAdd( cp, i ); } tr_bitfieldAdd( cp->pieceBitfield, piece ); }
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; } }
static int test_bitfield_count_range (void) { int i; int n; int begin; int end; int count1; int count2; const int bitCount = 100 + tr_cryptoWeakRandInt (1000); tr_bitfield bf; /* generate a random bitfield */ tr_bitfieldConstruct (&bf, bitCount); for (i=0, n=tr_cryptoWeakRandInt (bitCount); i<n; ++i) tr_bitfieldAdd (&bf, tr_cryptoWeakRandInt (bitCount)); begin = tr_cryptoWeakRandInt (bitCount); do end = tr_cryptoWeakRandInt (bitCount); while (end == begin); /* ensure end <= begin */ if (end < begin) { const int tmp = begin; begin = end; end = tmp; } /* test the bitfield */ count1 = 0; for (i=begin; i<end; ++i) if (tr_bitfieldHas (&bf, i)) ++count1; count2 = tr_bitfieldCountRange (&bf, begin, end); check (count1 == count2); /* cleanup */ tr_bitfieldDestruct (&bf); return 0; }
/* Initialize a completion object from a bitfield indicating which blocks we have */ tr_bool tr_cpBlockBitfieldSet( tr_completion * cp, tr_bitfield * blockBitfield ) { tr_bool success = FALSE; assert( cp ); assert( blockBitfield ); /* The bitfield of block flags is typically loaded from a resume file. Test the bitfield's length in case the resume file somehow got corrupted */ if(( success = blockBitfield->byteCount == cp->blockBitfield.byteCount )) { tr_block_index_t b = 0; tr_piece_index_t p = 0; uint32_t pieceBlock = 0; uint16_t completeBlocksInPiece = 0; tr_block_index_t completeBlocksInTorrent = 0; uint32_t blocksInCurrentPiece = tr_torPieceCountBlocks( cp->tor, p ); /* start cp with a state where it thinks we have nothing */ tr_cpReset( cp ); /* init our block bitfield from the one passed in */ memcpy( cp->blockBitfield.bits, blockBitfield->bits, blockBitfield->byteCount ); /* invalidate the fields that are lazy-evaluated */ cp->sizeWhenDoneIsDirty = TRUE; cp->haveValidIsDirty = TRUE; /* to set the remaining fields, we walk through every block... */ while( b < cp->tor->blockCount ) { if( tr_bitfieldHasFast( blockBitfield, b ) ) ++completeBlocksInPiece; ++b; ++pieceBlock; /* by the time we reach the end of a piece, we have enough info to update that piece's slot in cp.completeBlocks and cp.pieceBitfield */ if( pieceBlock == blocksInCurrentPiece ) { cp->completeBlocks[p] = completeBlocksInPiece; completeBlocksInTorrent += completeBlocksInPiece; if( completeBlocksInPiece == blocksInCurrentPiece ) tr_bitfieldAdd( &cp->pieceBitfield, p ); /* reset the per-piece counters because we're starting on a new piece now */ ++p; completeBlocksInPiece = 0; pieceBlock = 0; blocksInCurrentPiece = tr_torPieceCountBlocks( cp->tor, p ); } } /* update sizeNow */ cp->sizeNow = completeBlocksInTorrent; cp->sizeNow *= tr_torBlockCountBytes( cp->tor, 0 ); if( tr_bitfieldHasFast( &cp->blockBitfield, cp->tor->blockCount-1 ) ) { /* the last block is usually smaller than the other blocks, so handle that special case or cp->sizeNow might be too large */ cp->sizeNow -= tr_torBlockCountBytes( cp->tor, 0 ); cp->sizeNow += tr_torBlockCountBytes( cp->tor, cp->tor->blockCount-1 ); } } return success; }