Changeset 9782


Ignore:
Timestamp:
Dec 15, 2009, 8:13:34 PM (12 years ago)
Author:
charles
Message:

(trunk libT) #2548 "T's request queue can send out too many duplicate requests" -- experimental revision to r9465 to address further overdownloading issues

File:
1 edited

Legend:

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

    r9730 r9782  
    567567    const struct block_request * a = va;
    568568    const struct block_request * b = vb;
     569
     570    /* primary key: block */
    569571    if( a->block < b->block ) return -1;
    570572    if( a->block > b->block ) return 1;
     573
     574    /* secondary key: peer */
     575    if( a->peer < b->peer ) return -1;
     576    if( a->peer > b->peer ) return 1;
     577
    571578    return 0;
    572579}
     
    577584    const struct block_request * a = va;
    578585    const struct block_request * b = vb;
     586
     587    /* primary key: time */
    579588    if( a->sentAt < b->sentAt ) return -1;
    580589    if( a->sentAt > b->sentAt ) return 1;
     590
     591    /* secondary key: peer */
     592    if( a->peer < b->peer ) return -1;
     593    if( a->peer > b->peer ) return 1;
     594
    581595    return 0;
    582596}
     
    647661
    648662static struct block_request *
    649 requestListLookup( Torrent * t, tr_block_index_t block )
     663requestListLookup( Torrent * t, tr_block_index_t block, const tr_peer * peer )
    650664{
    651665    struct block_request key;
    652666    key.block = block;
     667    key.peer = (tr_peer*) peer;
    653668
    654669    requestListSort( t, REQ_SORTED_BY_BLOCK );
     
    659674}
    660675
    661 static void
    662 requestListRemove( Torrent * t, tr_block_index_t block )
    663 {
    664     const struct block_request * b = requestListLookup( t, block );
     676static int
     677countBlockRequests( Torrent * t, tr_block_index_t block )
     678{
     679    tr_bool exact;
     680    int i, n, pos;
     681    struct block_request key;
     682
     683    requestListSort( t, REQ_SORTED_BY_BLOCK );
     684    key.block = block;
     685    key.peer = NULL;
     686    pos = tr_lowerBound( &key, t->requests, t->requestCount,
     687                         sizeof( struct block_request ),
     688                         compareReqByBlock, &exact );
     689
     690    assert( !exact ); /* shouldn't have a request with .peer == NULL */
     691
     692    n = 0;
     693    for( i=pos; i<t->requestCount; ++i ) {
     694        if( t->requests[i].block == block )
     695            ++n;
     696        else
     697            break;
     698    }
     699
     700    return n;
     701}
     702
     703static void
     704requestListRemove( Torrent * t, tr_block_index_t block, const tr_peer * peer )
     705{
     706    const struct block_request * b = requestListLookup( t, block, peer );
    665707    if( b != NULL )
    666708    {
     
    921963    {
    922964        struct weighted_piece * p = pieces + i;
     965        const int missing = tr_cpMissingBlocksInPiece( &tor->completion, p->index );
     966        const int maxDuplicatesPerBlock = t->isInEndgame ? 3 : 1;
     967
     968        if( p->requestCount > ( missing * maxDuplicatesPerBlock ) )
     969            continue;
    923970
    924971        /* if the peer has this piece that we want... */
     
    930977            for( ; b!=e && got<numwant; ++b )
    931978            {
    932                 struct block_request * breq;
    933 
    934979                /* don't request blocks we've already got */
    935980                if( tr_cpBlockIsCompleteFast( &tor->completion, b ) )
    936981                    continue;
    937982
    938                 /* don't request blocks we've already requested (FIXME) */
    939                 breq = requestListLookup( t, b );
    940                 if( breq != NULL ) {
    941                     assert( breq->peer != NULL );
    942                     if( breq->peer == peer ) continue;
    943                     if( !t->isInEndgame ) continue;
    944                 }
    945 
     983                /* don't send the same request to the same peer twice */
     984                if( tr_peerMgrDidPeerRequest( tor, peer, b ) )
     985                    continue;
     986
     987                /* don't send the same request to any peer too many times */
     988                if( countBlockRequests( t, b ) > maxDuplicatesPerBlock )
     989                    continue;
     990
     991                /* update the caller's table */
    946992                setme[got++] = b;
    947993
    948994                /* update our own tables */
    949                 if( breq == NULL )
    950                     requestListAdd( t, now, b, peer );
     995                requestListAdd( t, now, b, peer );
    951996                ++p->requestCount;
    952997            }
     
    9551000
    9561001    /* In most cases we've just changed the weights of a small number of pieces.
    957      * So rather than qsort()ing the entire array, it's faster to sort just the
     1002     * So rather than qsort()ing the entire array, it's faster to sort only the
    9581003     * changed ones, then do a standard merge-two-sorted-arrays pass on the
    9591004     * changed and unchanged pieces. */
     
    10021047{
    10031048    const Torrent * t = tor->torrentPeers;
    1004     const struct block_request * b = requestListLookup( (Torrent*)t, block );
    1005     if( b == NULL ) return FALSE;
    1006     if( b->peer == peer ) return TRUE;
    1007     if( t->isInEndgame ) return TRUE;
    1008     return FALSE;
     1049    return requestListLookup( (Torrent*)t, block, peer ) != NULL;
    10091050}
    10101051
     
    11521193
    11531194static void
    1154 removeRequestFromTables( Torrent * t, tr_block_index_t block )
    1155 {
    1156     requestListRemove( t, block );
     1195removeRequestFromTables( Torrent * t, tr_block_index_t block, const tr_peer * peer )
     1196{
     1197    requestListRemove( t, block, peer );
    11571198    pieceListRemoveRequest( t, block );
    11581199}
     
    11711212
    11721213    for( i=0; i<n; ++i )
    1173         removeRequestFromTables( t, blocks[i] );
     1214        removeRequestFromTables( t, blocks[i], peer );
    11741215
    11751216    tr_free( blocks );
     
    12261267
    12271268        case TR_PEER_CLIENT_GOT_REJ:
    1228             removeRequestFromTables( t, _tr_block( t->tor, e->pieceIndex, e->offset ) );
     1269            removeRequestFromTables( t, _tr_block( t->tor, e->pieceIndex, e->offset ), peer );
    12291270            break;
    12301271
     
    12961337            tr_block_index_t block = _tr_block( tor, e->pieceIndex, e->offset );
    12971338
    1298             requestListRemove( t, block );
     1339            requestListRemove( t, block, peer );
    12991340            pieceListRemoveRequest( t, block );
    13001341
Note: See TracChangeset for help on using the changeset viewer.