Changeset 8781
- Timestamp:
- Jul 5, 2009, 6:28:36 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/peer-mgr.c
r8767 r8781 1947 1947 1948 1948 static void 1949 rechokeTorrent( Torrent * t )1949 rechokeTorrent( Torrent * t, const uint64_t now ) 1950 1950 { 1951 1951 int i, size, unchokedInterested; … … 1955 1955 const tr_session * session = t->manager->session; 1956 1956 const int chokeAll = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER ); 1957 const uint64_t now = tr_date( );1958 1957 1959 1958 assert( torrentIsLocked( t ) ); … … 2049 2048 rechokePulse( void * vmgr ) 2050 2049 { 2050 uint64_t now; 2051 2051 tr_torrent * tor = NULL; 2052 2052 tr_peerMgr * mgr = vmgr; 2053 2053 managerLock( mgr ); 2054 2054 2055 now = tr_date( ); 2055 2056 while(( tor = tr_torrentNext( mgr->session, tor ))) 2056 2057 if( tor->isRunning ) 2057 rechokeTorrent( tor->torrentPeers );2058 rechokeTorrent( tor->torrentPeers, now ); 2058 2059 2059 2060 managerUnlock( mgr ); … … 2410 2411 } 2411 2412 2413 struct peer_liveliness 2414 { 2415 tr_peer * peer; 2416 int speed; 2417 time_t pieceDataTime; 2418 time_t time; 2419 void * clientData; 2420 }; 2421 2422 static int 2423 comparePeerLiveliness( 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 */ 2441 static void 2442 sortPeersFromBestToWorst( 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 2473 static void 2474 enforceTorrentPeerLimit( 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 2488 static void 2489 enforceSessionPeerLimit( 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 2412 2534 static int 2413 2535 reconnectPulse( void * vmgr ) 2414 2536 { 2415 tr_torrent * tor = NULL;2537 tr_torrent * tor; 2416 2538 tr_peerMgr * mgr = vmgr; 2539 uint64_t now; 2417 2540 managerLock( mgr ); 2418 2541 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; 2419 2554 while(( tor = tr_torrentNext( mgr->session, tor ))) 2420 2555 if( tor->isRunning )
Note: See TracChangeset
for help on using the changeset viewer.