Ignore:
Timestamp:
Jun 18, 2007, 3:40:41 AM (15 years ago)
Author:
livings124
Message:

Merge file selection and torrent creation into the main branch.

The new code for these features is under a new license.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/completion.c

    r2004 r2149  
    2424
    2525#include "transmission.h"
     26#include "completion.h"
     27
     28struct tr_completion_s
     29{
     30    tr_torrent_t      * tor;
     31    tr_bitfield_t     * blockBitfield;
     32    uint8_t           * blockDownloaders;
     33    tr_bitfield_t     * pieceBitfield;
     34
     35    /* a block is missing if we don't have it AND there's not a request pending */
     36    int * missingBlocks;
     37
     38    /* a block is complete if and only if we have it */
     39    int * completeBlocks;
     40
     41    /* rather than calculating these over and over again in loops,
     42       just calculate them once */
     43    int nBlocksInPiece;
     44    int nBlocksInLastPiece;
     45};
     46
     47#define tr_cpCountBlocks(cp,piece) \
     48    (piece==cp->tor->info.pieceCount-1 ? cp->nBlocksInLastPiece : cp->nBlocksInPiece)
    2649
    2750tr_completion_t * tr_cpInit( tr_torrent_t * tor )
     
    3558    cp->pieceBitfield    = tr_bitfieldNew( tor->info.pieceCount );
    3659    cp->missingBlocks    = malloc( tor->info.pieceCount * sizeof( int ) );
     60    cp->completeBlocks   = malloc( tor->info.pieceCount * sizeof( int ) );
     61
     62    cp->nBlocksInLastPiece = tr_pieceCountBlocks ( tor->info.pieceCount - 1 );
     63    cp->nBlocksInPiece = tor->info.pieceCount==1 ? cp->nBlocksInLastPiece
     64                                                : tr_pieceCountBlocks( 0 );
    3765
    3866    tr_cpReset( cp );
     
    4775    tr_bitfieldFree( cp->pieceBitfield );
    4876    free(            cp->missingBlocks );
     77    free(            cp->completeBlocks );
    4978    free(            cp );
    5079}
     
    5584    int i;
    5685
    57     cp->blockCount = 0;
    5886    tr_bitfieldClear( cp->blockBitfield );
    5987    memset( cp->blockDownloaders, 0, tor->blockCount );
    6088    tr_bitfieldClear( cp->pieceBitfield );
    61     for( i = 0; i < tor->info.pieceCount; i++ )
    62     {
    63         cp->missingBlocks[i] = tr_pieceCountBlocks( i );
    64     }
    65 }
    66 
    67 float tr_cpCompletionAsFloat( tr_completion_t * cp )
    68 {
    69     return (float) cp->blockCount / (float) cp->tor->blockCount;
    70 }
    71 
    72 uint64_t tr_cpLeftBytes( tr_completion_t * cp )
    73 {
    74     tr_torrent_t * tor = cp->tor;
    75     uint64_t left;
    76     left = (uint64_t) ( cp->tor->blockCount - cp->blockCount ) *
    77            (uint64_t) tor->blockSize;
    78     if( !tr_bitfieldHas( cp->blockBitfield, cp->tor->blockCount - 1 ) &&
    79         tor->info.totalSize % tor->blockSize )
    80     {
    81         left += tor->info.totalSize % tor->blockSize;
    82         left -= tor->blockSize;
    83     }
    84     return left;
    85 }
    86 
    87 /* Pieces */
    88 int tr_cpPieceHasAllBlocks( tr_completion_t * cp, int piece )
    89 {
    90     tr_torrent_t * tor = cp->tor;
    91     int startBlock  = tr_pieceStartBlock( piece );
    92     int endBlock    = startBlock + tr_pieceCountBlocks( piece );
    93     int i;
    94 
    95     for( i = startBlock; i < endBlock; i++ )
    96     {
    97         if( !tr_bitfieldHas( cp->blockBitfield, i ) )
    98         {
    99             return 0;
    100         }
    101     }   
    102     return 1;
    103 }
    104 int tr_cpPieceIsComplete( tr_completion_t * cp, int piece )
    105 {
    106     return tr_bitfieldHas( cp->pieceBitfield, piece );
    107 }
    108 
    109 tr_bitfield_t * tr_cpPieceBitfield( tr_completion_t * cp )
     89    for( i = 0; i < tor->info.pieceCount; ++i ) {
     90        cp->missingBlocks[i] = tr_cpCountBlocks( cp, i );
     91        cp->completeBlocks[i] = 0;
     92    }
     93}
     94
     95int tr_cpPieceHasAllBlocks( const tr_completion_t * cp, int piece )
     96{
     97    return tr_cpPieceIsComplete( cp, piece );
     98}
     99
     100int tr_cpPieceIsComplete( const tr_completion_t * cp, int piece )
     101{
     102    const int total = tr_cpCountBlocks( cp, piece );
     103    const int have = cp->completeBlocks[piece];
     104    assert( have <= total );
     105    return have == total;
     106}
     107
     108const tr_bitfield_t * tr_cpPieceBitfield( const tr_completion_t * cp )
    110109{
    111110    return cp->pieceBitfield;
     
    114113void tr_cpPieceAdd( tr_completion_t * cp, int piece )
    115114{
    116     tr_torrent_t * tor = cp->tor;
    117     int startBlock, endBlock, i;
    118 
    119     startBlock = tr_pieceStartBlock( piece );
    120     endBlock   = startBlock + tr_pieceCountBlocks( piece );
    121     for( i = startBlock; i < endBlock; i++ )
    122     {
    123         tr_cpBlockAdd( cp, i );
    124     }
     115    int i;
     116    const tr_torrent_t * tor = cp->tor;
     117    const int n_blocks = tr_cpCountBlocks( cp, piece );
     118    const int startBlock = tr_pieceStartBlock( piece );
     119    const int endBlock   = startBlock + n_blocks;
     120
     121    cp->completeBlocks[piece] = n_blocks;
     122
     123    for( i=startBlock; i<endBlock; ++i )
     124        if( !cp->blockDownloaders[i] )
     125            --cp->missingBlocks[piece];
     126
     127    tr_bitfieldAddRange( cp->blockBitfield, startBlock, endBlock-1 );
    125128
    126129    tr_bitfieldAdd( cp->pieceBitfield, piece );
     
    129132void tr_cpPieceRem( tr_completion_t * cp, int piece )
    130133{
    131     tr_torrent_t * tor = cp->tor;
    132     int startBlock, endBlock, i;
    133 
    134     startBlock = tr_pieceStartBlock( piece );
    135     endBlock   = startBlock + tr_pieceCountBlocks( piece );
    136     for( i = startBlock; i < endBlock; i++ )
    137     {
    138         tr_cpBlockRem( cp, i );
    139     }
     134    int i;
     135    const tr_torrent_t * tor = cp->tor;
     136    const int n_blocks = tr_cpCountBlocks( cp, piece );
     137    const int startBlock = tr_pieceStartBlock( piece );
     138    const int endBlock   = startBlock + n_blocks;
     139
     140    cp->completeBlocks[piece] = 0;
     141
     142    for( i=startBlock; i<endBlock; ++i )
     143        if( !cp->blockDownloaders[i] )
     144            ++cp->missingBlocks[piece];
     145
     146    tr_bitfieldRemRange ( cp->blockBitfield, startBlock, endBlock-1 );
    140147
    141148    tr_bitfieldRem( cp->pieceBitfield, piece );
     
    155162void tr_cpDownloaderRem( tr_completion_t * cp, int block )
    156163{
    157     tr_torrent_t * tor = cp->tor;
     164    tr_torrent_t * tor;
     165
     166    assert( cp != NULL );
     167    assert( cp->tor != NULL );
     168    assert( 0 <= block );
     169
     170    tor = cp->tor;
    158171    (cp->blockDownloaders[block])--;
    159172    if( !cp->blockDownloaders[block] && !tr_cpBlockIsComplete( cp, block ) )
     
    165178int tr_cpBlockIsComplete( const tr_completion_t * cp, int block )
    166179{
     180    assert( cp != NULL );
     181    assert( 0 <= block );
     182
    167183    return tr_bitfieldHas( cp->blockBitfield, block );
    168184}
     
    170186void tr_cpBlockAdd( tr_completion_t * cp, int block )
    171187{
    172     tr_torrent_t * tor = cp->tor;
     188    const tr_torrent_t * tor;
     189
     190    assert( cp != NULL );
     191    assert( cp->tor != NULL );
     192    assert( 0 <= block );
     193
     194    tor = cp->tor;
     195
    173196    if( !tr_cpBlockIsComplete( cp, block ) )
    174197    {
    175         (cp->blockCount)++;
     198        const int piece = tr_blockPiece( block );
     199        ++cp->completeBlocks[piece];
     200
     201        if( cp->completeBlocks[piece] == tr_cpCountBlocks( cp, piece ) )
     202            tr_bitfieldAdd( cp->pieceBitfield, piece );
     203
    176204        if( !cp->blockDownloaders[block] )
    177         {
    178             (cp->missingBlocks[tr_blockPiece(block)])--;
    179         }
    180     }
    181     tr_bitfieldAdd( cp->blockBitfield, block );
    182 }
    183 
    184 void tr_cpBlockRem( tr_completion_t * cp, int block )
    185 {
    186     tr_torrent_t * tor = cp->tor;
    187     if( tr_cpBlockIsComplete( cp, block ) )
    188     {
    189         (cp->blockCount)--;
    190         if( !cp->blockDownloaders[block] )
    191         {
    192             (cp->missingBlocks[tr_blockPiece(block)])++;
    193         }
    194     }
    195     tr_bitfieldRem( cp->blockBitfield, block );
    196 }
    197 
    198 tr_bitfield_t * tr_cpBlockBitfield( tr_completion_t * cp )
    199 {
     205            cp->missingBlocks[piece]--;
     206
     207        tr_bitfieldAdd( cp->blockBitfield, block );
     208    }
     209}
     210
     211const tr_bitfield_t * tr_cpBlockBitfield( const tr_completion_t * cp )
     212{
     213    assert( cp != NULL );
     214
    200215    return cp->blockBitfield;
    201216}
    202217
    203 void tr_cpBlockBitfieldSet( tr_completion_t * cp, tr_bitfield_t * bitfield )
    204 {
    205     tr_torrent_t * tor = cp->tor;
    206     int i, j;
    207     int startBlock, endBlock;
    208     int pieceComplete;
    209 
    210     for( i = 0; i < cp->tor->info.pieceCount; i++ )
    211     {
    212         startBlock    = tr_pieceStartBlock( i );
    213         endBlock      = startBlock + tr_pieceCountBlocks( i );
    214         pieceComplete = 1;
    215 
    216         for( j = startBlock; j < endBlock; j++ )
    217         {
    218             if( tr_bitfieldHas( bitfield, j ) )
    219             {
    220                 tr_cpBlockAdd( cp, j );
    221             }
    222             else
    223             {
    224                 pieceComplete = 0;
    225             }
    226         }
    227         if( pieceComplete )
    228         {
    229             tr_cpPieceAdd( cp, i );
    230         }
    231     }
    232 }
    233 
    234 float tr_cpPercentBlocksInPiece( tr_completion_t * cp, int piece )
    235 {
    236     tr_torrent_t * tor = cp->tor;
    237     int i;
    238     int blockCount, startBlock, endBlock;
    239     int complete;
    240     tr_bitfield_t * bitfield;
    241    
    242     blockCount  = tr_pieceCountBlocks( piece );
    243     startBlock  = tr_pieceStartBlock( piece );
    244     endBlock    = startBlock + blockCount;
    245     complete    = 0;
    246    
    247     bitfield = cp->blockBitfield;
    248 
    249     for( i = startBlock; i < endBlock; i++ )
    250     {
     218void
     219tr_cpBlockBitfieldSet( tr_completion_t * cp, tr_bitfield_t * bitfield )
     220{
     221    int i;
     222
     223    assert( cp != NULL );
     224    assert( bitfield != NULL );
     225
     226    tr_cpReset( cp );
     227
     228    for( i=0; i < cp->tor->blockCount; ++i )
    251229        if( tr_bitfieldHas( bitfield, i ) )
    252         {
    253             complete++;
    254         }
    255     }   
    256 
    257     return (float)complete / (float)blockCount;
     230            tr_cpBlockAdd( cp, i );
     231}
     232
     233float tr_cpPercentBlocksInPiece( const tr_completion_t * cp, int piece )
     234{
     235    assert( cp != NULL );
     236
     237    return cp->completeBlocks[piece] / (double)tr_cpCountBlocks( cp, piece );
    258238}
    259239
    260240int tr_cpMissingBlockInPiece( const tr_completion_t * cp, int piece )
    261241{
     242    int i;
    262243    const tr_torrent_t * tor = cp->tor;
    263     int start, count, end, i;
    264 
    265     start = tr_pieceStartBlock( piece );
    266     count = tr_pieceCountBlocks( piece );
    267     end   = start + count;
    268 
    269     for( i = start; i < end; i++ )
    270     {
    271         if( tr_cpBlockIsComplete( cp, i ) || cp->blockDownloaders[i] )
    272         {
    273             continue;
    274         }
    275         return i;
    276     }
     244    const int start = tr_pieceStartBlock( piece );
     245    const int end   = start + tr_cpCountBlocks( cp, piece );
     246
     247    for( i = start; i < end; ++i )
     248        if( !tr_cpBlockIsComplete( cp, i ) && !cp->blockDownloaders[i] )
     249            return i;
    277250
    278251    return -1;
    279252}
    280253
    281 int tr_cpMostMissingBlockInPiece( tr_completion_t * cp, int piece,
    282                                   int * downloaders )
     254int tr_cpMostMissingBlockInPiece( const tr_completion_t * cp,
     255                                  int                     piece,
     256                                  int                   * downloaders )
    283257{
    284258    tr_torrent_t * tor = cp->tor;
     
    287261
    288262    start = tr_pieceStartBlock( piece );
    289     count = tr_pieceCountBlocks( piece );
     263    count = tr_cpCountBlocks( cp, piece );
    290264    end   = start + count;
    291265
     
    325299}
    326300
     301
     302int
     303tr_cpMissingBlocksForPiece( const tr_completion_t * cp, int piece )
     304{
     305    assert( cp != NULL );
     306
     307    return cp->missingBlocks[piece];
     308}
     309
     310/***
     311****
     312***/
     313
     314cp_status_t
     315tr_cpGetStatus ( const tr_completion_t * cp )
     316{
     317    int i;
     318    int ret = TR_CP_COMPLETE;
     319    const tr_info_t * info;
     320
     321    assert( cp != NULL );
     322    assert( cp->tor != NULL );
     323
     324    info = &cp->tor->info;
     325    for( i=0; i<info->pieceCount; ++i ) {
     326        if( tr_cpPieceIsComplete( cp, i ) )
     327            continue;
     328        if( info->pieces[i].priority != TR_PRI_DND)
     329            return TR_CP_INCOMPLETE;
     330        ret = TR_CP_DONE;
     331    }
     332
     333    return ret;
     334}
     335
     336uint64_t
     337tr_cpLeftUntilComplete ( const tr_completion_t * cp )
     338{
     339    int i;
     340    uint64_t b=0;
     341    const tr_torrent_t * tor;
     342    const tr_info_t * info;
     343
     344    assert( cp != NULL );
     345    assert( cp->tor != NULL );
     346
     347    tor = cp->tor;
     348    info = &tor->info;
     349    for( i=0; i<info->pieceCount; ++i )
     350        if( !tr_cpPieceIsComplete( cp, i ) )
     351            b += ( tr_cpCountBlocks( cp, i ) - cp->completeBlocks[ i ] );
     352
     353    return b * tor->blockSize;;
     354}
     355
     356uint64_t
     357tr_cpLeftUntilDone ( const tr_completion_t * cp )
     358{
     359    int i;
     360    uint64_t b=0;
     361    const tr_torrent_t * tor;
     362    const tr_info_t * info;
     363
     364    assert( cp != NULL );
     365    assert( cp->tor != NULL );
     366
     367    tor = cp->tor;
     368    info = &tor->info;
     369
     370    for( i=0; i<info->pieceCount; ++i )
     371        if( !tr_cpPieceIsComplete( cp, i ) && info->pieces[i].priority != TR_PRI_DND )
     372            b += tor->blockSize * (tr_cpCountBlocks( cp, i ) - cp->completeBlocks[ i ] );
     373
     374    return b;
     375}
     376
     377float
     378tr_cpPercentComplete ( const tr_completion_t * cp )
     379{
     380    int i;
     381    uint64_t have=0;
     382    const tr_torrent_t * tor;
     383
     384    assert( cp != NULL );
     385    assert( cp->tor != NULL );
     386
     387    tor = cp->tor;
     388    for( i=0; i<tor->info.pieceCount; ++i )
     389        have += cp->completeBlocks[ i ];
     390
     391    return tor->blockCount ? (float)have / (float)tor->blockCount : 0.0f;
     392}
     393
     394float
     395tr_cpPercentDone( const tr_completion_t * cp )
     396{
     397    int i;
     398    uint64_t have=0, total=0;
     399    const tr_torrent_t * tor;
     400
     401    assert( cp != NULL );
     402    assert( cp->tor != NULL );
     403
     404    tor = cp->tor;
     405
     406    for( i=0; i<tor->info.pieceCount; ++i ) {
     407        if( tor->info.pieces[i].priority != TR_PRI_DND) {
     408            total += tr_cpCountBlocks( cp, i );
     409            have += cp->completeBlocks[ i ];
     410        }
     411    }
     412
     413    return !total ? 0.0f : (float)have / (float)total;
     414}
     415
     416uint64_t
     417tr_cpDownloadedValid( const tr_completion_t * cp )
     418{
     419    int i, n;
     420    uint64_t b=0;
     421
     422    for( i=0, n=cp->tor->info.pieceCount; i<n; ++i )
     423        b += cp->completeBlocks[ i ];
     424
     425   return b * cp->tor->blockSize;
     426}
Note: See TracChangeset for help on using the changeset viewer.