⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloadmanagercontroller.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * Created on 29-Jul-2005
 * Created by Paul Gardner
 * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * AELITIS, SAS au capital de 46,603.30 euros
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
 *
 */

package org.gudy.azureus2.core3.download.impl;

import java.io.File;
import java.io.IOException; 
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.disk.DiskManagerFactory;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfoListener;
import org.gudy.azureus2.core3.disk.DiskManagerListener;
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerDiskListener;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerStats;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.peer.PEPeer;
import org.gudy.azureus2.core3.peer.PEPeerManager;
import org.gudy.azureus2.core3.peer.PEPeerManagerAdapter;
import org.gudy.azureus2.core3.peer.PEPeerManagerFactory;
import org.gudy.azureus2.core3.peer.PEPeerSource;
import org.gudy.azureus2.core3.peer.PEPiece;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider;
import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
import org.gudy.azureus2.core3.util.*;

import org.gudy.azureus2.plugins.network.ConnectionManager;

import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.peermanager.PeerManager;
import com.aelitis.azureus.core.peermanager.PeerManagerRegistration;
import com.aelitis.azureus.core.peermanager.PeerManagerRegistrationAdapter;
import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory;
import com.aelitis.azureus.core.util.bloom.BloomFilter;
import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin;

public class 
DownloadManagerController 
	extends LogRelation
	implements PEPeerManagerAdapter, PeerManagerRegistrationAdapter
{
	private static long STATE_FLAG_HASDND = 0x01;
	private static long STATE_FLAG_COMPLETE_NO_DND = 0x02;
	
	private static long skeleton_builds;
	
	private static ExternalSeedPlugin	ext_seed_plugin;
	private static boolean				ext_seed_plugin_tried;
	
	private static ExternalSeedPlugin
	getExternalSeedPlugin()
	{
		if ( !ext_seed_plugin_tried ){
			
			ext_seed_plugin_tried	= true;
			
			try {
				ext_seed_plugin = (ExternalSeedPlugin)AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass(
						ExternalSeedPlugin.class).getPlugin();
	
			}catch (Throwable e){
	
				Debug.printStackTrace( e );
			}
		}
		
		return( ext_seed_plugin );
	}
	
		// DISK listeners
	
	private static final int LDT_DL_ADDED		= 1;
	private static final int LDT_DL_REMOVED		= 2;

	private static ListenerManager	disk_listeners_agregator 	= ListenerManager.createAsyncManager(
			"DMC:DiskListenAgregatorDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		_listener,
					int			type,
					Object		value )
				{
					DownloadManagerDiskListener	listener = (DownloadManagerDiskListener)_listener;
					
					if ( type == LDT_DL_ADDED ){
						
						listener.diskManagerAdded((DiskManager)value);
						
					}else if ( type == LDT_DL_REMOVED ){
						
						listener.diskManagerRemoved((DiskManager)value);
					}
				}
			});	
	
	private ListenerManager	disk_listeners 	= ListenerManager.createManager(
			"DMC:DiskListenDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		listener,
					int			type,
					Object		value )
				{
					disk_listeners_agregator.dispatch( listener, type, value );
				}
			});
	
	private AEMonitor	disk_listeners_mon	= new AEMonitor( "DownloadManagerController:DL" );
	
	protected AEMonitor	this_mon		= new AEMonitor( "DownloadManagerController" );
	protected AEMonitor	state_mon		= new AEMonitor( "DownloadManagerController:State" );
	protected AEMonitor	facade_mon	= new AEMonitor( "DownloadManagerController:Facade" );

	
	private DownloadManagerImpl			download_manager;
	private DownloadManagerStatsImpl	stats;
	
		// these are volatile as we want to ensure that if a state is read it is always the
		// most up to date value available (as we don't synchronize state read - see below
		// for comments)
	
	private volatile int		state_set_by_method = DownloadManager.STATE_START_OF_DAY;
	private volatile int		substate;
	private volatile boolean 	force_start;

		// to try and ensure people don't start using disk_manager without properly considering its
		// access implications we've given it a silly name
	
	private volatile DiskManager 			disk_manager_use_accessors;
	private DiskManagerListener				disk_manager_listener_use_accessors;
	
	private fileInfoFacade[]		files_facade		= new fileInfoFacade[0];	// default before torrent avail
	private boolean					files_facade_destroyed;
	
	private boolean					cached_complete_excluding_dnd;
	private boolean					cached_has_dnd_files;
	private boolean         cached_values_set;
	
	private PeerManagerRegistration	peer_manager_registration;
	private PEPeerManager 			peer_manager;
	
	private String errorDetail;

	private GlobalManagerStats		global_stats;
	
	private boolean bInitialized = false;
	
	private long data_send_rate_at_close;
	
	private static final int			ACTIVATION_REBUILD_TIME		= 10*60*1000;
	private static final int			BLOOM_SIZE					= 64;
	private volatile BloomFilter		activation_bloom;
	private volatile long				activation_bloom_create_time	= SystemTime.getCurrentTime();
	private volatile int				activation_count;
	private volatile long				activation_count_time;
	
	
	
	protected
	DownloadManagerController(
		DownloadManagerImpl	_download_manager )
	{
		download_manager = _download_manager;
		
		GlobalManager	gm = download_manager.getGlobalManager();
					
		global_stats = gm.getStats();
		
		stats	= (DownloadManagerStatsImpl)download_manager.getStats();

		cached_values_set = false;
	}
	
	protected void
	setInitialState(
		int	initial_state )
	{
			// only take note if there's been no errors
		
		bInitialized = true;
		
		if ( getState() == DownloadManager.STATE_START_OF_DAY ){
			
			setState( initial_state, true );
		}
		
	
		TOTorrent torrent = download_manager.getTorrent();

		if (torrent != null) {
			
			try{
				peer_manager_registration = PeerManager.getSingleton().registerLegacyManager( torrent.getHashWrapper(), this );
				
			}catch( TOTorrentException e ){
				
				Debug.printStackTrace(e);
			}
		}
			
		DownloadManagerState state = download_manager.getDownloadState();
		if (state.parameterExists(DownloadManagerState.PARAM_DND_FLAGS)) {
			long flags = state.getLongParameter(DownloadManagerState.PARAM_DND_FLAGS);
			cached_complete_excluding_dnd = (flags & STATE_FLAG_COMPLETE_NO_DND) != 0;
			cached_has_dnd_files = (flags & STATE_FLAG_HASDND) != 0;
			cached_values_set = true;
		}
	}

	public void 
	startDownload(
		TRTrackerAnnouncer	tracker_client ) 
	{
		DiskManager	dm;
		
		try{
			this_mon.enter();
		
			if ( getState() != DownloadManager.STATE_READY ){
			
				Debug.out( "DownloadManagerController::startDownload state must be ready, " + getState());
				
				setFailed( "Inconsistent download state: startDownload, state = " + getState());

				return;
			}
			
	 		if ( tracker_client == null ){
	  			
	  			Debug.out( "DownloadManagerController:startDownload: tracker_client is null" );
	  			
	  				// one day we should really do a proper state machine for this. In the meantime...
	  				// probably caused by a "stop" during initialisation, I've reproduced it once or twice
	  				// in my life... Tidy things up so we don't sit here in a READ state that can't
	  				// be started.
	  			
	  			stopIt( DownloadManager.STATE_STOPPED, false, false );
	  			
	  			return;
	  		}
	  			
			if ( peer_manager != null ){
				
				Debug.out( "DownloadManagerController::startDownload: peer manager not null" );
				
					// try and continue....
				
				peer_manager.stopAll();
				
				peer_manager	= null;
			}
			
			dm	= getDiskManager();
			
			if ( dm == null ){
				
				Debug.out( "DownloadManagerController::startDownload: disk manager is null" );
				
				return;
			}
		
			setState( DownloadManager.STATE_DOWNLOADING, false );
		
		}finally{
			
			this_mon.exit();
	
		}
		
			// make sure it is started before making it "visible"
		
		final PEPeerManager temp = PEPeerManagerFactory.create( tracker_client.getPeerId(), this, dm );
		
		temp.start();
	
		   //The connection to the tracker
		
		tracker_client.setAnnounceDataProvider(
	    		new TRTrackerAnnouncerDataProvider()
	    		{
	    			public String
					getName()
	    			{
	    				return( getDisplayName());
	    			}
	    			
	    			public long
	    			getTotalSent()
	    			{
	    				return(temp.getStats().getTotalDataBytesSent());
	    			}
	    			public long
	    			getTotalReceived()
	    			{
	    				long verified = 
	    					temp.getStats().getTotalDataBytesReceived() - 
	    					( temp.getStats().getTotalDiscarded() + temp.getStats().getTotalHashFailBytes());
	    				
	    				return( verified < 0?0:verified );
	    			}
	    			
	    			public long
	    			getRemaining()
	    			{
	    				return( temp.getRemaining());
	    			}
					
					public String
					getExtensions()
					{
						return( getTrackerClientExtensions());
					}
					
					public int
					getMaxNewConnectionsAllowed()
					{
						return( temp.getMaxNewConnectionsAllowed());
					}
					
					public int 
					getUploadSpeedKBSec(
						boolean estimate ) 
					{
						long	current_local = stats.getDataSendRate();
						
						if ( estimate ){
							
								// see if we have an old value from previous stop/start
							
							current_local = data_send_rate_at_close;
							
							if ( current_local == 0 ){
								
								int current_global 	= global_stats.getDataSendRate();
								
								int	old_global		= global_stats.getDataSendRateAtClose();
							
								if ( current_global < old_global ){
									
									current_global = old_global;
								}
						
								List managers = download_manager.getGlobalManager().getDownloadManagers();
								
								int	num_dls = 0;
								
									// be optimistic and share out the bytes between non-seeds
								
								for (int i=0;i<managers.size();i++){
									
									DownloadManager	dm = (DownloadManager)managers.get(i);
									
									if ( dm.getStats().getDownloadCompleted( false ) == 1000 ){
										
										continue;
									}
									
									int	state = dm.getState();
									
									if ( 	state != DownloadManager.STATE_ERROR &&
											state != DownloadManager.STATE_STOPPING &&
											state != DownloadManager.STATE_STOPPED ){
										
										num_dls++;
									}
								}
								
								if ( num_dls == 0 ){
									
									current_local = current_global;
								}else{
									
									current_local = current_global/num_dls;
								}
							}
						}
												
						return((int)((current_local+1023)/1024 ));
					}
	    		});
	    
		
		peer_manager = temp;

		// Inform only after peer_manager.start(), because it 
		// may have switched it to STATE_SEEDING (in which case we don't need to
		// inform).
		
		if (getState() == DownloadManager.STATE_DOWNLOADING) {
			
			download_manager.informStateChanged();
		}

		download_manager.informStarted( temp );
	}
  
  
  

	public void 
	initializeDiskManager(
		final boolean	open_for_seeding )
	{
		initializeDiskManagerSupport(
			DownloadManager.STATE_INITIALIZED,
			new DiskManagerListener()
	  			{
	  				public void
	  				stateChanged(
	  					int 	oldDMState,
	  					int		newDMState )
	  				{
	  					DiskManager	dm;
	  					
	  					try{
	  						this_mon.enter();
	  					
		  					dm = getDiskManager();

		  					if ( dm == null ){
	  						
	  								// already been cleared down
	  							
		  						return;
		  					}
		  					
	  					}finally{
	  						this_mon.exit();
	  					}
	  					
	  					try{
			  				if ( newDMState == DiskManager.FAULTY ){
			  					
			  					setFailed( dm.getErrorMessage());						
			   				}
			  					
			  				if ( oldDMState == DiskManager.CHECKING ){
			  						
			  						// good time to trigger minimum file info fixup as the disk manager's
		  							// files are now in a good state

			  					makeSureFilesFacadeFilled(true);

			  					stats.setDownloadCompleted(stats.getDownloadCompleted(true));
			  						
			  					download_manager.setAssumedComplete(isDownloadComplete(false));
			  				}
			  					  
			  				if ( newDMState == DiskManager.READY ){
			  								  					
			  					if ( 	stats.getTotalDataBytesReceived() == 0 &&
			  							stats.getTotalDataBytesSent() == 0 &&
			  							stats.getSecondsDownloading() == 0 ){

			  						int	completed = stats.getDownloadCompleted(false);
	  							
			  						if ( completed < 1000 ){
		  							
			  							if ( open_for_seeding ){
			  								
			  								setFailed( "File check failed" );
			  								
			  								download_manager.getDownloadState().clearResumeData();
			  								
			  							}else{
			  								
					  						// make up some sensible "downloaded" figure for torrents that have been re-added to Azureus
					  						// and resumed 
					  				
					  									  										 
				  								// assume downloaded = uploaded, optimistic but at least results in
				  								// future share ratios relevant to amount up/down from now on
				  								// see bug 1077060 
				  								
				  							long	amount_downloaded = (completed*dm.getTotalLength())/1000;
				  								
				 							stats.setSavedDownloadedUploaded( amount_downloaded, amount_downloaded );
			  							}
			  						}else{		  					
			  								// see GlobalManager for comment on this
			  							
			  							int	dl_copies = COConfigurationManager.getIntParameter("StartStopManager_iAddForSeedingDLCopyCount");
			  		              
										if ( dl_copies > 0 ){
											
			  								stats.setSavedDownloadedUploaded( download_manager.getSize()*dl_copies, stats.getTotalDataBytesSent());
			  							}
										
							        	download_manager.getDownloadState().setFlag( DownloadManagerState.FLAG_ONLY_EVER_SEEDED, true );
			  						}
			  		        	}
			  				}
	  					}finally{
	  							  						
	  						download_manager.informStateChanged();
	  					}
	  				}

	                public void 
					filePriorityChanged(
						DiskManagerFileInfo	file ) 
	                {  
	                	download_manager.informPriorityChange( file );
	                }
	                
	               	public void
	            	pieceDoneChanged(
	            		DiskManagerPiece	piece )
	            	{           		
	            	}
	               	
	            	public void
	            	fileAccessModeChanged(
	            		DiskManagerFileInfo		file,
	            		int						old_mode,
	            		int						new_mode )
	            	{
	            	}
	  			});
	}
	
	protected void 
	initializeDiskManagerSupport(
		int						initialising_state,
		DiskManagerListener		listener ) 
	{
		try{
			this_mon.enter();
		
			int	entry_state = getState();
				
			if ( 	entry_state != DownloadManager.STATE_WAITING &&
					entry_state != DownloadManager.STATE_STOPPED &&
					entry_state != DownloadManager.STATE_QUEUED &&
					entry_state != DownloadManager.STATE_ERROR ){
					
				Debug.out( "DownloadManagerController::initializeDiskManager: Illegal initialize state, " + entry_state );
				
				setFailed( "Inconsistent download state: initSupport, state = " + entry_state );
				
				return;

⌨️ 快捷键说明

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