uint64_t
tr_cpHaveValid( const tr_completion * ccp )
{
    if( ccp->haveValidIsDirty )
    {
        tr_piece_index_t i;
        uint64_t size = 0;
        tr_completion * cp = (tr_completion *) ccp; /* mutable */
        const tr_torrent * tor = ccp->tor;
        const tr_info * info = &tor->info;

        for( i=0; i<info->pieceCount; ++i )
            if( tr_cpPieceIsComplete( ccp, i ) )
                size += tr_torPieceCountBytes( tor, i );

        cp->haveValidLazy = size;
        cp->haveValidIsDirty = false;
    }

    return ccp->haveValidLazy;
}
Example #2
0
void
tr_cpGetAmountDone( const tr_completion * cp,
                    float *               tab,
                    int                   tabCount )
{
    int                i;
    const tr_torrent * tor = cp->tor;
    const float        interval = tor->info.pieceCount / (float)tabCount;
    const int          isSeed = tr_cpGetStatus ( tor->completion ) == TR_SEED;

    for( i = 0; i < tabCount; ++i )
    {
        const tr_piece_index_t piece = i * interval;

        if( tor == NULL )
            tab[i] = 0.0f;
        else if( isSeed || tr_cpPieceIsComplete( cp, piece ) )
            tab[i] = 1.0f;
        else
            tab[i] = (float)cp->completeBlocks[piece] /
                     tr_torPieceCountBlocks( tor, piece );
    }
}
Example #3
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;
    }
}
Example #4
0
static tr_bool
verifyTorrent( tr_torrent * tor, tr_bool * stopFlag )
{
    time_t end;
    SHA_CTX sha;
    int fd = -1;
    int64_t filePos = 0;
    tr_bool changed = 0;
    tr_bool hadPiece = 0;
    time_t lastSleptAt = 0;
    uint32_t piecePos = 0;
    tr_file_index_t fileIndex = 0;
    tr_file_index_t prevFileIndex = !fileIndex;
    tr_piece_index_t pieceIndex = 0;
    const time_t begin = tr_time( );
    const size_t buflen = 1024 * 128; /* 128 KiB buffer */
    uint8_t * buffer = tr_valloc( buflen );

    SHA1_Init( &sha );

    tr_tordbg( tor, "%s", "verifying torrent..." );
    tr_torrentSetChecked( tor, 0 );
    while( !*stopFlag && ( pieceIndex < tor->info.pieceCount ) )
    {
        uint32_t leftInPiece;
        uint32_t bytesThisPass;
        uint64_t leftInFile;
        const tr_file * file = &tor->info.files[fileIndex];

        /* if we're starting a new piece... */
        if( piecePos == 0 )
            hadPiece = tr_cpPieceIsComplete( &tor->completion, pieceIndex );

        /* if we're starting a new file... */
        if( !filePos && (fd<0) && (fileIndex!=prevFileIndex) )
        {
            char * filename = tr_torrentFindFile( tor, fileIndex );
            fd = filename == NULL ? -1 : tr_open_file_for_scanning( filename );
            tr_free( filename );
            prevFileIndex = fileIndex;
        }

        /* figure out how much we can read this pass */
        leftInPiece = tr_torPieceCountBytes( tor, pieceIndex ) - piecePos;
        leftInFile = file->length - filePos;
        bytesThisPass = MIN( leftInFile, leftInPiece );
        bytesThisPass = MIN( bytesThisPass, buflen );

        /* read a bit */
        if( fd >= 0 ) {
            const ssize_t numRead = tr_pread( fd, buffer, bytesThisPass, filePos );
            if( numRead > 0 ) {
                bytesThisPass = (uint32_t)numRead;
                SHA1_Update( &sha, buffer, bytesThisPass );
#if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_DONTNEED
                posix_fadvise( fd, filePos, bytesThisPass, POSIX_FADV_DONTNEED );
#endif
            }
        }

        /* move our offsets */
        leftInPiece -= bytesThisPass;
        leftInFile -= bytesThisPass;
        piecePos += bytesThisPass;
        filePos += bytesThisPass;

        /* if we're finishing a piece... */
        if( leftInPiece == 0 )
        {
            time_t now;
            tr_bool hasPiece;
            uint8_t hash[SHA_DIGEST_LENGTH];

            SHA1_Final( hash, &sha );
            hasPiece = !memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH );

            if( hasPiece || hadPiece ) {
                tr_torrentSetHasPiece( tor, pieceIndex, hasPiece );
                changed |= hasPiece != hadPiece;
            }
            tr_torrentSetPieceChecked( tor, pieceIndex );
            now = tr_time( );
            tor->anyDate = now;

            /* sleeping even just a few msec per second goes a long
             * way towards reducing IO load... */
            if( lastSleptAt != now ) {
                lastSleptAt = now;
                tr_wait_msec( MSEC_TO_SLEEP_PER_SECOND_DURING_VERIFY );
            }

            SHA1_Init( &sha );
            ++pieceIndex;
            piecePos = 0;
        }

        /* if we're finishing a file... */
        if( leftInFile == 0 )
        {
            if( fd >= 0 ) { tr_close_file( fd ); fd = -1; }
            ++fileIndex;
            filePos = 0;
        }
    }

    /* cleanup */
    if( fd >= 0 )
        tr_close_file( fd );
    free( buffer );

    /* stopwatch */
    end = tr_time( );
    tr_tordbg( tor, "Verification is done. It took %d seconds to verify %"PRIu64" bytes (%"PRIu64" bytes per second)",
               (int)(end-begin), tor->info.totalSize,
               (uint64_t)(tor->info.totalSize/(1+(end-begin))) );

    return changed;
}
Example #5
0
static tr_bool
verifyTorrent( tr_torrent * tor, tr_bool * stopFlag )
{
    SHA_CTX sha;
    int fd = -1;
    int64_t filePos = 0;
    tr_bool changed = 0;
    tr_bool hadPiece = 0;
    uint32_t piecePos = 0;
    uint32_t pieceBytesRead = 0;
    tr_file_index_t fileIndex = 0;
    tr_piece_index_t pieceIndex = 0;
    const int64_t buflen = tor->info.pieceSize;
    uint8_t * buffer = tr_new( uint8_t, buflen );
#ifdef STOPWATCH
    time_t now = time( NULL );
#endif

    SHA1_Init( &sha );

    while( !*stopFlag && ( pieceIndex < tor->info.pieceCount ) )
    {
        int64_t leftInPiece;
        int64_t leftInFile;
        int64_t bytesThisPass;
        const tr_file * file = &tor->info.files[fileIndex];

        /* if we're starting a new piece... */
        if( piecePos == 0 )
        {
            hadPiece = tr_cpPieceIsComplete( &tor->completion, pieceIndex );
            /* fprintf( stderr, "starting piece %d of %d\n", (int)pieceIndex, (int)tor->info.pieceCount ); */
        }

        /* if we're starting a new file... */
        if( !filePos && (fd<0) )
        {
            char * filename = tr_buildPath( tor->downloadDir, file->name, NULL );
            fd = tr_open_file_for_scanning( filename );
            /* fprintf( stderr, "opening file #%d (%s) -- %d\n", fileIndex, filename, fd ); */
            tr_free( filename );
        }

        /* figure out how much we can read this pass */
        leftInPiece = tr_torPieceCountBytes( tor, pieceIndex ) - piecePos;
        leftInFile = file->length - filePos;
        bytesThisPass = MIN( leftInFile, leftInPiece );
        bytesThisPass = MIN( bytesThisPass, buflen );
        /* fprintf( stderr, "reading this pass: %d\n", (int)bytesThisPass ); */

        /* read a bit */
        if( (fd>=0) && tr_lseek( fd, filePos, SEEK_SET ) != -1 ) {
            const int64_t numRead = read( fd, buffer, bytesThisPass );
            if( numRead > 0 )
                pieceBytesRead += numRead;
            if( numRead == bytesThisPass )
                SHA1_Update( &sha, buffer, numRead );
        }

        /* move our offsets */
        leftInPiece -= bytesThisPass;
        leftInFile -= bytesThisPass;
        piecePos += bytesThisPass;
        filePos += bytesThisPass;

        /* if we're finishing a piece... */
        if( leftInPiece == 0 )
        {
            tr_bool hasPiece;
            uint8_t hash[SHA_DIGEST_LENGTH];

            SHA1_Final( hash, &sha );
            hasPiece = !memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH );
            /* fprintf( stderr, "do the hashes match? %s\n", (hasPiece?"yes":"no") ); */

            if( hasPiece ) {
                tr_torrentSetHasPiece( tor, pieceIndex, TRUE );
                if( !hadPiece )
                    changed = TRUE;
            } else if( hadPiece ) {
                tr_torrentSetHasPiece( tor, pieceIndex, FALSE );
                changed = TRUE;
            }
            tr_torrentSetPieceChecked( tor, pieceIndex, TRUE );
            tor->anyDate = time( NULL );

            /* going full-throttle on a verify can choke other processes'
             * disk IO, so wait a fwe msec between pieces.
             * The msec is arbitrary, and the "if" clause is to make sure we
             * don't slow down verification of files that don't exist */
            if( pieceBytesRead == tr_torPieceCountBytes( tor, pieceIndex ) )
                tr_wait( 50 );

            SHA1_Init( &sha );
            ++pieceIndex;
            piecePos = 0;
            pieceBytesRead = 0;
        }

        /* if we're finishing a file... */
        if( leftInFile == 0 )
        {
            /* fprintf( stderr, "closing file\n" ); */
            if( fd >= 0 ) {
                tr_close_file( fd );
                fd = -1;
            }
            ++fileIndex;
            filePos = 0;
        }
    }

    /* cleanup */
    if( fd >= 0 )
        tr_close_file( fd );
    tr_free( buffer );

#ifdef STOPWATCH
    {
        time_t now2 = time( NULL );
        fprintf( stderr, "it took %d seconds to verify %"PRIu64" bytes (%"PRIu64" bytes per second)\n",
                 (int)(now2-now), tor->info.totalSize, (uint64_t)(tor->info.totalSize/(1+(now2-now))) );
    }
#endif

    return changed;
}