SeedingUnchokerpublic class SeedingUnchoker extends Object implements UnchokerUnchoker implementation to be used while in seeding mode. |
Fields Summary |
---|
private ArrayList | chokes | private ArrayList | unchokes |
Constructors Summary |
---|
public SeedingUnchoker()
/* nothing */
|
Methods Summary |
---|
public void | calculateUnchokes(int max_to_unchoke, java.util.ArrayList all_peers, boolean force_refresh)
//get all the currently unchoked peers
for( int i=0; i < all_peers.size(); i++ ) {
PEPeerTransport peer = (PEPeerTransport)all_peers.get( i );
if( !peer.isChokedByMe() ) {
if( UnchokerUtil.isUnchokable( peer, false ) ) {
unchokes.add( peer );
}
else { //should be immediately choked
chokes.add( peer );
}
}
}
//if too many unchokes
while( unchokes.size() > max_to_unchoke ) {
chokes.add( unchokes.remove( unchokes.size() - 1 ) );
}
//we only recalculate the uploads when we're force to refresh the optimistic unchokes
if( force_refresh ) {
int max_optimistic = ((max_to_unchoke - 1) / 5) + 1; //one optimistic unchoke for every 5 upload slots
//we need to make room for new opt unchokes by finding the "worst" peers
ArrayList peers_ordered_by_rate = new ArrayList();
ArrayList peers_ordered_by_uploaded = new ArrayList();
long[] rates = new long[ unchokes.size() ]; //0-initialized
long[] uploaded = new long[ rates.length ]; //0-initialized
//calculate factor rankings
for( int i=0; i < unchokes.size(); i++ ) {
PEPeerTransport peer = (PEPeerTransport)unchokes.get( i );
long rate = peer.getStats().getDataSendRate();
if( rate > 256 ) { //filter out really slow peers
//calculate reverse order by our upload rate to them
UnchokerUtil.updateLargestValueFirstSort( rate, rates, peer, peers_ordered_by_rate, 0 );
//calculate order by the total number of bytes we've uploaded to them
UnchokerUtil.updateLargestValueFirstSort( peer.getStats().getTotalDataBytesSent(), uploaded, peer, peers_ordered_by_uploaded, 0 );
}
}
Collections.reverse( peers_ordered_by_rate ); //we want higher rates at the end
ArrayList peers_ordered_by_rank = new ArrayList();
long[] ranks = new long[ peers_ordered_by_rate.size() ];
Arrays.fill( ranks, Long.MIN_VALUE );
//combine factor rankings to get best
for( int i=0; i < unchokes.size(); i++ ) {
PEPeerTransport peer = (PEPeerTransport)unchokes.get( i );
//"better" peers have high indexes (toward the end of each list)
long rate_factor = peers_ordered_by_rate.indexOf( peer );
long uploaded_factor = peers_ordered_by_uploaded.indexOf( peer );
if( rate_factor == -1 ) continue; //wasn't downloading fast enough, skip add so it will be choked automatically
long rank_factor = rate_factor + uploaded_factor;
UnchokerUtil.updateLargestValueFirstSort( rank_factor, ranks, peer, peers_ordered_by_rank, 0 );
}
//make space for new optimistic unchokes
while( peers_ordered_by_rank.size() > max_to_unchoke - max_optimistic ) {
peers_ordered_by_rank.remove( peers_ordered_by_rank.size() - 1 );
}
//update choke list with drops and unchoke list with optimistic unchokes
ArrayList to_unchoke = new ArrayList();
for( Iterator it = unchokes.iterator(); it.hasNext(); ) {
PEPeerTransport peer = (PEPeerTransport)it.next();
peer.setOptimisticUnchoke( false );
if( !peers_ordered_by_rank.contains( peer ) ) { //should be choked
//we assume that any/all chokes are to be replace by optimistics
PEPeerTransport optimistic_peer = UnchokerUtil.getNextOptimisticPeer( all_peers, false, false );
if( optimistic_peer != null ) { //only choke if we've got a peer to replace it with
chokes.add( peer );
it.remove();
to_unchoke.add( optimistic_peer );
optimistic_peer.setOptimisticUnchoke( true );
}
}
}
for( int i=0; i < to_unchoke.size(); i++ ) {
unchokes.add( to_unchoke.get( i ) );
}
}
| public java.util.ArrayList | getChokes()
ArrayList to_choke = chokes;
chokes = new ArrayList();
return to_choke;
| public java.util.ArrayList | getImmediateUnchokes(int max_to_unchoke, java.util.ArrayList all_peers)
int peer_count = all_peers.size();
if ( max_to_unchoke > peer_count ){
max_to_unchoke = peer_count;
}
//count all the currently unchoked peers
int num_unchoked = 0;
for( int i=0; i < all_peers.size(); i++ ) {
PEPeerTransport peer = (PEPeerTransport)all_peers.get( i );
if( !peer.isChokedByMe() ) num_unchoked++;
}
//if not enough unchokes
int needed = max_to_unchoke - num_unchoked;
if ( needed > 0 ) {
ArrayList to_unchoke = UnchokerUtil.getNextOptimisticPeers( all_peers, false, false, needed );
if ( to_unchoke == null ){
return( new ArrayList(0));
}
for ( int i=0;i<to_unchoke.size();i++){
((PEPeerTransport)to_unchoke.get(i)).setOptimisticUnchoke( true );
}
return( to_unchoke );
}else{
return( new ArrayList(0));
}
| public java.util.ArrayList | getUnchokes()
ArrayList to_unchoke = unchokes;
unchokes = new ArrayList();
return to_unchoke;
|
|