Exemple #1
0
static void
saveProgress( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * l;
    tr_benc * prog;
    tr_file_index_t fi;
    const tr_info * inf = tr_torrentInfo( tor );
    const time_t now = tr_time( );

    prog = tr_bencDictAddDict( dict, KEY_PROGRESS, 3 );

    /* add the file/piece check timestamps... */
    l = tr_bencDictAddList( prog, KEY_PROGRESS_CHECKTIME, inf->fileCount );
    for( fi=0; fi<inf->fileCount; ++fi )
    {
        const tr_piece * p;
        const tr_piece * pend;
        time_t oldest_nonzero = now;
        time_t newest = 0;
        bool has_zero = false;
        const time_t mtime = tr_torrentGetFileMTime( tor, fi );
        const tr_file * f = &inf->files[fi];

        /* get the oldest and newest nonzero timestamps for pieces in this file */
        for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]; p!=pend; ++p )
        {
            if( !p->timeChecked )
                has_zero = true;
            else if( oldest_nonzero > p->timeChecked )
                oldest_nonzero = p->timeChecked;
            if( newest < p->timeChecked )
                newest = p->timeChecked;
        }

        /* If some of a file's pieces have been checked more recently than
           the file's mtime, and some lest recently, then that file will
           have a list containing timestamps for each piece.

           However, the most common use case is that the file doesn't change
           after it's downloaded. To reduce overhead in the .resume file,
           only a single timestamp is saved for the file if *all* or *none*
           of the pieces were tested more recently than the file's mtime. */

        if( !has_zero && ( mtime <= oldest_nonzero ) ) /* all checked */
            tr_bencListAddInt( l, oldest_nonzero );
        else if( newest < mtime ) /* none checked */
            tr_bencListAddInt( l, newest );
        else { /* some are checked, some aren't... so list piece by piece */
            const int offset = oldest_nonzero - 1;
            tr_benc * ll = tr_bencListAddList( l, 2 + f->lastPiece - f->firstPiece );
            tr_bencListAddInt( ll, offset );
            for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]+1; p!=pend; ++p )
                tr_bencListAddInt( ll, p->timeChecked ? p->timeChecked - offset : 0 );
        }
    }

    /* add the progress */
    if( tor->completeness == TR_SEED )
        tr_bencDictAddStr( prog, KEY_PROGRESS_HAVE, "all" );

    /* add the blocks bitfield */
    bitfieldToBenc( &tor->completion.blockBitfield,
                    tr_bencDictAdd( prog, KEY_PROGRESS_BLOCKS ) );
}
Exemple #2
0
static void saveProgress(tr_variant* dict, tr_torrent* tor)
{
    tr_variant* l;
    tr_variant* prog;
    tr_info const* inf = tr_torrentInfo(tor);
    time_t const now = tr_time();

    prog = tr_variantDictAddDict(dict, TR_KEY_progress, 3);

    /* add the file/piece check timestamps... */
    l = tr_variantDictAddList(prog, TR_KEY_time_checked, inf->fileCount);

    for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
    {
        time_t oldest_nonzero = now;
        time_t newest = 0;
        bool has_zero = false;
        time_t const mtime = tr_torrentGetFileMTime(tor, fi);
        tr_file const* f = &inf->files[fi];

        /* get the oldest and newest nonzero timestamps for pieces in this file */
        for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
        {
            tr_piece const* const p = &inf->pieces[i];

            if (p->timeChecked == 0)
            {
                has_zero = true;
            }
            else if (oldest_nonzero > p->timeChecked)
            {
                oldest_nonzero = p->timeChecked;
            }

            if (newest < p->timeChecked)
            {
                newest = p->timeChecked;
            }
        }

        /* If some of a file's pieces have been checked more recently than
           the file's mtime, and some less recently, then that file will
           have a list containing timestamps for each piece.

           However, the most common use case is that the file doesn't change
           after it's downloaded. To reduce overhead in the .resume file,
           only a single timestamp is saved for the file if *all* or *none*
           of the pieces were tested more recently than the file's mtime. */

        if (!has_zero && mtime <= oldest_nonzero) /* all checked */
        {
            tr_variantListAddInt(l, oldest_nonzero);
        }
        else if (newest < mtime) /* none checked */
        {
            tr_variantListAddInt(l, newest);
        }
        else /* some are checked, some aren't... so list piece by piece */
        {
            int const offset = oldest_nonzero - 1;
            tr_variant* ll = tr_variantListAddList(l, 2 + f->lastPiece - f->firstPiece);
            tr_variantListAddInt(ll, offset);

            for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
            {
                tr_piece const* const p = &inf->pieces[i];

                tr_variantListAddInt(ll, p->timeChecked != 0 ? p->timeChecked - offset : 0);
            }
        }
    }

    /* add the progress */
    if (tor->completeness == TR_SEED)
    {
        tr_variantDictAddStr(prog, TR_KEY_have, "all");
    }

    /* add the blocks bitfield */
    bitfieldToBenc(&tor->completion.blockBitfield, tr_variantDictAdd(prog, TR_KEY_blocks));
}