pepeercontrolimpl.java

来自「Azureus is a powerful, full-featured, cr」· Java 代码 · 共 2,180 行 · 第 1/5 页

JAVA
2,180
字号
/*
 * Created on Oct 15, 2003
 * Created by Olivier Chalouhi
 * Modified Apr 13, 2004 by Alon Rohter
 * Copyright (C) 2004 Aelitis, All Rights Reserved.
 * 
 */
 
package org.gudy.azureus2.core3.peer.impl.control;


import java.nio.ByteBuffer;
import java.util.*;


import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.tracker.client.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.ipfilter.*;
import org.gudy.azureus2.core3.logging.LGLogger;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.peer.impl.*;
import org.gudy.azureus2.core3.peer.impl.transport.base.DataReaderOwner;
import org.gudy.azureus2.core3.peer.impl.transport.base.DataReaderSpeedLimiter;
import org.gudy.azureus2.core3.peer.util.*;

import com.aelitis.azureus.core.networkmanager.ConnectDisconnectManager;
import com.aelitis.azureus.core.peermanager.LimitedRateGroup;
import com.aelitis.azureus.core.peermanager.utils.PeerConnectInfoStorage;


public class 
PEPeerControlImpl
	implements 	PEPeerControl, ParameterListener, DiskManagerWriteRequestListener, DiskManagerCheckRequestListener
{
  
  //Min number of requests sent to a peer
  private static final int MIN_REQUESTS = 2;
  //Default number of requests sent to a peer
  //(for each X B/s a new request will be used)
  private static final int SLOPE_REQUESTS = 2 * 1024;
  //Max number of request sent to a peer
  private static final int MAX_REQUESTS = 64;
  
  private static final int BAD_CHUNKS_LIMIT = 3;
  private static final int WARNINGS_LIMIT = 3;
  
  private static boolean oldPolling = COConfigurationManager.getBooleanParameter("Old.Socket.Polling.Style", false);
  private static boolean disconnect_seeds_when_seeding = COConfigurationManager.getBooleanParameter("Disconnect Seed", true);
  
    
  private static IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter();
  
  private int peer_manager_state = PS_INITIALISED;
  
  private int[] 	availability_cow;
  
  private boolean _bContinue;    
  
  private volatile ArrayList peer_transports_cow = new ArrayList();	// Copy on write!
  
  private AEMonitor	peer_transports_mon	= new AEMonitor( "PEPeerControl:PT");
  
  private DiskManager 			_diskManager;
  private DiskManagerPiece[]	dm_pieces;
  
  private boolean[] _downloading;
  private boolean 	seeding_mode;
  private boolean	restart_initiated;
  
  private boolean[] 			_piecesRarest;
  private PeerIdentityDataID 	_hash;
  private byte[] _myPeerId;
  private int _nbPieces;
  private PEPieceImpl[] 				_pieces;
  private PEPeerServerHelper 			_server;
  private PEPeerManagerStatsImpl 		_stats;
  private TRTrackerClient _tracker;
   //  private int _maxUploads;
  private int _seeds, _peers,_remotes;
  private long _timeStarted;
  private long _timeStartedSeeding = -1;
  private long _timeFinished;
  private Average _averageReceptionSpeed;
  private PEPeerTransport currentOptimisticUnchoke;
  
  
  private static final long	END_GAME_MODE_SIZE_TRIGGER	= 20*1024*1024;
  private static final long	END_GAME_MODE_TIMEOUT		= 10*60*1000;
  
  	//A flag to indicate when we're in endgame mode
  private boolean endGameMode;
  private boolean endGameModeAbandoned;
  private long	  timeEndGameModeEntered;
  
    //The list of chunks needing to be downloaded (the mechanism change when entering end-game mode)
  private List 		endGameModeChunks;
  private AEMonitor	endGameModeChunks_mon	= new AEMonitor( "PEPeerControl:EG");

  
  private DownloadManager _downloadManager;
  private PeerUpdater peerUpdater;
  
  private int nbHashFails;
  

  private static final int PEER_UPDATER_INTERVAL = 50;
  
  private long mainloop_loop_count;
  private static final int MAINLOOP_INTERVAL   = 100;
  private static final int MAINLOOP_ONE_SECOND_INTERVAL = 1000 / MAINLOOP_INTERVAL;
  private static final int MAINLOOP_FIVE_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 5;
  private static final int MAINLOOP_TEN_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 10;
  private static final int MAINLOOP_THIRTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 30;
  
  

  private List	peer_manager_listeners 		= new ArrayList();
  //private List	peer_transport_listeners 	= new ArrayList();
  
  private List 		piece_check_result_list 	= new ArrayList();
  private AEMonitor	piece_check_result_list_mon	= new AEMonitor( "PEPeerControl:PCRL");

  private boolean superSeedMode;
  private int superSeedModeCurrentPiece;
  private int superSeedModeNumberOfAnnounces;
  private SuperSeedPiece[] superSeedPieces;
  
  private final PeerConnectInfoStorage peer_info_storage = new PeerConnectInfoStorage( 200 );  //size will be updated later on
  
  private final HashMap 	reconnect_counts 		= new HashMap();
  private final AEMonitor	reconnect_counts_mon	= new AEMonitor( "PEPeerControl:RC");

  private AEMonitor	this_mon	= new AEMonitor( "PEPeerControl");
  
  private long		ip_filter_last_update_time;
  
  private Map		user_data;
  
  private PEPeerTransportDataReader		download_speed_limiter;
  
  private final LimitedRateGroup upload_limited_rate_group = new LimitedRateGroup() {
    public int getRateLimitBytesPerSecond() {
      return _downloadManager.getStats().getUploadRateLimitBytesPerSecond();
    }
  };
  

  public 
  PEPeerControlImpl
  (
    DownloadManager 	manager,
    PEPeerServerHelper 	server,
	TRTrackerClient 	tracker,
    DiskManager 		diskManager) 
  {
  	  _server = server;
  	  this._downloadManager = manager;
  	  _tracker = tracker;
  	  this._diskManager = diskManager;
  	  COConfigurationManager.addParameterListener("Old.Socket.Polling.Style", this);
      COConfigurationManager.addParameterListener("Ip Filter Enabled", this);
      COConfigurationManager.addParameterListener( "Disconnect Seed", this );
      
 }
  
	public DownloadManager
	getDownloadManager()
	{
		return( _downloadManager );
	}
 
	public int
	getState()
	{
		return( peer_manager_state );
	}
	
  public void
  start()
  {  
    endGameMode = false;
    //This torrent Hash
    
    try{
    
    	_hash = PeerIdentityManager.createDataID( _tracker.getTorrent().getHash());
    	
    }catch( TOTorrentException e ){
    	
    		// this should never happen
    	Debug.printStackTrace( e );
    	
    	_hash = PeerIdentityManager.createDataID( new byte[20] ); 
    }
    
    this.nbHashFails = 0;

    //The connection to the tracker
    _tracker.setAnnounceDataProvider(
    		new TrackerClientAnnounceDataProvider()
    		{
    			public String
				getName()
    			{
    				return( getDownloadManager().getDisplayName());
    			}
    			
    			public long
    			getTotalSent()
    			{
    				return(getStats().getTotalSent());
    			}
    			public long
    			getTotalReceived()
    			{
    				return(getStats().getTotalReceived());
    			}
    			
    			public long
    			getRemaining()
    			{
    				return( PEPeerControlImpl.this.getRemaining());
    			}
    		});
    
    _myPeerId = _tracker.getPeerId();

    //The peer connections
    peer_transports_cow = new ArrayList();

    //The Server that handle incoming connections
     _server.setServerAdapter(this);

    //BtManager is threaded, this variable represents the
    // current loop iteration. It's used by some components only called
    // at some specific times.
    mainloop_loop_count = 0;

    //The current tracker state
    //this could be start or update

    _averageReceptionSpeed = Average.getInstance(1000, 30);

	download_speed_limiter = 
				DataReaderSpeedLimiter.getSingleton().getDataReader(
						new DataReaderOwner()
					{
							public int
							getMaximumBytesPerSecond()
							{
								return( _downloadManager.getStats().getMaxDownloadKBSpeed() * 1024 );
							}
					});
    
    setDiskManager(_diskManager);
    
    superSeedMode = (COConfigurationManager.getBooleanParameter("Use Super Seeding") && this.getRemaining() == 0);
    
    superSeedModeCurrentPiece = 0;
    
    if ( superSeedMode ){
    	initialiseSuperSeedMode();
    }
    
    peerUpdater = new PeerUpdater();
    peerUpdater.start();
    
    
    new AEThread( "Peer Manager"){
      public void
      runSupport()
      {
        mainLoop();
      }
    }.start();
  }

  private class 
  PeerUpdater 
  extends AEThread 
  {
    private boolean bContinue = true;

    public PeerUpdater() {
      super("Peer Updater"); //$NON-NLS-1$
      setPriority(Thread.NORM_PRIORITY - 1);
    }

    public void runSupport() {
      while (bContinue) {
        
        long start_time = SystemTime.getCurrentTime();
        
        try{
        	List	peer_transports = peer_transports_cow;
                       	
	          for (int i=0; i < peer_transports.size(); i++) {
	            PEPeerTransport ps = (PEPeerTransport) peer_transports.get(i);
	
	            if (SystemTime.isErrorLast5sec() || oldPolling || (SystemTime.getCurrentTime() > (ps.getLastReadTime() + ps.getReadSleepTime()))) {
	              ps.setReadSleepTime( ps.processRead() );
	              if ( !oldPolling ) ps.setLastReadTime( SystemTime.getCurrentTime() );
	            }
	          }
        }catch( Throwable e ){
        	
        	Debug.printStackTrace( e );
        }
         
        long loop_time = SystemTime.getCurrentTime() - start_time;
        
        //TODO : BOTTLENECK for download speed HERE (100 : max 500kB/s from BitTornado, 50 : 1MB/s, 25 : 2MB/s, 10 : 3MB/s
        
        if( loop_time < PEER_UPDATER_INTERVAL && loop_time >= 0 ) {
          try {  Thread.sleep( PEER_UPDATER_INTERVAL - loop_time );  } catch(Exception e) {}
        }

      }
    }

    public void stopIt() {
      bContinue = false;
    }
  }
  
  
  
  private void mainLoop() {
    _bContinue = true;

    _downloadManager.setState( DownloadManager.STATE_DOWNLOADING );

    _timeStarted = SystemTime.getCurrentTime();

    // initial check on finished state - future checks are driven by piece check results

    checkFinished( true );

    while( _bContinue ) { //loop until stopAll() kills us

      try {
        long timeStart = SystemTime.getCurrentTime();

        updateTrackerAnnounceInterval();
        
        doConnectionChecks();

        processPieceChecks();

        checkCompletedPieces(); //check to see if we've completed anything else

        computeAvailability(); //compute the availablity

        updateStats();

        checkFastPieces();

        if( !seeding_mode ) { //if we're not finished

          _diskManager.computePriorityIndicator();

          checkRequests(); //check the requests

          checkDLPossible(); //look for downloadable pieces
        }

        checkSeeds( false );

        updatePeersInSuperSeedMode();

        doUnchokes();
        

        long loop_time = SystemTime.getCurrentTime() - timeStart;
        if( loop_time < MAINLOOP_INTERVAL && loop_time >= 0 ) {
          try {  Thread.sleep( MAINLOOP_INTERVAL - loop_time );  } catch(Exception e) {}
        }
        
      }
      catch (Throwable e) {

        Debug.printStackTrace( e );
      }

      mainloop_loop_count++;
    }
  }

  
  
  public void 
  stopAll() 
  {
  		// send stopped event
  	
    _tracker.stop();
    
    	//  Stop the server
    
    _server.stopServer();
    
    _server.clearServerAdapter();
    
    	// Close all clients
    
    try{
    	peer_transports_mon.enter();
      
        	//  Stop itself
    	
        _bContinue = false;

        while (peer_transports_cow.size() != 0) {
        	
          removeFromPeerTransports((PEPeerTransport)peer_transports_cow.get(0), "Closing all Connections");
        }
    }finally{
      	
      	peer_transports_mon.exit();
    }
  
    
    // Stop the peer updater
    peerUpdater.stopIt();

    //clear pieces
    for (int i = 0; i < _pieces.length; i++) {
      if (_pieces[i] != null)
        pieceRemoved(_pieces[i]);
    }


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?