FileDocCategorySizeDatePackage
PeerNATTraverser.javaAPI DocAzureus 3.0.3.412734Thu Sep 06 08:46:06 BST 2007com.aelitis.azureus.core.peermanager.nat

PeerNATTraverser

public class PeerNATTraverser extends Object implements com.aelitis.azureus.core.nat.NATTraversalHandler

Fields Summary
private static final org.gudy.azureus2.core3.logging.LogIDs
LOGID
private static final int
OUTCOME_SUCCESS
private static final int
OUTCOME_FAILED_NO_REND
private static final int
OUTCOME_FAILED_OTHER
private static PeerNATTraverser
singleton
private static int
MAX_ACTIVE_REQUESTS
private static final int
TIMER_PERIOD
private static final int
USAGE_PERIOD
private static final int
USAGE_DURATION_SECS
private static final int
MAX_USAGE_PER_MIN
private static final int
STATS_TICK_COUNT
private com.aelitis.azureus.core.nat.NATTraverser
nat_traverser
private Map
initiators
private LinkedList
pending_requests
private List
active_requests
private org.gudy.azureus2.core3.util.Average
usage_average
private int
attempted_count
private int
success_count
private int
failed_no_rendezvous
private int
failed_negative_bloom
private com.aelitis.azureus.core.util.bloom.BloomFilter
negative_result_bloom
private static final int
BLOOM_SIZE
private static final int
BLOOM_REBUILD_PERIOD
private static final int
BLOOM_REBUILD_TICKS
Constructors Summary
public PeerNATTraverser(com.aelitis.azureus.core.AzureusCore core)

	
	
	
				 
	
		nat_traverser = core.getNATTraverser();
		
		nat_traverser.registerHandler( this );
		
		SimpleTimer.addPeriodicEvent(
			"PeerNAT:stats",
			TIMER_PERIOD,
			new TimerEventPerformer()
			{
				private int	ticks;
				
				public void
				perform(
					TimerEvent	event )
				{
					ticks++;

					List	to_run = null;
					
					synchronized( initiators ){
	
						if ( ticks % BLOOM_REBUILD_TICKS == 0 ){
							
							int	size = negative_result_bloom.getEntryCount();
							
					      	if (Logger.isEnabled()){
					      		
					      		if ( size > 0 ){
					      			
					      			Logger.log(	new LogEvent(LOGID,	"PeerNATTraverser: negative bloom size = " + size ));
					      		}
				          	}
					      	
					      	negative_result_bloom = BloomFilterFactory.createAddOnly( BLOOM_SIZE );
						}
						
						if ( ticks % STATS_TICK_COUNT == 0 ){
							
							String	msg = 
								"NAT traversal stats: active=" +  active_requests.size() +
								",pending=" + pending_requests.size() + ",attempted=" + attempted_count +
								",no rendezvous=" + failed_no_rendezvous + ",negative bloom=" + failed_negative_bloom +
								",successful=" + success_count;

							// System.out.println( msg );
							
					      	if (Logger.isEnabled()){
								Logger.log(	new LogEvent(LOGID,	msg ));
				          	}
						}

						int	used = 0;
						
						for (int i=0;i<active_requests.size();i++){
							
							used += ((PeerNATTraversal)active_requests.get(i)).getTimeUsed();
						}
						
						usage_average.addValue( used );
						
						int	usage = (int)usage_average.getAverage();
						
						if ( usage > MAX_USAGE_PER_MIN ){
							
							return;
						}
						
						// System.out.println( "usage = " + usage );

						while( true ){
						
							if ( 	pending_requests.size() == 0 ||
									active_requests.size() >= MAX_ACTIVE_REQUESTS ){
								
								break;
							}
								
								// TODO: prioritisation based on initiator connections etc?
							
							PeerNATTraversal traversal = (PeerNATTraversal)pending_requests.removeFirst();
							
							active_requests.add( traversal );
							
							if ( to_run == null ){
								
								to_run = new ArrayList();
							}
							
							to_run.add( traversal );
							
							attempted_count++;
						}
					}	
					
					if ( to_run != null ){
						
						for (int i=0;i<to_run.size();i++){
							
							PeerNATTraversal	traversal = (PeerNATTraversal)to_run.get(i);
							
							boolean	bad = false;
							
							synchronized( initiators ){
							
								if ( negative_result_bloom.contains( traversal.getTarget().toString().getBytes())){
									
									bad = true;
									
									failed_negative_bloom++;
								}
							}
							
							if ( bad ){
								
								removeRequest( traversal, OUTCOME_FAILED_OTHER );
								
								traversal.getAdapter().failed();
							}else{
								
								traversal.run();
							}
						}
					}
				}
			});
	
Methods Summary
public voidcreate(PeerNATInitiator initiator, java.net.InetSocketAddress target, PeerNATTraversalAdapter adapter)

		boolean	bad = false;
						
		synchronized( initiators ){
			
			if ( negative_result_bloom.contains( target.toString().getBytes() )){
				
				bad	= true;
				
				failed_negative_bloom++;
				
			}else{
			
				LinkedList	requests = (LinkedList)initiators.get( initiator );
					
				if ( requests == null ){
	
					// we get here when download stopped at same time
					// Debug.out( "initiator not found" );
					
					bad	= true;
					
				}else{
				
					PeerNATTraversal	traversal = new PeerNATTraversal( initiator, target, adapter );
					
					requests.addLast( traversal );
							
					pending_requests.addLast( traversal );
					
		          	if (Logger.isEnabled()){
						Logger.log(
							new LogEvent(
								LOGID,
								"created NAT traversal for " + initiator.getDisplayName() + "/" + target ));
		          	}
				}
			}
		}
		
		if ( bad ){
			
			adapter.failed();
		}
	
public java.lang.StringgetName()

		return( "Peer Traversal" );
	
public static com.aelitis.azureus.core.peermanager.nat.PeerNATTraversergetSingleton()

		return( singleton );
	
public java.util.ListgetTraversals(PeerNATInitiator initiator)

		List result = new ArrayList();
		
		synchronized( initiators ){
			
			LinkedList	requests = (LinkedList)initiators.get( initiator );

			if ( requests != null ){
				
				Iterator it = requests.iterator();
				
				while( it.hasNext()){
					
					PeerNATTraversal	x = (PeerNATTraversal)it.next();
					
					result.add( x.getTarget());
				}
			}
		}
		
		return( result );
	
public intgetType()

		return(  NATTraverser.TRAVERSE_REASON_PEER_DATA );
	
public static voidinitialise(com.aelitis.azureus.core.AzureusCore core)

	
	  
	
				 
	
		singleton	= new PeerNATTraverser( core );
	
public java.util.Mapprocess(java.net.InetSocketAddress originator, java.util.Map data)

		// System.out.println( "PeerNAT: received traversal from " + originator );
		
		return( null );
	
public voidregister(PeerNATInitiator initiator)

		synchronized( initiators ){
			
			if ( initiators.put( initiator, new LinkedList()) != null ){
				
				Debug.out( "initiator already present" );
			}
		}
	
protected voidremoveRequest(com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser$PeerNATTraversal request, int outcome)

		synchronized( initiators ){
			
			LinkedList	requests = (LinkedList)initiators.get( request.getInitiator());
	
			if ( requests != null ){
				
				requests.remove( request );
			}
			
			pending_requests.remove( request );
			
			if ( active_requests.remove( request )){
			
				usage_average.addValue( request.getTimeUsed());
				
				if ( outcome == OUTCOME_SUCCESS ){
					
					success_count++;
					
				}else{
					
					InetSocketAddress	target = request.getTarget();
					
					negative_result_bloom.add( target.toString().getBytes());
					
					if ( outcome == OUTCOME_FAILED_NO_REND ){
					
						failed_no_rendezvous++;
					}
				}
			}
		}
	
public voidunregister(PeerNATInitiator initiator)

		List	to_cancel;
		
		synchronized( initiators ){
			
			LinkedList	requests = (LinkedList)initiators.remove( initiator );
				
			if ( requests == null ){
				
				Debug.out( "initiator not present" );
				
				return;
				
			}else{
				
				to_cancel = requests;
			}
		}
		
		Iterator it = to_cancel.iterator();
		
		while( it.hasNext()){
								
			PeerNATTraversal	traversal = (PeerNATTraversal)it.next();
			
			traversal.cancel();
		}