Changeset 2177 for trunk/libtransmission/peer.c
- Timestamp:
- Jun 21, 2007, 2:47:26 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/peer.c
r2149 r2177 26 26 #include "peertree.h" 27 27 28 /***** 29 ****** 30 *****/ 31 32 /** 33 *** The "SWIFT" system is described by Karthik Tamilmani, 34 *** Vinay Pai, and Alexander Mohr of Stony Brook University 35 *** in their paper "SWIFT: A System With Incentives For Trading" 36 *** http://citeseer.ist.psu.edu/tamilmani04swift.html 37 **/ 38 39 /** 40 * Use SWIFT? 41 */ 42 static const int SWIFT_ENABLED = 1; 43 44 /** 45 * For every byte the peer uploads to us, 46 * allow them to download this many bytes from us 47 */ 48 static const double SWIFT_REPAYMENT_RATIO = 1.1; 49 50 /** 51 * Allow new peers to download this many bytes from 52 * us when getting started. This can prevent gridlock 53 * with other peers using tit-for-tat algorithms 54 */ 55 static const int SWIFT_INITIAL_CREDIT = 64 * 1024; /* 64 KiB */ 56 57 /** 58 * We expend a fraction of our torrent's total upload speed 59 * on on largesse by uniformly distributing free credit to 60 * all of our peers. This too helps prevent gridlock. 61 */ 62 static const double SWIFT_LARGESSE = 0.05; /* 5% of our UL */ 63 64 /** 65 * How frequently to extend largesse-based credit 66 */ 67 static const int SWIFT_REFRESH_INTERVAL_SEC = 5; 68 69 /***** 70 ****** 71 *****/ 72 28 73 #define PERCENT_PEER_WANTED 25 /* Percent before we start relax peers min activeness */ 29 74 #define MIN_UPLOAD_IDLE 60000 /* In high peer situations we wait only 1 min … … 40 85 during high peer situations */ 41 86 #define MAX_REQUEST_COUNT 32 42 #define OUR_REQUEST_COUNT 8/* TODO: we should detect if we are on a87 #define OUR_REQUEST_COUNT 12 /* TODO: we should detect if we are on a 43 88 high-speed network and adapt */ 44 89 #define PEX_PEER_CUTOFF 50 /* only try to add new peers from pex if … … 151 196 152 197 char * client; 198 199 int64_t credit; 153 200 }; 154 201 … … 191 238 peer->port = port; 192 239 peer->from = from; 240 peer->credit = SWIFT_INITIAL_CREDIT; 193 241 if( s >= 0 ) 194 242 { … … 220 268 tr_bitfieldFree( peer->blamefield ); 221 269 tr_bitfieldFree( peer->banfield ); 222 if( peer->buf ) 223 { 224 free( peer->buf ); 225 } 226 if( peer->outMessages ) 227 { 228 free( peer->outMessages ); 229 } 270 tr_free( peer->buf ); 271 tr_free( peer->outMessages ); 230 272 if( peer->status > PEER_STATUS_IDLE ) 231 273 { … … 331 373 if( NULL != tor ) 332 374 { 333 tr_rcTransferred( peer->download, ret );334 tr_rcTransferred( tor->download, ret );335 if ( !tor->customDownloadLimit )336 {337 tr_rcTransferred( tor->handle->download, ret );338 }339 340 375 if( tr_peerAmInterested( peer ) && !tr_peerIsChoking( peer ) ) 341 376 { … … 360 395 } 361 396 362 uint64_t tr_peerDate( tr_peer_t * peer )397 uint64_t tr_peerDate( const tr_peer_t * peer ) 363 398 { 364 399 return peer->date; 365 }366 367 /***********************************************************************368 * tr_peerId369 ***********************************************************************370 *371 **********************************************************************/372 uint8_t * tr_peerId( tr_peer_t * peer )373 {374 return & peer->id[0];375 400 } 376 401 … … 390 415 * 391 416 **********************************************************************/ 392 uint8_t * tr_peerHash(tr_peer_t * peer )417 const uint8_t * tr_peerHash( const tr_peer_t * peer ) 393 418 { 394 419 return parseBufHash( peer ); … … 406 431 uint8_t * p; 407 432 uint64_t date; 433 const int isSeeding = tr_cpGetStatus( tor->completion ) != TR_CP_INCOMPLETE; 408 434 409 435 if( ( ret = checkPeer( peer ) ) ) … … 512 538 while( ( p = blockPending( tor, peer, &size ) ) ) 513 539 { 540 if( SWIFT_ENABLED && !isSeeding && (peer->credit<0) ) 541 { 542 break; 543 } 544 514 545 if( tor->customUploadLimit 515 546 ? !tr_rcCanTransfer( tor->upload ) … … 530 561 531 562 blockSent( peer, ret ); 532 tr_rcTransferred( peer->upload, ret ); 533 tr_rcTransferred( tor->upload, ret ); 534 if ( !tor->customUploadLimit ) 535 { 536 tr_rcTransferred( tor->handle->upload, ret ); 537 } 563 564 if( ret > 0 ) 565 tr_peerGotBlockFromUs( peer, ret ); 538 566 539 567 tor->uploadedCur += ret; … … 555 583 556 584 /* Ask for a block whenever possible */ 557 if( tr_cpGetStatus( tor->completion ) == TR_CP_INCOMPLETE585 if( !isSeeding 558 586 && !peer->amInterested 559 587 && tor->peerCount > TR_MAX_PEER_COUNT - 2 ) … … 605 633 } 606 634 607 /*********************************************************************** 608 * tr_peerIsConnected 609 *********************************************************************** 610 * 611 **********************************************************************/ 612 int tr_peerIsConnected( tr_peer_t * peer ) 635 int tr_peerIsConnected( const tr_peer_t * peer ) 613 636 { 614 637 return PEER_STATUS_CONNECTED == peer->status; 615 638 } 616 639 617 /*********************************************************************** 618 * tr_peerIsIncoming 619 *********************************************************************** 620 * 621 **********************************************************************/ 622 int tr_peerIsFrom( tr_peer_t * peer ) 640 int tr_peerIsFrom( const tr_peer_t * peer ) 623 641 { 624 642 return peer->from; 625 643 } 626 644 627 int tr_peerAmChoking( tr_peer_t * peer )645 int tr_peerAmChoking( const tr_peer_t * peer ) 628 646 { 629 647 return peer->amChoking; 630 648 } 631 int tr_peerAmInterested( tr_peer_t * peer )649 int tr_peerAmInterested( const tr_peer_t * peer ) 632 650 { 633 651 return peer->amInterested; 634 652 } 635 int tr_peerIsChoking( tr_peer_t * peer )653 int tr_peerIsChoking( const tr_peer_t * peer ) 636 654 { 637 655 return peer->peerChoking; 638 656 } 639 int tr_peerIsInterested( tr_peer_t * peer )657 int tr_peerIsInterested( const tr_peer_t * peer ) 640 658 { 641 659 return peer->peerInterested; … … 647 665 * 648 666 **********************************************************************/ 649 float tr_peerProgress( tr_peer_t * peer )667 float tr_peerProgress( const tr_peer_t * peer ) 650 668 { 651 669 return peer->progress; … … 657 675 * Returns peer's listening port in host byte order 658 676 **********************************************************************/ 659 int tr_peerPort( tr_peer_t * peer )677 int tr_peerPort( const tr_peer_t * peer ) 660 678 { 661 679 return ntohs( peer->port ); 662 680 } 663 681 664 /*********************************************************************** 665 * tr_peerBitfield 666 *********************************************************************** 667 * 668 **********************************************************************/ 669 tr_bitfield_t * tr_peerBitfield( tr_peer_t * peer ) 670 { 671 return peer->bitfield; 672 } 673 674 float tr_peerDownloadRate( tr_peer_t * peer ) 682 int tr_peerHasPiece( const tr_peer_t * peer, int pieceIndex ) 683 { 684 return tr_bitfieldHas( peer->bitfield, pieceIndex ); 685 } 686 687 float tr_peerDownloadRate( const tr_peer_t * peer ) 675 688 { 676 689 return tr_rcRate( peer->download ); 677 690 } 678 691 679 float tr_peerUploadRate( tr_peer_t * peer )692 float tr_peerUploadRate( const tr_peer_t * peer ) 680 693 { 681 694 return tr_rcRate( peer->upload ); … … 694 707 } 695 708 696 uint64_t tr_peerLastChoke( tr_peer_t * peer )709 uint64_t tr_peerLastChoke( const tr_peer_t * peer ) 697 710 { 698 711 return peer->lastChoke; … … 704 717 } 705 718 706 int tr_peerIsOptimistic( tr_peer_t * peer )719 int tr_peerIsOptimistic( const tr_peer_t * peer ) 707 720 { 708 721 return peer->optimistic; 709 722 } 710 723 711 static in line int peerIsBad(tr_peer_t * peer )712 { 713 return ( peer->badPcs > 4 + 2 * peer->goodPcs );714 } 715 716 static in line int peerIsGood(tr_peer_t * peer )717 { 718 return ( peer->goodPcs > 3 * peer->badPcs );724 static int peerIsBad( const tr_peer_t * peer ) 725 { 726 return peer->badPcs > 4 + 2 * peer->goodPcs; 727 } 728 729 static int peerIsGood( const tr_peer_t * peer ) 730 { 731 return peer->goodPcs > 3 * peer->badPcs; 719 732 } 720 733 … … 796 809 return count * 6; 797 810 } 811 812 /*** 813 **** 814 ***/ 815 816 void 817 tr_peerSentBlockToUs ( tr_peer_t * peer, int byteCount ) 818 { 819 tr_torrent_t * tor = peer->tor; 820 821 tr_rcTransferred( peer->download, byteCount ); 822 tr_rcTransferred( tor->download, byteCount ); 823 if ( !tor->customUploadLimit ) 824 tr_rcTransferred( tor->handle->download, byteCount ); 825 826 peer->credit += (int)(byteCount * SWIFT_REPAYMENT_RATIO); 827 } 828 829 void 830 tr_peerGotBlockFromUs ( tr_peer_t * peer, int byteCount ) 831 { 832 tr_torrent_t * tor = peer->tor; 833 834 tr_rcTransferred( peer->upload, byteCount ); 835 tr_rcTransferred( tor->upload, byteCount ); 836 if ( !tor->customDownloadLimit ) 837 tr_rcTransferred( tor->handle->upload, byteCount ); 838 839 peer->credit -= byteCount; 840 } 841 842 static void 843 tr_torrentSwiftPulse ( tr_torrent_t * tor ) 844 { 845 int i; 846 int deadbeatCount = 0; 847 tr_peer_t ** deadbeats; 848 849 tr_lockLock( &tor->lock ); 850 851 deadbeats = tr_calloc( tor->peerCount, sizeof(tr_peer_t*) ); 852 for( i=0; i<tor->peerCount; ++i ) { 853 tr_peer_t * peer = tor->peers[ i ]; 854 if( tr_peerIsConnected( peer ) && ( peer->credit < 0 ) ) 855 deadbeats[deadbeatCount++] = peer; 856 } 857 858 if( deadbeatCount ) 859 { 860 const double ul_KiBsec = tr_rcRate( tor->upload ); 861 const double ul_KiB = ul_KiBsec * SWIFT_REFRESH_INTERVAL_SEC; 862 const double ul_bytes = ul_KiB * 1024; 863 const double freeCreditTotal = ul_bytes * SWIFT_LARGESSE; 864 const int freeCreditPerPeer = (int)( freeCreditTotal / deadbeatCount ); 865 for( i=0; i<deadbeatCount; ++i ) 866 deadbeats[i]->credit = freeCreditPerPeer; 867 tr_dbg( "torrent %s has %d deadbeats, " 868 "who are each being granted %d bytes' credit " 869 "for a total of %.1f KiB, " 870 "%d%% of the torrent's ul speed %.1f\n", 871 tor->info.name, deadbeatCount, freeCreditPerPeer, 872 ul_KiBsec*SWIFT_LARGESSE, (int)(SWIFT_LARGESSE*100), ul_KiBsec ); 873 } 874 875 free( deadbeats ); 876 877 tr_lockUnlock( &tor->lock ); 878 } 879 void 880 tr_swiftPulse( tr_handle_t * h ) 881 { 882 static time_t lastPulseTime = 0; 883 const time_t now = time (NULL); 884 tr_torrent_t * tor; 885 886 if( lastPulseTime + SWIFT_REFRESH_INTERVAL_SEC > now ) 887 return; 888 lastPulseTime = now; 889 890 for( tor=h->torrentList; tor; tor=tor->next ) 891 tr_torrentSwiftPulse( tor ); 892 }
Note: See TracChangeset
for help on using the changeset viewer.