FileDocCategorySizeDatePackage
OutgoingBTHaveMessageAggregator.javaAPI DocAzureus 3.0.3.46014Mon Jun 25 16:48:30 BST 2007com.aelitis.azureus.core.peermanager.utils

OutgoingBTHaveMessageAggregator

public class OutgoingBTHaveMessageAggregator extends Object
Utility class to enable write aggregation of BT Have messages, in order to save bandwidth by not wasting a whole network packet on a single small 9-byte message, and instead pad them onto other messages.

Fields Summary
private final ArrayList
pending_haves
private final org.gudy.azureus2.core3.util.AEMonitor
pending_haves_mon
private byte
bt_have_version
private byte
az_have_version
private boolean
destroyed
private final OutgoingMessageQueue
outgoing_message_q
private final OutgoingMessageQueue.MessageQueueListener
added_message_listener
Constructors Summary
public OutgoingBTHaveMessageAggregator(OutgoingMessageQueue outgoing_message_q, byte _bt_have_version, byte _az_have_version)
Create a new aggregator, which will send messages out the given queue.

param
outgoing_message_q

  
  
  
  
                   
   
   
	 	 
	 					
						 
  
    this.outgoing_message_q = outgoing_message_q;
    bt_have_version = _bt_have_version;
    az_have_version	= _az_have_version;
    
    outgoing_message_q.registerQueueListener( added_message_listener );
  
Methods Summary
public voiddestroy()
Destroy the aggregator, along with any pending messages.

    try{
      pending_haves_mon.enter();
    
      pending_haves.clear();
      destroyed = true;
    }
    finally{ 	
      pending_haves_mon.exit();
    }
  
public voidforceSendOfPending()
Force send of any aggregated/pending have messages.

   
    sendPendingHaves();
  
public booleanhasPending()
Are there Haves messages pending?

return
true if there are any unsent haves, false otherwise

  return !pending_haves.isEmpty();  
public voidqueueHaveMessage(int piece_number, boolean force)
Queue a new have message for aggregated sending.

param
piece_number of the have message
param
force if true, send this and any other pending haves right away

    if( destroyed )  return;
    
    try{
      pending_haves_mon.enter();
    
      pending_haves.add( new Integer( piece_number ) );
      if( force ) {
        sendPendingHaves();
      }
      else {
        int pending_bytes = pending_haves.size() * 9;
        if( pending_bytes >= outgoing_message_q.getMssSize() ) {
          //System.out.println("enough pending haves for a full packet!");
          //there's enough pending bytes to fill a packet payload
          sendPendingHaves();
        }
      }
    }finally{
    	
    	pending_haves_mon.exit();
    }
  
private voidsendPendingHaves()

    if ( destroyed ){
    	
    	return;
    }
    
    try{
      pending_haves_mon.enter();
    
      int	num_haves = pending_haves.size();
      
      if ( num_haves == 0 ){
    	  
    	  return;
      }
      
      	// single have -> use BT
      	
      if ( num_haves == 1 || az_have_version < BTMessageFactory.MESSAGE_VERSION_SUPPORTS_PADDING ){
    	        
	      for( int i=0; i < num_haves; i++ ){
	    	  
	        Integer piece_num = (Integer)pending_haves.get( i );
	        
	        outgoing_message_q.addMessage( new BTHave( piece_num.intValue(), bt_have_version ), true );
	      }
      }else{
    	  
    	  int[]	piece_numbers = new int[num_haves];
    	  
	      for( int i=0; i < num_haves; i++ ) {

	    	  piece_numbers[i] = ((Integer)pending_haves.get( i )).intValue(); 
	      }
	      
	      outgoing_message_q.addMessage( new AZHave( piece_numbers, az_have_version ), true );

      }
      
      outgoing_message_q.doListenerNotifications();
      
      pending_haves.clear();
      
    }finally{
    	
      pending_haves_mon.exit();
    }
  
public voidsetHaveVersion(byte bt_version, byte az_version)

	  bt_have_version 	= bt_version;
	  az_have_version	= az_version;