Exemplo n.º 1
0
int
tr_cpBlockBitfieldSet( tr_completion * cp,
                       tr_bitfield *   bitfield )
{
    int success = FALSE;

    assert( cp );
    assert( bitfield );
    assert( cp->blockBitfield );

    if( tr_bitfieldTestFast( bitfield, cp->tor->blockCount - 1 ) )
    {
        tr_block_index_t i;
        tr_cpReset( cp );
        for( i = 0; i < cp->tor->blockCount; ++i )
            if( tr_bitfieldHasFast( bitfield, i ) )
                tr_cpBlockAdd( cp, i );
        success = TRUE;
    }

    return success;
}
Exemplo n.º 2
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;
}