Changeset 10301


Ignore:
Timestamp:
Mar 3, 2010, 4:16:18 AM (12 years ago)
Author:
charles
Message:

(trunk libT) #2993 "'Downloaded' much greater than 'Have' or 'Verified'" -- found a weighted piece sorting issue while trying to confirm or refute this issue.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/peer-mgr.c

    r10273 r10301  
    442442    t->webseeds = TR_PTR_ARRAY_INIT;
    443443    t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
    444     t->requests = 0;
    445444
    446445    for( i = 0; i < tor->info.webseedCount; ++i )
     
    546545***
    547546*** 2. Torrent::pieces, an array of "struct weighted_piece" which lists the
    548 ***    pieces that we want to request.  It's used to decide which pieces to
     547***    pieces that we want to request.  It's used to decide which blocks to
    549548***    return next when tr_peerMgrGetBlockRequests() is called.
    550549**/
     
    672671        decrementPendingReqCount( b );
    673672
    674         memmove( t->requests + pos,
    675                  t->requests + pos + 1,
    676                  sizeof( struct block_request ) * ( --t->requestCount - pos ) );
     673        tr_removeElementFromArray( t->requests,
     674                                   pos,
     675                                   sizeof( struct block_request ),
     676                                   t->requestCount-- );
     677
    677678        /*fprintf( stderr, "removing request of block %lu from peer %s... "
    678679                           "there are now %d block requests left\n",
     
    728729}
    729730
     731/**
     732 * This function is useful for sanity checking,
     733 * but is too expensive even for nightly builds...
     734 * let's leave it disabled but add an easy hook to compile it back in
     735 */
     736#if 1
     737static void
     738assertWeightedPiecesAreSorted( Torrent * t )
     739{
     740    int i;
     741    weightTorrent = t->tor;
     742    for( i=0; i<t->pieceCount-1; ++i )
     743        assert( comparePieceByWeight( &t->pieces[i], &t->pieces[i+1] ) <= 0 );
     744}
     745#else
     746#define assertWeightedPiecesAreSorted(t)
     747#endif
     748
    730749static int
    731750comparePieceByIndex( const void * va, const void * vb )
     
    760779isInEndgame( Torrent * t )
    761780{
    762     tr_bool endgame = TRUE;
     781    tr_bool endgame = FALSE;
    763782
    764783    if( ( t->pieces != NULL ) && ( t->pieceCount > 0 ) )
    765784    {
    766         const tr_completion * cp = &t->tor->completion;
    767785        const struct weighted_piece * p = t->pieces;
    768786        const int pending = p->requestCount;
    769         const int missing = tr_cpMissingBlocksInPiece( cp, p->index );
     787        const int missing = tr_cpMissingBlocksInPiece( &t->tor->completion, p->index );
    770788        endgame = pending >= missing;
    771789    }
     
    778796pieceListLookup( Torrent * t, tr_piece_index_t index )
    779797{
    780     const struct weighted_piece * limit = t->pieces;
    781     struct weighted_piece * piece = t->pieces + t->pieceCount - 1;
    782 
    783     if ( t->pieceCount == 0 ) return NULL;
    784 
    785     /* reverse linear search */
    786     for( ;; )
    787     {
    788         if( piece < limit ) return NULL;
    789         if( index == piece->index ) return piece; else --piece;
    790     }
     798    int i;
     799
     800    for( i=0; i<t->pieceCount; ++i )
     801        if( t->pieces[i].index == index )
     802            return &t->pieces[i];
     803
     804    return NULL;
    791805}
    792806
     
    794808pieceListRebuild( Torrent * t )
    795809{
     810    assertWeightedPiecesAreSorted( t );
     811
    796812    if( !tr_torrentIsSeed( t->tor ) )
    797813    {
     
    855871pieceListRemovePiece( Torrent * t, tr_piece_index_t piece )
    856872{
    857     struct weighted_piece * p = pieceListLookup( t, piece );
    858 
    859     if( p != NULL )
     873    struct weighted_piece * p;
     874
     875    assertWeightedPiecesAreSorted( t );
     876
     877    if(( p = pieceListLookup( t, piece )))
    860878    {
    861879        const int pos = p - t->pieces;
    862880
    863         memmove( t->pieces + pos,
    864                  t->pieces + pos + 1,
    865                  sizeof( struct weighted_piece ) * ( --t->pieceCount - pos ) );
     881        tr_removeElementFromArray( t->pieces,
     882                                   pos,
     883                                   sizeof( struct weighted_piece ),
     884                                   t->pieceCount-- );
    866885
    867886        if( t->pieceCount == 0 )
     
    871890        }
    872891    }
     892
     893    assertWeightedPiecesAreSorted( t );
     894}
     895
     896static void
     897pieceListResortPiece( Torrent * t, struct weighted_piece * p )
     898{
     899    int pos;
     900    tr_bool isSorted = TRUE;
     901
     902    if( p == NULL )
     903        return;
     904
     905    /* is the torrent already sorted? */
     906    pos = p - t->pieces;
     907    weightTorrent = t->tor;
     908    if( isSorted && ( pos > 0 ) && ( comparePieceByWeight( p-1, p ) > 0 ) )
     909        isSorted = FALSE;
     910    if( isSorted && ( pos < t->pieceCount - 1 ) && ( comparePieceByWeight( p, p+1 ) > 0 ) )
     911        isSorted = FALSE;
     912
     913    /* if it's not sorted, move it around */
     914    if( !isSorted )
     915    {
     916        tr_bool exact;
     917        const struct weighted_piece tmp = *p;
     918
     919        tr_removeElementFromArray( t->pieces,
     920                                   pos,
     921                                   sizeof( struct weighted_piece ),
     922                                   t->pieceCount-- );
     923
     924        pos = tr_lowerBound( &tmp, t->pieces, t->pieceCount,
     925                             sizeof( struct weighted_piece ),
     926                             comparePieceByWeight, &exact );
     927
     928        memmove( &t->pieces[pos + 1],
     929                 &t->pieces[pos],
     930                 sizeof( struct weighted_piece ) * ( t->pieceCount++ - pos ) );
     931
     932        t->pieces[pos] = tmp;
     933    }
     934
     935    assertWeightedPiecesAreSorted( t );
    873936}
    874937
     
    876939pieceListRemoveRequest( Torrent * t, tr_block_index_t block )
    877940{
     941    struct weighted_piece * p;
    878942    const tr_piece_index_t index = tr_torBlockPiece( t->tor, block );
    879     const struct weighted_piece * p = pieceListLookup( t, index );
    880 
    881     if( p != NULL )
    882     {
    883         const int pos = p - t->pieces;
    884         struct weighted_piece piece = t->pieces[pos];
    885         int newpos;
    886         tr_bool exact;
    887 
    888         /* remove request */
    889         if( piece.requestCount > 0 )
    890             --piece.requestCount;
    891 
    892         /* List is nearly sorted (by weight) : insert piece into the right place. */
    893 
    894         weightTorrent = t->tor;
    895         newpos = tr_lowerBound( &piece, t->pieces, t->pieceCount,
    896                                 sizeof( struct weighted_piece ),
    897                                 comparePieceByWeight, &exact );
    898 
    899         if( newpos == pos || newpos == pos + 1 )
    900         {
    901             /* it's VERY likely that piece keeps its position */
    902             t->pieces[pos].requestCount = piece.requestCount;
    903         }
    904         else
    905         {
    906             /* piece is removed temporally to make insertion easier */
    907             memmove( &t->pieces[pos],
    908                      &t->pieces[pos + 1],
    909                      sizeof( struct weighted_piece ) * ( --t->pieceCount - pos ) );
    910 
    911             if( newpos > pos ) --newpos;
    912 
    913             memmove( &t->pieces[newpos + 1],
    914                      &t->pieces[newpos],
    915                      sizeof( struct weighted_piece ) * ( t->pieceCount++ - newpos ) );
    916 
    917             t->pieces[newpos] = piece;
    918         }
    919     }
     943
     944    assertWeightedPiecesAreSorted( t );
     945
     946    if( ((p = pieceListLookup( t, index ))) && ( p->requestCount > 0 ) )
     947    {
     948        --p->requestCount;
     949        pieceListResortPiece( t, p );
     950    }
     951
     952    assertWeightedPiecesAreSorted( t );
    920953}
    921954
     
    953986    got = 0;
    954987    t = tor->torrentPeers;
     988    assertWeightedPiecesAreSorted( t );
    955989
    956990    /* prep the pieces list */
     
    10291063    }
    10301064
     1065    assertWeightedPiecesAreSorted( t );
    10311066    *numgot = got;
    10321067}
     
    13311366            {
    13321367                tr_cpBlockAdd( &tor->completion, block );
     1368                pieceListResortPiece( t, pieceListLookup( t, e->pieceIndex ) );
    13331369                tr_torrentSetDirty( tor );
    13341370
Note: See TracChangeset for help on using the changeset viewer.