Changeset 8781


Ignore:
Timestamp:
Jul 5, 2009, 6:28:36 PM (13 years ago)
Author:
charles
Message:

(trunk libT) #1841: Transmission doesn't stick to maximum peer limits

File:
1 edited

Legend:

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

    r8767 r8781  
    19471947
    19481948static void
    1949 rechokeTorrent( Torrent * t )
     1949rechokeTorrent( Torrent * t, const uint64_t now )
    19501950{
    19511951    int i, size, unchokedInterested;
     
    19551955    const tr_session * session = t->manager->session;
    19561956    const int chokeAll = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER );
    1957     const uint64_t now = tr_date( );
    19581957
    19591958    assert( torrentIsLocked( t ) );
     
    20492048rechokePulse( void * vmgr )
    20502049{
     2050    uint64_t now;
    20512051    tr_torrent * tor = NULL;
    20522052    tr_peerMgr * mgr = vmgr;
    20532053    managerLock( mgr );
    20542054
     2055    now = tr_date( );
    20552056    while(( tor = tr_torrentNext( mgr->session, tor )))
    20562057        if( tor->isRunning )
    2057             rechokeTorrent( tor->torrentPeers );
     2058            rechokeTorrent( tor->torrentPeers, now );
    20582059
    20592060    managerUnlock( mgr );
     
    24102411}
    24112412
     2413struct peer_liveliness
     2414{
     2415    tr_peer * peer;
     2416    int speed;
     2417    time_t pieceDataTime;
     2418    time_t time;
     2419    void * clientData;
     2420};
     2421
     2422static int
     2423comparePeerLiveliness( const void * va, const void * vb )
     2424{
     2425    const struct peer_liveliness * a = va;
     2426    const struct peer_liveliness * b = vb;
     2427
     2428    if( a->speed != b->speed ) /* faster goes first */
     2429        return a->speed > b->speed ? -1 : 1;
     2430
     2431    if( a->pieceDataTime != b->pieceDataTime ) /* the one to give us data more recently goes first */
     2432        return a->pieceDataTime > b->pieceDataTime ? -1 : 1;
     2433
     2434    if( a->time != b->time ) /* the one we connected to most recently goes first */
     2435        return a->time > b->time ? -1 : 1;
     2436
     2437    return 0;
     2438}
     2439
     2440/* FIXME: getPeersToClose() should use this */
     2441static void
     2442sortPeersFromBestToWorst( tr_peer ** peers, void** clientData, int n, uint64_t now )
     2443{
     2444    int i;
     2445    struct peer_liveliness * l;
     2446
     2447    /* build a sortable array of peer + extra info */
     2448    l = tr_new0( struct peer_liveliness, n );
     2449    for( i=0; i<n; ++i ) {
     2450        tr_peer * p = peers[i];
     2451        l[i].peer = p;
     2452        l[i].speed = 1024.0 * (tr_peerGetPieceSpeed( p, now, TR_UP ) + tr_peerGetPieceSpeed( p, now, TR_DOWN ));
     2453        l[i].pieceDataTime = p->atom->piece_data_time;
     2454        l[i].time = p->atom->time;
     2455        if( clientData )
     2456            l[i].clientData = clientData[i];
     2457    }
     2458
     2459    /* sort 'em */
     2460    qsort( l, n, sizeof(struct peer_liveliness), comparePeerLiveliness );
     2461
     2462    /* build the peer array */
     2463    for( i=0; i<n; ++i ) {
     2464        peers[i] = l[i].peer;
     2465        if( clientData )
     2466            clientData[i] = l[i].clientData;
     2467    }
     2468
     2469    /* cleanup */
     2470    tr_free( l );
     2471}
     2472
     2473static void
     2474enforceTorrentPeerLimit( Torrent * t, uint64_t now )
     2475{
     2476    int n = tr_ptrArraySize( &t->peers );
     2477    const int max = tr_sessionGetPeerLimitPerTorrent( t->tor->session );
     2478    if( n > max )
     2479    {
     2480        tr_peer ** peers = tr_memdup( tr_ptrArrayBase( &t->peers ), n*sizeof(tr_peer*) );
     2481        sortPeersFromBestToWorst( peers, NULL, n, now );
     2482        while( n > max )
     2483            closePeer( t, peers[--n] );
     2484        tr_free( peers );
     2485    }
     2486}
     2487
     2488static void
     2489enforceSessionPeerLimit( tr_session * session, uint64_t now )
     2490{
     2491    int n;
     2492    tr_torrent * tor;
     2493    const int max = tr_sessionGetPeerLimit( session );
     2494
     2495    /* count the total number of peers */
     2496    n = 0;
     2497    tor = NULL;
     2498    while(( tor = tr_torrentNext( session, tor )))
     2499        n += tr_ptrArraySize( &tor->torrentPeers->peers );
     2500
     2501    /* if there are too many, prune out the worst */
     2502    if( n > max )
     2503    {
     2504        int n = 0;
     2505        tr_peer ** peers = tr_new( tr_peer*, n );
     2506        Torrent ** torrents = tr_new( Torrent*, n );
     2507
     2508        /* populate the peer array */
     2509        tor = NULL;
     2510        while(( tor = tr_torrentNext( session, tor ))) {
     2511            int i;
     2512            Torrent * t = tor->torrentPeers;
     2513            const int tn = tr_ptrArraySize( &t->peers );
     2514            for( i=0; i<tn; ++i, ++n ) {
     2515                peers[n] = tr_ptrArrayNth( &t->peers, i );
     2516                torrents[n] = t;
     2517            }
     2518        }
     2519       
     2520        /* sort 'em */
     2521        sortPeersFromBestToWorst( peers, (void**)torrents, n, now );
     2522
     2523        /* cull out the crappiest */
     2524        while( n-- > max )
     2525            closePeer( torrents[n], peers[n] );
     2526
     2527        /* cleanup */
     2528        tr_free( torrents );
     2529        tr_free( peers );
     2530    }
     2531}
     2532
     2533
    24122534static int
    24132535reconnectPulse( void * vmgr )
    24142536{
    2415     tr_torrent * tor = NULL;
     2537    tr_torrent * tor;
    24162538    tr_peerMgr * mgr = vmgr;
     2539    uint64_t now;
    24172540    managerLock( mgr );
    24182541
     2542    now = tr_date( );
     2543
     2544    /* if we're over the per-torrent peer limits, cull some peers */
     2545    tor = NULL;
     2546    while(( tor = tr_torrentNext( mgr->session, tor )))
     2547        if( tor->isRunning )
     2548            enforceTorrentPeerLimit( tor->torrentPeers, now );
     2549
     2550    /* if we're over the per-session peer limits, cull some peers */
     2551    enforceSessionPeerLimit( mgr->session, now );
     2552
     2553    tor = NULL;
    24192554    while(( tor = tr_torrentNext( mgr->session, tor )))
    24202555        if( tor->isRunning )
Note: See TracChangeset for help on using the changeset viewer.