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

📄 downloadmanagerimpl.java

📁 Azureus is a powerful, full-featured, cross-platform java BitTorrent client
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * File    : DownloadManagerImpl.java
 * Created : 19-Oct-2003
 * By      : parg
 * 
 * Azureus - a Java Bittorrent client
 *
 * 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.
 *
 * 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 ( see the LICENSE file ).
 *
 * 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
 */

package org.gudy.azureus2.core3.download.impl;
/*
 * Created on 30 juin 2003
 *
 */
 
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.net.*;


import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.internat.*;
import org.gudy.azureus2.core3.peer.*;
import org.gudy.azureus2.core3.tracker.client.*;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.download.*;

import org.gudy.azureus2.core3.logging.*;

/**
 * @author Olivier
 * 
 */

public class 
DownloadManagerImpl 
	implements DownloadManager
{
		// DownloadManager listeners
	
	private static final int LDT_STATECHANGED		= 1;
	private static final int LDT_DOWNLOADCOMPLETE	= 2;
	private static final int LDT_COMPLETIONCHANGED = 3;
	private static final int LDT_POSITIONCHANGED = 4;
	
	private ListenerManager	listeners 	= ListenerManager.createManager(
			"DMM:ListenDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		_listener,
					int			type,
					Object		value )
				{
					DownloadManagerListener	listener = (DownloadManagerListener)_listener;
					
					if ( type == LDT_STATECHANGED ){
						
						listener.stateChanged(DownloadManagerImpl.this, ((Integer)value).intValue());
						
					}else if ( type == LDT_DOWNLOADCOMPLETE ){
						
						listener.downloadComplete(DownloadManagerImpl.this);

					}else if ( type == LDT_COMPLETIONCHANGED ){
						listener.completionChanged(DownloadManagerImpl.this, ((Boolean)value).booleanValue());

					}else if ( type == LDT_POSITIONCHANGED ){
						listener.positionChanged(DownloadManagerImpl.this,
						                         ((Integer)value).intValue(), position);
					}
				}
			});		
	
		// TrackerListeners
	
	private static final int LDT_TL_ANNOUNCERESULT		= 1;
	private static final int LDT_TL_SCRAPERESULT		= 2;
	
	private ListenerManager	tracker_listeners 	= ListenerManager.createManager(
			"DMM:TrackerListenDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		_listener,
					int			type,
					Object		value )
				{
					DownloadManagerTrackerListener	listener = (DownloadManagerTrackerListener)_listener;
					
					if ( type == LDT_TL_ANNOUNCERESULT ){
						
						listener.announceResult((TRTrackerResponse)value);
						
					}else if ( type == LDT_TL_SCRAPERESULT ){
						
						listener.scrapeResult((TRTrackerScraperResponse)value);
					}
				}
			});	

	// PeerListeners
	
	private static final int LDT_PE_PEER_ADDED		= 1;
	private static final int LDT_PE_PEER_REMOVED	= 2;
	private static final int LDT_PE_PIECE_ADDED		= 3;
	private static final int LDT_PE_PIECE_REMOVED	= 4;
	private static final int LDT_PE_PM_ADDED		= 5;
	private static final int LDT_PE_PM_REMOVED		= 6;
	
	private ListenerManager	peer_listeners 	= ListenerManager.createAsyncManager(
			"DMM:PeerListenDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		_listener,
					int			type,
					Object		value )
				{
					DownloadManagerPeerListener	listener = (DownloadManagerPeerListener)_listener;
					
					if ( type == LDT_PE_PEER_ADDED ){
						
						listener.peerAdded((PEPeer)value);
						
					}else if ( type == LDT_PE_PEER_REMOVED ){
						
						listener.peerRemoved((PEPeer)value);
						
					}else if ( type == LDT_PE_PIECE_ADDED ){
						
						listener.pieceAdded((PEPiece)value);
						
					}else if ( type == LDT_PE_PIECE_REMOVED ){
						
						listener.pieceRemoved((PEPiece)value);
						
					}else if ( type == LDT_PE_PM_ADDED ){
						
						listener.peerManagerAdded((PEPeerManager)value);
						
					}else if ( type == LDT_PE_PM_REMOVED ){
						
						listener.peerManagerRemoved((PEPeerManager)value);
					}
				}
			});	
	
	private AEMonitor	peer_listeners_mon	= new AEMonitor( "DownloadManager:PL" );
	
	private List	current_peers 	= new ArrayList();
	private List	current_pieces	= new ArrayList();
  
	private DownloadManagerStatsImpl	stats;
	
	private boolean		persistent;
	/**
	 * forceStarted torrents can't/shouldn't be automatically stopped
	 */
	private boolean 	forceStarted;
	/**
	 * Only seed this torrent. Never download or allocate<P>
	 * Current Implementation:
	 * - implies that the user completed the download at one point
	 * - Checks if there's Data Missing when torrent is done (or torrent load)
	 *
	 * Perhaps a better name would be "bCompleted"
	 */
	protected boolean onlySeeding;
	
	private int 		state = -1;
  
	private int prevState = -1;

	private String errorDetail;

	private GlobalManager globalManager;

	private String torrentFileName;

	private int nbPieces;
	
	private String	display_name;
	
	
		// torrent_save_dir is always the directory within which torrent data is being saved. That is, it
		// never includes the torrent data itself. In particular it DOESN'T include the dir name of a
		// non-simple torrent
	
	private String	torrent_save_dir;
	
		// torrent_save_file is the top level file corresponding to the torrent save data location. This
		// will be the file name for simple torrents and the folder name for non-simple ones
	
	private String	torrent_save_file;
	
  
	// Position in Queue
	private int position = -1;
	
  
	//Used when trackerConnection is not yet created.
	// private String trackerUrl;
  
	private PEPeerServer server;
	
	private	DownloadManagerState		download_manager_state;
	
	private TOTorrent		torrent;
	private String 			torrent_comment;
	private String 			torrent_created_by;
	
	private TRTrackerClient 			tracker_client;
	private TRTrackerClientListener		tracker_client_listener;
	
	private long						scrape_random_seed	= SystemTime.getCurrentTime();
	
	private DiskManager 			diskManager;
	private DiskManagerListener		disk_manager_listener;
  
	private PEPeerManager 			peerManager;
	private PEPeerManagerListener	peer_manager_listener;

	private HashMap data;
  
	private boolean data_already_allocated = false;
  
	private long	creation_time	= SystemTime.getCurrentTime();
   
	// Only call this with STATE_QUEUED, STATE_WAITING, or STATE_STOPPED unless you know what you are doing
	
	
	public 
	DownloadManagerImpl(
		GlobalManager 	_gm,
		byte[]			_torrent_hash,
		String 			_torrentFileName, 
		String 			_torrent_save_dir,
		String			_torrent_save_file,
		int   			_initialState,
		boolean			_persistent,
		boolean			_recovered,
		boolean			_open_for_seeding ) 
	{
		persistent	= _persistent;
  	
		stats = new DownloadManagerStatsImpl( this );
  	
		globalManager = _gm;
	
		stats.setMaxUploads( COConfigurationManager.getIntParameter("Max Uploads") );
	 
		forceStarted = false;
	
		torrentFileName = _torrentFileName;
	
		torrent_save_dir	= _torrent_save_dir;	
		torrent_save_file	= _torrent_save_file;
	
			// readTorrent adjusts the save dir and file to be sensible values
			
		readTorrent( _torrent_hash, persistent && !_recovered, _open_for_seeding );
		
			// must be after readTorrent, so that any listeners have a TOTorrent
		
		if (state == -1){
			
			setState( _initialState );
		}
	}

  public void 
  initialize() 
  {
    setState( STATE_INITIALIZING );
         	
    // If we only want to seed, do a quick check first (before we create the diskManager, which allocates diskspace)
    if (onlySeeding && !filesExist()) {
      // If the user wants to re-download the missing files, they must
      // do a re-check, which will reset the onlySeeding flag.
      return;
    }

    if ( torrent == null ) {
    	
      setFailed();
      
      return;
    }

    errorDetail = "";

    startServer();
    
    if ( state == STATE_WAITING || state == STATE_ERROR ){
    	
      return;
    }
    
    try{
      if ( tracker_client != null ){

        tracker_client.destroy();
      }

      tracker_client = TRTrackerClientFactory.create( torrent, server );
    
      tracker_client.setTrackerResponseCache( download_manager_state.getTrackerResponseCache());

      tracker_client_listener = new TRTrackerClientListener() {
        public void receivedTrackerResponse(TRTrackerResponse	response) {
          PEPeerManager pm = peerManager;
          if ( pm != null ) {
            pm.processTrackerResponse( response );
          }

          tracker_listeners.dispatch( LDT_TL_ANNOUNCERESULT, response );
        }

        public void urlChanged(String url, boolean explicit) {
          if ( explicit ){
            checkTracker( true );
          }
        }

        public void urlRefresh() {
          checkTracker( true );
        }
      };

      tracker_client.addListener( tracker_client_listener );

      if ( getState() != STATE_ERROR ){
      	
      		// we need to set the state to "initialized" before kicking off the disk manager
      		// initialisation as it should only report its status while in the "initialized"
      		// state (see getState for how this works...)
      	
      	setState( STATE_INITIALIZED );
          
      	initializeDiskManager();
      }


    }catch( TRTrackerClientException e ){
 		
    	setFailed( e );
			 
    }
  }

  public void 
  startDownload() 
  {
	setState( STATE_DOWNLOADING );
	
	PEPeerManager temp = PEPeerManagerFactory.create(this, server, tracker_client, diskManager);

	peer_manager_listener = 	
		new PEPeerManagerListener()
		{
			public void
			stateChanged(
				int	new_state )
			{
			}
		};
		
	temp.addListener( peer_manager_listener );
		
	temp.start();
	
	try{
		peer_listeners_mon.enter();
		
		peerManager = temp;		// delay this so peerManager var not available to other threads until it is started
	
		peer_listeners.dispatch( LDT_PE_PM_ADDED, temp );
	}finally{
		
		peer_listeners_mon.exit();
	}
	
	tracker_client.update( true );
  }

	private void 
	readTorrent(
		byte[]		torrent_hash,		// can be null for initial torrents
		boolean		new_torrent,		// probably equivalend to (torrent_hash == null)????
		boolean		open_for_seeding )
	{
		display_name				= torrentFileName;	// default if things go wrong decoding it
		//trackerUrl				= "";
		torrent_comment				= "";
		torrent_created_by			= "";
		nbPieces					= 0;
		
		try {

			 download_manager_state	= 
				 	DownloadManagerStateImpl.getDownloadState(
				 			this, torrentFileName, torrent_hash );
			 
			 torrent	= download_manager_state.getTorrent();
			 
			 LocaleUtilDecoder	locale_decoder = LocaleUtil.getSingleton().getTorrentEncoding( torrent );
					 
			 	// if its a simple torrent and an explicit save file wasn't supplied, use
			 	// the torrent name itself
			 
			 display_name = locale_decoder.decodeString( torrent.getName());
             
			 display_name = FileUtil.convertOSSpecificChars( display_name );
		
			 	// now we know if its a simple torrent or not we can make some choices about
			 	// the save dir and file. On initial entry the save_dir will have the user-selected
			 	// save location and the save_file will be null
			 
			 File	save_dir_file	= new File( torrent_save_dir );
			 
			 // System.out.println( "before: " + torrent_save_dir + "/" + torrent_save_file );
			 
			 	// if save file is non-null then things have already been sorted out
			 
			 if ( torrent_save_file == null ){
			 		 	
			 	if ( torrent.isSimpleTorrent()){
			 		
			 			// if target save location is a directory then we use that as the save
			 			// dir and use the torrent display name as the target. Otherwise we
			 			// use the file name
			 		
			 		if ( save_dir_file.exists()){
			 			
			 			if ( save_dir_file.isDirectory()){
			 				
			 				torrent_save_file	= display_name;
			 				
			 			}else{
			 				
			 				torrent_save_dir	= save_dir_file.getParent().toString();
			 				
			 				torrent_save_file	= save_dir_file.getName();
			 			}
			 		}else{
			 			

⌨️ 快捷键说明

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