Changeset 12035


Ignore:
Timestamp:
Feb 24, 2011, 3:58:47 PM (11 years ago)
Author:
jordan
Message:

(2.2x) backport r11892 for #3656 "endgame should be faster" -- patch by harrydb

Location:
branches/2.2x/libtransmission
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2x/libtransmission/completion.c

    r11797 r12035  
    2828    cp->sizeNow = 0;
    2929    cp->sizeWhenDoneIsDirty = 1;
     30    cp->blocksWantedIsDirty = 1;
    3031    cp->haveValidIsDirty = 1;
    3132}
     
    5556{
    5657    cp->sizeWhenDoneIsDirty = 1;
     58    cp->blocksWantedIsDirty = 1;
     59}
     60
     61tr_block_index_t
     62tr_cpBlocksMissing( const tr_completion * ccp )
     63{
     64    if( ccp->blocksWantedIsDirty )
     65    {
     66        tr_completion *    cp = (tr_completion *) ccp; /* mutable */
     67        const tr_torrent * tor = cp->tor;
     68        const tr_info *    info = &tor->info;
     69        tr_piece_index_t   i;
     70        tr_block_index_t   wanted = 0;
     71        tr_block_index_t   complete = 0;
     72
     73        for( i = 0; i < info->pieceCount; ++i )
     74        {
     75            if( info->pieces[i].dnd )
     76                continue;
     77
     78            wanted += tr_torPieceCountBlocks( tor, i );
     79            complete += cp->completeBlocks[i];
     80        }
     81
     82        cp->blocksWantedLazy = wanted;
     83        cp->blocksWantedCompleteLazy = complete;
     84        cp->blocksWantedIsDirty = FALSE;
     85    }
     86
     87    return ccp->blocksWantedLazy - ccp->blocksWantedCompleteLazy;
    5788}
    5889
     
    133164            cp->sizeNow -= tr_torBlockCountBytes( tor, block );
    134165
     166    if( !tor->info.pieces[piece].dnd )
     167        cp->blocksWantedCompleteLazy -= cp->completeBlocks[piece];
     168
    135169    cp->sizeWhenDoneIsDirty = 1;
    136170    cp->haveValidIsDirty = 1;
     
    159193
    160194        cp->sizeNow += blockSize;
     195        if( !tor->info.pieces[piece].dnd )
     196            cp->blocksWantedCompleteLazy++;
    161197
    162198        cp->haveValidIsDirty = 1;
     
    180216        cp->completeBlocks[i] = tr_torPieceCountBlocks( tor, i );
    181217    cp->sizeWhenDoneIsDirty = 1;
     218    cp->blocksWantedIsDirty = 1;
    182219    cp->haveValidIsDirty = 1;
    183220}
     
    211248        /* invalidate the fields that are lazy-evaluated */
    212249        cp->sizeWhenDoneIsDirty = TRUE;
     250        cp->blocksWantedIsDirty = TRUE;
    213251        cp->haveValidIsDirty = TRUE;
    214252
  • branches/2.2x/libtransmission/completion.h

    r11709 r12035  
    2626{
    2727    tr_bool  sizeWhenDoneIsDirty;
     28    tr_bool  blocksWantedIsDirty;
    2829    tr_bool  haveValidIsDirty;
    2930
     
    3839    /* a block is complete if and only if we have it */
    3940    uint16_t *  completeBlocks;
     41
     42    /* total number of blocks that we want downloaded
     43       DON'T access this directly; it's a lazy field.
     44       Used by tr_cpBlocksMissing(). */
     45    tr_block_index_t    blocksWantedLazy;
     46
     47    /* total number of completed blocks that we want downloaded
     48       DON'T access this directly; it's a lazy field.
     49       Used by tr_cpBlocksMissing(). */
     50    tr_block_index_t    blocksWantedCompleteLazy;
    4051
    4152    /* number of bytes we'll have when done downloading. [0..info.totalSize]
     
    6980
    7081uint64_t                   tr_cpHaveValid( const tr_completion * );
     82
     83tr_block_index_t           tr_cpBlocksMissing( const tr_completion * );
    7184
    7285uint64_t                   tr_cpSizeWhenDone( const tr_completion * );
  • branches/2.2x/libtransmission/peer-mgr.c

    r12032 r12035  
    205205    int                        maxPeers;
    206206    time_t                     lastCancel;
     207
     208    /* Before the endgame this should be 0. In endgame, is contains the average
     209     * number of pending requests per peer. Only peers which have more pending
     210     * requests are considered 'fast' are allowed to request a block that's
     211     * already been requested from another (slower?) peer. */
     212    int                        endgame;
    207213}
    208214Torrent;
     
    727733}
    728734
    729 /* how many peers are we currently requesting this block from... */
    730 static int
    731 countBlockRequests( Torrent * t, tr_block_index_t block )
     735/**
     736 * Find the peers are we currently requesting the block
     737 * with index @a block from and append them to @a peerArr.
     738 */
     739static void
     740getBlockRequestPeers( Torrent * t, tr_block_index_t block,
     741                      tr_ptrArray * peerArr )
    732742{
    733743    tr_bool exact;
    734     int i, n, pos;
     744    int i, pos;
    735745    struct block_request key;
    736746
     
    743753    assert( !exact ); /* shouldn't have a request with .peer == NULL */
    744754
    745     n = 0;
    746     for( i=pos; i<t->requestCount; ++i ) {
    747         if( t->requests[i].block == block )
    748             ++n;
    749         else
     755    for( i = pos; i < t->requestCount; ++i )
     756    {
     757        if( t->requests[i].block != block )
    750758            break;
    751     }
    752 
    753     return n;
     759        tr_ptrArrayAppend( peerArr, t->requests[i].peer );
     760    }
    754761}
    755762
     
    855862}
    856863
    857 static tr_bool
    858 isInEndgame( Torrent * t )
    859 {
    860     tr_bool endgame = FALSE;
    861 
    862     if( ( t->pieces != NULL ) && ( t->pieceCount > 0 ) )
    863     {
    864         const struct weighted_piece * p = t->pieces;
    865         const int pending = p->requestCount;
    866         const int missing = tr_cpMissingBlocksInPiece( &t->tor->completion, p->index );
    867         endgame = pending >= missing;
    868     }
    869 
    870     /*if( endgame ) fprintf( stderr, "ENDGAME reached\n" );*/
    871     return endgame;
     864static int
     865countActiveWebseeds( const Torrent * t )
     866{
     867    int activeCount = 0;
     868    const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase( &t->webseeds );
     869    const tr_webseed ** const wend = w + tr_ptrArraySize( &t->webseeds );
     870
     871    for( ; w!=wend; ++w )
     872        if( tr_webseedIsActive( *w ) )
     873            ++activeCount;
     874
     875    return activeCount;
     876}
     877
     878static void
     879updateEndgame( Torrent * t )
     880{
     881    const tr_torrent * tor = t->tor;
     882    const tr_block_index_t missing = tr_cpBlocksMissing( &tor->completion );
     883
     884    assert( t->requestCount >= 0 );
     885
     886    if( (tr_block_index_t) t->requestCount < missing )
     887    {
     888        /* not in endgame */
     889        t->endgame = 0;
     890    }
     891    else if( !t->endgame ) /* only recalculate when endgame first begins */
     892    {
     893        int numDownloading = 0;
     894        const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase( &t->peers );
     895        const tr_peer ** const pend = p + tr_ptrArraySize( &t->peers );
     896
     897        /* add the active bittorrent peers... */
     898        for( ; p!=pend; ++p )
     899            if( (*p)->pendingReqsToPeer > 0 )
     900                ++numDownloading;
     901
     902        /* add the active webseeds... */
     903        numDownloading += countActiveWebseeds( t );
     904
     905        /* average number of pending requests per downloading peer */
     906        t->endgame = t->requestCount / MAX( numDownloading, 1 );
     907    }
    872908}
    873909
     
    881917assertWeightedPiecesAreSorted( Torrent * t )
    882918{
    883     if( !isInEndgame( t ) )
     919    if( !t->endgame )
    884920    {
    885921        int i;
     
    10751111    int got;
    10761112    Torrent * t;
    1077     tr_bool endgame;
    10781113    struct weighted_piece * pieces;
    10791114    const tr_bitset * have = &peer->have;
     
    10941129        pieceListRebuild( t );
    10951130
    1096     endgame = isInEndgame( t );
    1097 
     1131    updateEndgame( t );
    10981132    pieces = t->pieces;
    10991133    for( i=0; i<t->pieceCount && got<numwant; ++i )
    11001134    {
    11011135        struct weighted_piece * p = pieces + i;
    1102         const int missing = tr_cpMissingBlocksInPiece( &tor->completion, p->index );
    1103         const int maxDuplicatesPerBlock = endgame ? 3 : 1;
    1104 
    1105         if( p->requestCount > ( missing * maxDuplicatesPerBlock ) )
    1106             continue;
    11071136
    11081137        /* if the peer has this piece that we want... */
     
    11111140            tr_block_index_t b = tr_torPieceFirstBlock( tor, p->index );
    11121141            const tr_block_index_t e = b + tr_torPieceCountBlocks( tor, p->index );
     1142            tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
    11131143
    11141144            for( ; b!=e && got<numwant; ++b )
    11151145            {
     1146                int peerCount;
     1147                tr_peer ** peers;
     1148
    11161149                /* don't request blocks we've already got */
    11171150                if( tr_cpBlockIsCompleteFast( &tor->completion, b ) )
    11181151                    continue;
    11191152
    1120                 /* don't send the same request to the same peer twice */
    1121                 if( tr_peerMgrDidPeerRequest( tor, peer, b ) )
    1122                     continue;
    1123 
    1124                 /* don't send the same request to any peer too many times */
    1125                 if( countBlockRequests( t, b ) >= maxDuplicatesPerBlock )
    1126                     continue;
     1153                /* always add peer if this block has no peers yet */
     1154                tr_ptrArrayClear( &peerArr );
     1155                getBlockRequestPeers( t, b, &peerArr );
     1156                peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
     1157                if( peerCount != 0 )
     1158                {
     1159                    /* don't make a second block request until the endgame */
     1160                    if( !t->endgame )
     1161                        continue;
     1162
     1163                    /* don't have more than two peers requesting this block */
     1164                    if( peerCount > 1 )
     1165                        continue;
     1166
     1167                    /* don't send the same request to the same peer twice */
     1168                    if( peer == peers[0] )
     1169                        continue;
     1170
     1171                    /* in the endgame allow an additional peer to download a
     1172                       block but only if the peer seems to be handling requests
     1173                       relatively fast */
     1174                    if( peer->pendingReqsToPeer + numwant - got < t->endgame )
     1175                        continue;
     1176                }
    11271177
    11281178                /* update the caller's table */
     
    11331183                ++p->requestCount;
    11341184            }
     1185
     1186            tr_ptrArrayDestruct( &peerArr, NULL );
    11351187        }
    11361188    }
     
    14241476            tr_torrent * tor = t->tor;
    14251477            tr_block_index_t block = _tr_block( tor, e->pieceIndex, e->offset );
    1426 
    1427             requestListRemove( t, block, peer );
    1428             pieceListRemoveRequest( t, block );
     1478            int i, peerCount;
     1479            tr_peer ** peers;
     1480            tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
     1481
     1482            removeRequestFromTables( t, block, peer );
     1483            getBlockRequestPeers( t, block, &peerArr );
     1484            peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
     1485
     1486            /* remove additional block requests and send cancel to peers */
     1487            for( i=0; i<peerCount; i++ ) {
     1488                tr_peer * p = peers[i];
     1489                assert( p != peer );
     1490                if( p->msgs ) {
     1491                    tr_historyAdd( p->cancelsSentToPeer, tr_time( ), 1 );
     1492                    tr_peerMsgsCancel( p->msgs, block );
     1493                }
     1494                removeRequestFromTables( t, block, p );
     1495            }
     1496
     1497            tr_ptrArrayDestruct( &peerArr, FALSE );
    14291498
    14301499            if( peer && peer->blocksSentToClient )
     
    22222291    const Torrent * t = tor->torrentPeers;
    22232292    const tr_peer ** peers;
    2224     const tr_webseed ** webseeds;
    22252293
    22262294    assert( tr_torrentIsLocked( tor ) );
     
    22612329    }
    22622330
    2263     webseeds = (const tr_webseed**) tr_ptrArrayBase( &t->webseeds );
    2264     size = tr_ptrArraySize( &t->webseeds );
    2265     for( i=0; i<size; ++i )
    2266         if( tr_webseedIsActive( webseeds[i] ) )
    2267             ++*setmeWebseedsSendingToUs;
     2331    *setmeWebseedsSendingToUs = countActiveWebseeds( t );
    22682332}
    22692333
Note: See TracChangeset for help on using the changeset viewer.