예제 #1
0
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;
    }
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #5
0
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)]++;
    }
}
예제 #6
0
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 );
}
예제 #7
0
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;
    }
}
예제 #8
0
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;
    }
}
예제 #9
0
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 );
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}