Ignore:
Timestamp:
Apr 24, 2008, 3:25:01 PM (14 years ago)
Author:
charles
Message:

#894: wont start - cp->doneHave <= cp->completeHave

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/completion.c

    r5656 r5682  
    3333struct tr_completion
    3434{
     35    unsigned int sizeWhenDoneIsDirty : 1;
     36
    3537    tr_torrent * tor;
    3638
     
    4446    uint16_t * completeBlocks;
    4547
    46     uint8_t doneDirty;
    47     uint64_t doneHave;
    48     uint64_t doneTotal;
    49     uint64_t completeHave;
     48    /* number of bytes we'll have when done downloading. [0..info.totalSize]
     49       DON'T access this directly; it's a lazy field.
     50       use tr_cpSizeWhenDone() instead! */
     51    uint64_t sizeWhenDoneLazy;
     52
     53    /* number of bytes we want or have now. [0..sizeWhenDone] */
     54    uint64_t sizeNow;
    5055};
    5156
     
    5358tr_cpReset( tr_completion * cp )
    5459{
    55     tr_torrent * tor = cp->tor;
    56 
    5760    tr_bitfieldClear( cp->pieceBitfield );
    5861    tr_bitfieldClear( cp->blockBitfield );
    59     memset( cp->completeBlocks, 0, sizeof(uint16_t) * tor->info.pieceCount );
    60 
    61     cp->doneDirty = TRUE;
    62     cp->doneHave = 0;
    63     cp->doneTotal = 0;
    64     cp->completeHave = 0;
    65 }
    66 
    67 tr_completion * tr_cpInit( tr_torrent * tor )
    68 {
    69     tr_completion * cp;
    70 
    71     cp                   = tr_new( tr_completion, 1 );
    72     cp->tor              = tor;
    73     cp->blockBitfield    = tr_bitfieldNew( tor->blockCount );
    74     cp->pieceBitfield    = tr_bitfieldNew( tor->info.pieceCount );
    75     cp->completeBlocks   = tr_new( uint16_t, tor->info.pieceCount );
    76 
     62    memset( cp->completeBlocks, 0, sizeof(uint16_t) * cp->tor->info.pieceCount );
     63    cp->sizeNow = 0;
     64    cp->sizeWhenDoneIsDirty = 1;
     65}
     66
     67tr_completion *
     68tr_cpInit( tr_torrent * tor )
     69{
     70    tr_completion * cp  = tr_new( tr_completion, 1 );
     71    cp->tor             = tor;
     72    cp->blockBitfield   = tr_bitfieldNew( tor->blockCount );
     73    cp->pieceBitfield   = tr_bitfieldNew( tor->info.pieceCount );
     74    cp->completeBlocks  = tr_new( uint16_t, tor->info.pieceCount );
    7775    tr_cpReset( cp );
    78 
    7976    return cp;
    8077}
    8178
    82 void tr_cpClose( tr_completion * cp )
    83 {
    84     tr_free(         cp->completeBlocks );
     79void
     80tr_cpClose( tr_completion * cp )
     81{
     82    tr_free        ( cp->completeBlocks );
    8583    tr_bitfieldFree( cp->pieceBitfield );
    8684    tr_bitfieldFree( cp->blockBitfield );
    87     tr_free(         cp );
    88 }
    89 
    90 /**
    91 ***
    92 **/
    93 
    94 static void
    95 tr_cpEnsureDoneValid( const tr_completion * ccp )
    96 {
    97     if( ccp->doneDirty )
     85    tr_free        ( cp );
     86}
     87
     88void
     89tr_cpInvalidateDND ( tr_completion * cp )
     90{
     91    cp->sizeWhenDoneIsDirty = 1;
     92}
     93
     94uint64_t
     95tr_cpSizeWhenDone( const tr_completion * ccp )
     96{
     97    if( ccp->sizeWhenDoneIsDirty )
    9898    {
    99         const tr_torrent * tor = ccp->tor;
    100         const tr_info * info = &tor->info;
    101         uint64_t have = 0;
    102         uint64_t total = 0;
     99        tr_completion * cp = (tr_completion *) ccp; /* mutable */
     100        const tr_info * info = &cp->tor->info;
    103101        tr_piece_index_t i;
    104         tr_completion * cp ;
    105 
    106         /* too bad C doesn't have 'mutable' */
    107         cp = (tr_completion*) ccp;
    108         cp->doneDirty = FALSE;
    109 
    110         for( i=0; i<info->pieceCount; ++i ) {
    111             if( tr_cpPieceIsComplete( ccp, i ) || !info->pieces[i].dnd ) {
    112                 total += info->pieceSize;
    113                 have += cp->completeBlocks[ i ];
    114             }
    115         }
    116 
    117         have *= tor->blockSize;
    118 
    119         /* the last piece/block is probably smaller than the others */
    120         if( !info->pieces[info->pieceCount-1].dnd ) {
    121             total -= ( info->pieceSize - tr_torPieceCountBytes(tor,info->pieceCount-1) );
    122             if( tr_cpBlockIsComplete( cp, tor->blockCount-1 ) )
    123                 have -= ( tor->blockSize - tr_torBlockCountBytes(tor,tor->blockCount-1) );
    124         }
    125 
    126         assert( have <= total );
    127         assert( total <= info->totalSize );
    128 
    129         cp->doneHave = have;
    130         cp->doneTotal = total;
     102        uint64_t size = 0;
     103
     104        for( i=0; i<info->pieceCount; ++i )
     105            if( !info->pieces[i].dnd || tr_cpPieceIsComplete( cp, i ) )
     106                size += tr_torPieceCountBytes( cp->tor, i );
     107
     108        cp->sizeWhenDoneLazy = size;
     109        cp->sizeWhenDoneIsDirty = 0;
    131110    }
    132 }
    133 
    134 void
    135 tr_cpInvalidateDND ( tr_completion * cp )
    136 {
    137     cp->doneDirty = TRUE;
     111
     112    assert( ccp->sizeWhenDoneLazy <= ccp->tor->info.totalSize );
     113    assert( ccp->sizeWhenDoneLazy >= ccp->sizeNow );
     114    return ccp->sizeWhenDoneLazy;
    138115}
    139116
     
    142119                      tr_piece_index_t       piece )
    143120{
    144     assert( piece < cp->tor->info.pieceCount );
    145     assert( cp->completeBlocks[piece] <= tr_torPieceCountBlocks(cp->tor,piece) );
    146 
    147121    return cp->completeBlocks[piece] == tr_torPieceCountBlocks(cp->tor,piece);
    148122}
    149123
    150 const tr_bitfield * tr_cpPieceBitfield( const tr_completion * cp )
     124const tr_bitfield *
     125tr_cpPieceBitfield( const tr_completion * cp )
    151126{
    152127    return cp->pieceBitfield;
     
    169144{
    170145    const tr_torrent * tor = cp->tor;
    171     const tr_block_index_t start = tr_torPieceFirstBlock(tor,piece);
    172     const tr_block_index_t end = start + tr_torPieceCountBlocks(tor,piece);
     146    const tr_block_index_t start = tr_torPieceFirstBlock( tor, piece );
     147    const tr_block_index_t end = start + tr_torPieceCountBlocks( tor, piece );
    173148    tr_block_index_t block;
    174149
     
    179154    assert( end <= tor->blockCount );
    180155
    181     for( block=start; block<end; ++block ) {
    182         if( tr_cpBlockIsComplete( cp, block ) ) {
    183             const int blockSize = tr_torBlockCountBytes( tor, block );
    184             cp->completeHave -= blockSize;
    185             if( !tor->info.pieces[piece].dnd )
    186                 cp->doneHave -= blockSize;
    187         }
    188     }
    189 
     156    for( block=start; block<end; ++block )
     157        if( tr_cpBlockIsComplete( cp, block ) )
     158            cp->sizeNow -= tr_torBlockCountBytes( tor, block );
     159
     160    cp->sizeWhenDoneIsDirty = 1;
    190161    cp->completeBlocks[piece] = 0;
    191162    tr_bitfieldRemRange ( cp->blockBitfield, start, end );
    192163    tr_bitfieldRem( cp->pieceBitfield, piece );
    193 
    194     assert( cp->completeHave <= tor->info.totalSize );
    195     assert( cp->doneHave <= tor->info.totalSize );
    196     assert( cp->doneHave <= cp->completeHave );
    197164}
    198165
     
    200167tr_cpBlockIsComplete( const tr_completion * cp, tr_block_index_t block )
    201168{
    202     return tr_bitfieldHas( cp->blockBitfield, block ) ? 1 : 0;
     169    return tr_bitfieldHas( cp->blockBitfield, block );
    203170}
    204171
     
    220187        tr_bitfieldAdd( cp->blockBitfield, block );
    221188
    222         cp->completeHave += blockSize;
    223 
    224         if( !tor->info.pieces[piece].dnd )
    225             cp->doneHave += blockSize;
     189        cp->sizeNow += blockSize;
     190
     191        cp->sizeWhenDoneIsDirty = 1;
    226192    }
    227 
    228     assert( cp->completeHave <= tor->info.totalSize );
    229     assert( cp->doneHave <= tor->info.totalSize );
    230     assert( cp->doneHave <= cp->completeHave );
    231193}
    232194
     
    262224}
    263225
    264 float
    265 tr_cpPercentBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
    266 {
    267     assert( cp != NULL );
    268 
    269     return (double)cp->completeBlocks[piece] / tr_torPieceCountBlocks(cp->tor,piece);
    270 }
    271 
    272226int
    273227tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
    274228{
    275     assert( cp != NULL );
    276 
    277     return tr_torPieceCountBlocks(cp->tor,piece) - cp->completeBlocks[piece];
     229    return tr_torPieceCountBlocks( cp->tor, piece ) - cp->completeBlocks[piece];
    278230}
    279231
     
    283235
    284236float
     237tr_cpPercentDone( const tr_completion * cp )
     238{
     239    return tr_getRatio( cp->sizeNow, tr_cpSizeWhenDone(cp) );
     240}
     241
     242float
    285243tr_cpPercentComplete ( const tr_completion * cp )
    286244{
    287     return (double)cp->completeHave / cp->tor->info.totalSize;
     245    return tr_getRatio( cp->sizeNow, cp->tor->info.totalSize );
     246}
     247
     248uint64_t
     249tr_cpLeftUntilDone ( const tr_completion * cp )
     250{
     251    return tr_cpSizeWhenDone(cp) - cp->sizeNow;
    288252}
    289253
     
    291255tr_cpLeftUntilComplete ( const tr_completion * cp )
    292256{
    293     assert( cp->tor->info.totalSize >= cp->completeHave );
    294 
    295     return cp->tor->info.totalSize - cp->completeHave;
    296 }
    297 
    298 float
    299 tr_cpPercentDone( const tr_completion * cp )
    300 {
    301     tr_cpEnsureDoneValid( cp );
    302 
    303     return cp->doneTotal ? (double)cp->doneHave / cp->doneTotal : 1.0;
    304 }
    305 
    306 uint64_t
    307 tr_cpLeftUntilDone ( const tr_completion * cp )
    308 {
    309     tr_cpEnsureDoneValid( cp );
    310 
    311     return cp->doneTotal - cp->doneHave;
    312 }
    313 
    314 uint64_t
    315 tr_cpSizeWhenDone( const tr_completion * cp )
    316 {
    317     tr_cpEnsureDoneValid( cp );
    318 
    319     return cp->doneTotal;
     257    return cp->tor->info.totalSize - cp->sizeNow;
    320258}
    321259
     
    323261tr_cpGetStatus ( const tr_completion * cp )
    324262{
    325     assert( cp->tor->info.totalSize >= cp->completeHave );
    326 
    327     if( cp->completeHave == cp->tor->info.totalSize )
    328         return TR_CP_COMPLETE;
    329 
    330     tr_cpEnsureDoneValid( cp );
    331 
    332     return cp->doneHave >= cp->doneTotal ? TR_CP_DONE
    333                                          : TR_CP_INCOMPLETE;
     263    if( cp->sizeNow == cp->tor->info.totalSize ) return TR_CP_COMPLETE;
     264    if( cp->sizeNow == tr_cpSizeWhenDone(cp) ) return TR_CP_DONE;
     265    return TR_CP_INCOMPLETE;
    334266}
    335267
     
    338270{
    339271    uint64_t b = 0;
     272    tr_piece_index_t i;
    340273    const tr_torrent * tor = cp->tor;
    341     const tr_info * info = &tor->info;
    342     tr_piece_index_t i;
    343 
    344     for( i=0; i<info->pieceCount; ++i )
     274
     275    for( i=0; i<tor->info.pieceCount; ++i )
    345276        if( tr_cpPieceIsComplete( cp, i ) )
    346             ++b;
    347 
    348     b *= info->pieceSize;
    349 
    350     if( tr_cpPieceIsComplete( cp, info->pieceCount-1 ) )
    351         b -= (info->pieceSize - (info->totalSize % info->pieceSize));
     277            b += tr_torPieceCountBytes( tor, i );
    352278
    353279    return b;
     
    357283tr_cpHaveTotal( const tr_completion * cp )
    358284{
    359     return cp->completeHave;
    360 }
     285    return cp->sizeNow;
     286}
     287
     288void
     289tr_cpGetAmountDone( const tr_completion * cp, float * tab, int tabCount )
     290{
     291    const int tabSpan = tabCount / cp->tor->blockCount;
     292    tr_block_index_t block_i = 0;
     293    int tab_i;
     294    for( tab_i=0; tab_i<tabCount; ++tab_i ) {
     295        int loop, have;
     296        for( loop=have=0; loop<tabSpan; ++loop )
     297            if( tr_cpBlockIsComplete( cp, block_i++ ) )
     298                ++have;
     299        tab[tab_i] = (float)have / tabSpan;
     300    }
     301}
Note: See TracChangeset for help on using the changeset viewer.