Changeset 108 for trunk/libtransmission
- Timestamp:
- Feb 8, 2006, 9:26:27 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/choking.c
r95 r108 28 28 #endif 29 29 30 /* We may try to allocate and free tables of size 0. Quick and dirty 31 way to handle it... */ 32 void * __malloc( int size ) 33 { 34 if( !size ) 35 return NULL; 36 return malloc( size ); 37 } 38 void __free( void * p ) 39 { 40 if( p ) 41 free( p ); 42 } 43 #define malloc __malloc 44 #define free __free 45 30 46 struct tr_choking_s 31 47 { … … 63 79 } 64 80 65 #define sortPeersAscending(p,c) sortPeers(p,c,0) 66 #define sortPeersDescending(p,c) sortPeers(p,c,1) 67 static inline void sortPeers( tr_peer_t ** peers, int count, int order ) 68 { 69 int i, j, sorted; 70 float rate1, rate2; 71 tr_peer_t * tmp; 72 73 for( i = count - 1; i > 0; i-- ) 74 { 81 #define sortPeersAscending(a,ac,z,zc,n,nc) sortPeers(a,ac,z,zc,n,nc,0) 82 #define sortPeersDescending(a,ac,z,zc,n,nc) sortPeers(a,ac,z,zc,n,nc,1) 83 static inline void sortPeers( tr_peer_t ** all, int allCount, 84 tr_peer_t ** zero, int * zeroCount, 85 tr_peer_t ** nonZero, int * nonZeroCount, 86 int order ) 87 { 88 int i, shuffle; 89 90 /* Seperate uploaders from non-uploaders */ 91 *zeroCount = 0; 92 *nonZeroCount = 0; 93 for( i = 0; i < allCount; i++ ) 94 { 95 if( tr_peerDownloadRate( all[i] ) < 0.1 ) 96 zero[(*zeroCount)++] = all[i]; 97 else 98 nonZero[(*nonZeroCount)++] = all[i]; 99 } 100 101 /* Randomly shuffle non-uploaders, so they are treated equally */ 102 if( *zeroCount && ( shuffle = tr_rand( *zeroCount ) ) ) 103 { 104 tr_peer_t ** bak; 105 bak = malloc( shuffle * sizeof( tr_peer_t * ) ); 106 memcpy( bak, zero, shuffle * sizeof( tr_peer_t * ) ); 107 memmove( zero, &zero[shuffle], 108 ( *zeroCount - shuffle ) * sizeof( tr_peer_t * ) ); 109 memcpy( &zero[*zeroCount - shuffle], bak, 110 shuffle * sizeof( tr_peer_t * ) ); 111 free( bak ); 112 } 113 114 /* Sort uploaders by download rate */ 115 for( i = *nonZeroCount - 1; i > 0; i-- ) 116 { 117 float rate1, rate2; 118 tr_peer_t * tmp; 119 int j, sorted; 120 75 121 sorted = 1; 76 122 for( j = 0; j < i; j++ ) 77 123 { 78 rate1 = tr_peerDownloadRate( peers[j] );79 rate2 = tr_peerDownloadRate( peers[j+1] );124 rate1 = tr_peerDownloadRate( nonZero[j] ); 125 rate2 = tr_peerDownloadRate( nonZero[j+1] ); 80 126 if( order ? ( rate1 < rate2 ) : ( rate1 > rate2 ) ) 81 127 { 82 tmp = peers[j];83 peers[j] = peers[j+1];84 peers[j+1] = tmp;85 sorted = 0;128 tmp = nonZero[j]; 129 nonZero[j] = nonZero[j+1]; 130 nonZero[j+1] = tmp; 131 sorted = 0; 86 132 } 87 133 } … … 93 139 void tr_chokingPulse( tr_choking_t * c ) 94 140 { 95 int i, j, peersTotalCount; 96 tr_peer_t * peer; 97 tr_peer_t ** peersCanChoke, ** peersCanUnchoke; 98 int peersCanChokeCount, peersCanUnchokeCount, unchokedCount; 141 int i, peersTotalCount, unchoked; 142 tr_peer_t ** canChoke, ** canUnchoke; 143 tr_peer_t ** canChokeZero, ** canUnchokeZero; 144 tr_peer_t ** canChokeNonZero, ** canUnchokeNonZero; 145 int canChokeCount, canUnchokeCount; 146 int canChokeZeroCount, canUnchokeZeroCount; 147 int canChokeNonZeroCount, canUnchokeNonZeroCount; 99 148 tr_torrent_t * tor; 100 149 uint64_t now = tr_date(); … … 111 160 } 112 161 113 peersCanChoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );114 peersCanUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) );115 peersCanChokeCount = 0;116 peersCanUnchokeCount = 0;117 unchoked Count= 0;162 canChoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) ); 163 canUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) ); 164 canChokeCount = 0; 165 canUnchokeCount = 0; 166 unchoked = 0; 118 167 119 168 for( i = 0; i < c->h->torrentCount; i++ ) 120 169 { 170 tr_peer_t * peer; 171 int j; 172 121 173 tor = c->h->torrents[i]; 122 174 for( j = 0; j < tor->peerCount; j++ ) … … 141 193 if( tr_peerIsUnchoked( peer ) ) 142 194 { 143 unchoked Count++;195 unchoked++; 144 196 if( tr_peerLastChoke( peer ) + 10000 < now ) 145 peersCanChoke[peersCanChokeCount++] = peer;197 canChoke[canChokeCount++] = peer; 146 198 } 147 199 else 148 200 { 149 201 if( tr_peerLastChoke( peer ) + 10000 < now ) 150 peersCanUnchoke[peersCanUnchokeCount++] = peer;202 canUnchoke[canUnchokeCount++] = peer; 151 203 } 152 204 } 153 205 } 154 206 155 /* Sort peers by the rate we are downloading from them. */ 156 sortPeersDescending( peersCanChoke, peersCanChokeCount ); 157 sortPeersAscending( peersCanUnchoke, peersCanUnchokeCount ); 158 159 if( unchokedCount > c->slots && peersCanChokeCount > 0 ) 160 { 161 /* We have more open slots than what we should have (the user 162 has just lowered his upload limit. We need to choke some of the 163 peers we are uploading to. */ 164 int willChoke; 165 willChoke = MIN( peersCanChokeCount, unchokedCount - c->slots ); 166 for( i = 0; i < willChoke; i++ ) 167 tr_peerChoke( peersCanChoke[--peersCanChokeCount] ); 168 } 169 else if( unchokedCount < c->slots && peersCanUnchokeCount > 0 ) 170 { 171 /* We have unused open slots. Let's unchoke some people. */ 172 int willUnchoke; 173 willUnchoke = MIN( peersCanUnchokeCount, c->slots - unchokedCount ); 174 for( i = 0; i < willUnchoke; i++ ) 175 tr_peerUnchoke( peersCanUnchoke[--peersCanUnchokeCount] ); 176 } 177 178 while( peersCanChokeCount > 0 && peersCanUnchokeCount > 0 ) 179 { 180 /* All slots are used and more peers are waiting. If 181 applicable, choke some peers in favor of others who are 182 uploading more to us. */ 183 if( tr_peerDownloadRate( peersCanUnchoke[peersCanUnchokeCount - 1] ) 184 < tr_peerDownloadRate( peersCanChoke[peersCanChokeCount - 1] ) ) 207 canChokeZero = malloc( canChokeCount * sizeof( tr_peer_t * ) ); 208 canChokeNonZero = malloc( canChokeCount * sizeof( tr_peer_t * ) ); 209 canUnchokeZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) ); 210 canUnchokeNonZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) ); 211 212 sortPeersDescending( canChoke, canChokeCount, 213 canChokeZero, &canChokeZeroCount, 214 canChokeNonZero, &canChokeNonZeroCount); 215 sortPeersAscending( canUnchoke, canUnchokeCount, 216 canUnchokeZero, &canUnchokeZeroCount, 217 canUnchokeNonZero, &canUnchokeNonZeroCount); 218 219 free( canChoke ); 220 free( canUnchoke ); 221 222 /* If we have more open slots than what we should have (the user has 223 just lowered his upload limit), we need to choke some of the 224 peers we are uploading to. We start with the peers who aren't 225 uploading to us, then those we upload the least. */ 226 while( unchoked > c->slots && canChokeZeroCount > 0 ) 227 { 228 tr_peerChoke( canChokeZero[--canChokeZeroCount] ); 229 unchoked--; 230 } 231 while( unchoked > c->slots && canChokeNonZeroCount > 0 ) 232 { 233 tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] ); 234 unchoked--; 235 } 236 237 /* If we have unused open slots, let's unchoke some people. We start 238 with the peers who are uploading to us the most. */ 239 while( unchoked < c->slots && canUnchokeNonZeroCount > 0 ) 240 { 241 tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] ); 242 unchoked++; 243 } 244 while( unchoked < c->slots && canUnchokeZeroCount > 0 ) 245 { 246 tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] ); 247 unchoked++; 248 } 249 250 /* Choke peers who aren't uploading if there are good peers waiting 251 for an unchoke */ 252 while( canChokeZeroCount > 0 && canUnchokeNonZeroCount > 0 ) 253 { 254 tr_peerChoke( canChokeZero[--canChokeZeroCount] ); 255 tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] ); 256 } 257 258 /* Choke peers who aren't uploading that much if there are choked 259 peers who are uploading more */ 260 while( canChokeNonZeroCount > 0 && canUnchokeNonZeroCount > 0 ) 261 { 262 if( tr_peerDownloadRate( canUnchokeNonZero[canUnchokeNonZeroCount - 1] ) 263 < tr_peerDownloadRate( canChokeNonZero[canChokeNonZeroCount - 1] ) ) 185 264 break; 186 265 187 tr_peerChoke( peersCanChoke[--peersCanChokeCount] ); 188 tr_peerUnchoke( peersCanUnchoke[--peersCanUnchokeCount] ); 189 } 190 191 free( peersCanChoke ); 192 free( peersCanUnchoke ); 266 tr_peerChoke( canChokeNonZero[--canChokeNonZeroCount] ); 267 tr_peerUnchoke( canUnchokeNonZero[--canUnchokeNonZeroCount] ); 268 } 269 270 /* Some unchoked peers still aren't uploading to us, let's give a 271 chance to other non-uploaders */ 272 while( canChokeZeroCount > 0 && canUnchokeZeroCount > 0 ) 273 { 274 tr_peerChoke( canChokeZero[--canChokeZeroCount] ); 275 tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] ); 276 } 277 278 free( canChokeZero ); 279 free( canChokeNonZero ); 280 free( canUnchokeZero ); 281 free( canUnchokeNonZero ); 193 282 194 283 /* Unlock all torrents */
Note: See TracChangeset
for help on using the changeset viewer.