Changeset 4340


Ignore:
Timestamp:
Dec 26, 2007, 7:25:50 AM (14 years ago)
Author:
charles
Message:

add per-priority-level endgame mode

File:
1 edited

Legend:

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

    r4326 r4340  
    701701getPreferredBlocks( Torrent * t, uint64_t * setmeCount )
    702702{
     703    int s;
    703704    uint32_t i;
    704705    uint32_t pieceCount;
     706    uint32_t blockCount;
     707    uint32_t unreqCount[3], reqCount[3];
    705708    uint32_t * pieces;
    706     uint64_t *req, *unreq, *ret, *walk;
    707     int reqCount, unreqCount;
     709    uint64_t * ret, * walk;
     710    uint64_t * unreq[3], *req[3];
    708711    const tr_torrent * tor = t->tor;
    709712
     
    712715    pieces = getPreferredPieces( t, &pieceCount );
    713716
    714     req = tr_new( uint64_t, pieceCount *  tor->blockCountInPiece );
    715     reqCount = 0;
    716     unreq = tr_new( uint64_t, pieceCount *  tor->blockCountInPiece );
    717     unreqCount = 0;
    718 
    719     for( i=0; i<pieceCount; ++i ) {
     717    /**
     718     * Now we walk through those preferred pieces to find all the blocks
     719     * are still missing from them.  We put unrequested blocks first,
     720     * of course, but by including requested blocks afterwards, endgame
     721     * handling happens naturally.
     722     *
     723     * By doing this once per priority we also effectively get an endgame
     724     * mode for each priority level.  The helps keep high priority files
     725     * from getting stuck at 99% due of unresponsive peers.
     726     */
     727
     728    /* make temporary bins for the four tiers of blocks */
     729    for( i=0; i<3; ++i ) {
     730        req[i] = tr_new( uint64_t, pieceCount *  tor->blockCountInPiece );
     731        reqCount[i] = 0;
     732        unreq[i] = tr_new( uint64_t, pieceCount *  tor->blockCountInPiece );
     733        unreqCount[i] = 0;
     734    }
     735
     736    /* sort the blocks into our temp bins */
     737    for( i=blockCount=0; i<pieceCount; ++i )
     738    {
    720739        const uint32_t index = pieces[i];
     740        const int priorityIndex = tor->info.pieces[index].priority + 1;
    721741        const int begin = tr_torPieceFirstBlock( tor, index );
    722742        const int end = begin + tr_torPieceCountBlocks( tor, (int)index );
    723743        int block;
     744
    724745        for( block=begin; block<end; ++block )
     746        {
    725747            if( tr_cpBlockIsComplete( tor->completion, block ) )
    726748                continue;
    727             else if( tr_bitfieldHas( t->requested, block ) )
    728                 req[reqCount++] = block;
     749
     750            ++blockCount;
     751
     752            if( tr_bitfieldHas( t->requested, block ) )
     753            {
     754                const uint32_t n = reqCount[priorityIndex]++;
     755                req[priorityIndex][n] = block;
     756            }
    729757            else
    730                 unreq[unreqCount++] = block;
    731     }
    732 
    733     ret = walk = tr_new( uint64_t, unreqCount + reqCount );
    734     memcpy( walk, unreq, sizeof(uint64_t) * unreqCount );
    735     walk += unreqCount;
    736     memcpy( walk, req, sizeof(uint64_t) * reqCount );
    737     walk += reqCount;
    738     assert( ( walk - ret ) == ( unreqCount + reqCount ) );
    739     *setmeCount = walk - ret;
    740 
    741     tr_free( req );
    742     tr_free( unreq );
     758            {
     759                const uint32_t n = unreqCount[priorityIndex]++;
     760                unreq[priorityIndex][n] = block;
     761            }
     762        }
     763    }
     764
     765    /* join the bins together, going from highest priority to lowest so
     766     * the the blocks we want to request first will be first in the list */
     767    ret = walk = tr_new( uint64_t, blockCount );
     768    for( s=2; s>=0; --s ) {
     769        memcpy( walk, unreq[s], sizeof(uint64_t) * unreqCount[s] );
     770        walk += unreqCount[s];
     771        memcpy( walk, req[s], sizeof(uint64_t) * reqCount[s] );
     772        walk += reqCount[s];
     773    }
     774    assert( ( walk - ret ) == blockCount );
     775    *setmeCount = blockCount;
     776
     777    /* cleanup */
    743778    tr_free( pieces );
    744 
     779    for( i=0; i<3; ++i ) {
     780        tr_free( unreq[i] );
     781        tr_free( req[i] );
     782    }
    745783    return ret;
    746784}
Note: See TracChangeset for help on using the changeset viewer.