FileDocCategorySizeDatePackage
DownloadingUnchoker.javaAPI DocAzureus 3.0.3.47362Sat Jul 22 13:28:12 BST 2006com.aelitis.azureus.core.peermanager.unchoker

DownloadingUnchoker

public class DownloadingUnchoker extends Object implements Unchoker
Unchoker implementation to be used while in downloading mode.

Fields Summary
private ArrayList
chokes
private ArrayList
unchokes
Constructors Summary
public DownloadingUnchoker()

  

    
    /* nothing */
  
Methods Summary
public voidcalculateUnchokes(int max_to_unchoke, java.util.ArrayList all_peers, boolean force_refresh)

    int max_optimistic = ((max_to_unchoke - 1) / 10) + 1;  //one optimistic unchoke for every 10 upload slots
    
    ArrayList optimistic_unchokes = new ArrayList();
    ArrayList best_peers = new ArrayList();
    long[] bests = new long[ max_to_unchoke ];  //ensure we never pick more slots than allowed to unchoke
    
    
    //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, true ) ) {
          unchokes.add( peer );
          if( peer.isOptimisticUnchoke() ) {
            optimistic_unchokes.add( peer );
          }
        }
        else {  //should be immediately choked
          chokes.add( peer );
        }
      }
    }
       
    
    if( !force_refresh ) {  //ensure current optimistic unchokes remain unchoked
      for( int i=0; i < optimistic_unchokes.size(); i++ ) {
      	PEPeerTransport peer = (PEPeerTransport)optimistic_unchokes.get( i );
        
        if( i < max_optimistic ) {
          best_peers.add( peer );  //add them to the front of the "best" list
        }
        else { //too many optimistics
          peer.setOptimisticUnchoke( false );
        }
      }
    }
    
    
    //fill slots with peers who we are currently downloading the fastest from
    int start_pos = best_peers.size();
    for( int i=0; i < all_peers.size(); i++ ) {
    	PEPeerTransport peer = (PEPeerTransport)all_peers.get( i );

      if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) && !best_peers.contains( peer ) ) {  //viable peer found
        long rate = peer.getStats().getSmoothDataReceiveRate();
        if( rate > 256 ) {  //filter out really slow peers
          UnchokerUtil.updateLargestValueFirstSort( rate, bests, peer, best_peers, start_pos );
        }
      }
    }
    

    //if we havent yet picked enough slots
    if( best_peers.size() < max_to_unchoke ) {  
      start_pos = best_peers.size();
      
      //fill the remaining slots with peers that we have downloaded from in the past
      for( int i=0; i < all_peers.size(); i++ ) {
      	PEPeerTransport peer = (PEPeerTransport)all_peers.get( i );

        if( peer.isInteresting() && UnchokerUtil.isUnchokable( peer, false ) && !best_peers.contains( peer ) ) {  //viable peer found
          long uploaded_ratio = peer.getStats().getTotalDataBytesSent() / (peer.getStats().getTotalDataBytesReceived() + (DiskManager.BLOCK_SIZE-1));
          //make sure we haven't already uploaded several times as much data as they've sent us
          if( uploaded_ratio <3) {
            UnchokerUtil.updateLargestValueFirstSort( peer.getStats().getTotalDataBytesReceived(), bests, peer, best_peers, start_pos );
          }  
        }
      }
    }
    
    
    if( force_refresh ) {
      //make space for new optimistic unchokes
      while( best_peers.size() > max_to_unchoke - max_optimistic ) {
        best_peers.remove( best_peers.size() - 1 );
      }
    }
    
    
    //if we still have remaining slots
    while( best_peers.size() < max_to_unchoke ) { 
    	PEPeerTransport peer = UnchokerUtil.getNextOptimisticPeer( all_peers, true, true );  //just pick one optimistically
      if( peer == null )  break;  //no more new unchokes avail
      
      if( !best_peers.contains( peer ) ) {
        best_peers.add( peer );
        peer.setOptimisticUnchoke( true );
      }
      else {
        //we're here because the given optimistic peer is already "best", but is choked still,
        //which means it will continually get picked by the getNextOptimisticPeer() method,
        //and we'll loop forever if there are no other peers to choose from
        peer.sendUnChoke();  //send unchoke immediately, so it won't get picked optimistically anymore
      	//all_peers.remove( peer );  //remove from all_peers list, so it won't get picked optimistically anymore    //TODO
      }
    }
      

    //update chokes
    for( Iterator it = unchokes.iterator(); it.hasNext(); ) {
    	PEPeerTransport peer = (PEPeerTransport)it.next();

      if( !best_peers.contains( peer ) ) {  //should be choked
        if( best_peers.size() < max_to_unchoke ) {  //but there are still slots needed (no optimistics avail), so don't bother choking them
          best_peers.add( peer );
        }
        else {
          chokes.add( peer );
          it.remove();
        }
      }
    }
    
    //update unchokes
    for( int i=0; i < best_peers.size(); i++ ) {
    	PEPeerTransport peer = (PEPeerTransport)best_peers.get( i );
      
      if( !unchokes.contains( peer ) ) {
        unchokes.add( peer );
      }
    }

  
public java.util.ArrayListgetChokes()

    ArrayList to_choke = chokes;
    chokes = new ArrayList();
    return to_choke;
  
public java.util.ArrayListgetImmediateUnchokes(int max_to_unchoke, java.util.ArrayList all_peers)

    ArrayList to_unchoke = new ArrayList();
    
    //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 ) {
      for( int i=0; i < needed; i++ ) {
      	PEPeerTransport peer = UnchokerUtil.getNextOptimisticPeer( all_peers, true, true );
        if( peer == null )  break;  //no more new unchokes avail
        to_unchoke.add( peer );
        peer.setOptimisticUnchoke( true );
      }
    }
    
    return to_unchoke;
  
public java.util.ArrayListgetUnchokes()

    ArrayList to_unchoke = unchokes;
    unchokes  = new ArrayList();
    return to_unchoke;