diskmanagerimpl.java

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

JAVA
1,458
字号
/*
 * Azureus - a Java Bittorrent client
 *
 * This program is free software; you can redistribute it and/or modify
 * 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
 * 
 * Created on Oct 18, 2003
 * Created by Paul Gardner
 * Modified Apr 13, 2004 by Alon Rohter
 * Copyright (C) 2004 Aelitis, All Rights Reserved.
 * 
 */

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

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;


import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.disk.impl.piecepicker.*;
import org.gudy.azureus2.core3.disk.impl.access.*;
import org.gudy.azureus2.core3.disk.impl.resume.*;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.internat.*;
import org.gudy.azureus2.core3.logging.*;
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.util.*;

import com.aelitis.azureus.core.diskmanager.cache.*;

/**
 * 
 * The disk Wrapper.
 * 
 * @author Tdv_VgA
 *
 */
public class 
DiskManagerImpl
	implements DiskManagerHelper 
{  
	private String	dm_name	= "";
	
	private boolean	used	= false;
	
	private boolean started = false;
  
	private int state_set_via_method;
	private String errorMessage = "";

	private int pieceLength;
	private int lastPieceLength;

	private int 		nbPieces;
	private long 		totalLength;
	private int 		percentDone;
	private long 		allocated;
	private long 		remaining;

    
	private	TOTorrent		torrent;


	private DMReader				reader;
	private DMWriterAndChecker		writer_and_checker;
	
	private RDResumeHandler			resume_handler;
	private DMPiecePicker			piece_picker;
	private DiskManagerPieceMapper	piece_mapper;
	
	
	
	private DiskManagerPieceImpl[]	pieces;
	private PieceList[] 			pieceMap;

	private DiskManagerFileInfoImpl[] 	files;
	
    private DownloadManager 			download_manager;

	private boolean alreadyMoved = false;

		// DiskManager listeners
	
	private static final int LDT_STATECHANGED		= 1;
	
	private ListenerManager	listeners 	= ListenerManager.createManager(
			"DiskM:ListenDispatcher",
			new ListenerManagerDispatcher()
			{
				public void
				dispatch(
					Object		_listener,
					int			type,
					Object		value )
				{
					DiskManagerListener	listener = (DiskManagerListener)_listener;
					
					if (type == LDT_STATECHANGED){
						
						int params[] = (int[])value;
						
  						listener.stateChanged(params[0], params[1]);
					}
				}
			});		
	
	protected AEMonitor	this_mon	= new AEMonitor( "DiskManager" );
	
	public 
	DiskManagerImpl(
		TOTorrent			_torrent, 
		DownloadManager 	_dmanager) 
	{
	    torrent 	= _torrent;
	    download_manager 	= _dmanager;
	 
	    pieces		= new DiskManagerPieceImpl[0];	// in case things go wrong later
	    
	    setState( INITIALIZING );
	    
	    percentDone = 0;
	    
		if ( torrent == null ){
			
			setState( FAULTY );
			
			return;
		}
   
		LocaleUtilDecoder	locale_decoder = null;
		
		try{
			locale_decoder = LocaleUtil.getSingleton().getTorrentEncoding( torrent );

			dm_name	= ByteFormatter.nicePrint(torrent.getHash(),true);
			
		}catch( TOTorrentException e ){
			
			Debug.printStackTrace( e );
			
			this.errorMessage = TorrentUtils.exceptionToText(e) + " (Constructor)";
			
			setState( FAULTY );
			
			return;
			
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
			
			this.errorMessage = e.getMessage() + " (Constructor)";
			
			setState( FAULTY );
			
			return;
		}
		
		piece_mapper	= new DiskManagerPieceMapper( this );

			//build something to hold the filenames/sizes
		
		TOTorrentFile[] torrent_files = torrent.getFiles();

		if ( torrent.isSimpleTorrent()){
			 								
			piece_mapper.buildFileLookupTables( torrent_files[0], download_manager.getTorrentSaveFile());

		}else{

			piece_mapper.buildFileLookupTables( torrent_files, locale_decoder );
		}
		
		if ( getState() == FAULTY){
			
			return;
		}

		totalLength	= piece_mapper.getTotalLength();
		
		remaining 	= totalLength;

		nbPieces 	= torrent.getNumberOfPieces();
		
		pieceLength		 	= (int)torrent.getPieceLength();
		
		lastPieceLength  	= piece_mapper.getLastPieceLength();
		
		pieces		= new DiskManagerPieceImpl[ nbPieces ];
		
		for (int i=0;i<pieces.length;i++){
			
			pieces[i] = new DiskManagerPieceImpl( this, i );
		}
		
		reader 				= DMAccessFactory.createReader(this);
		
		writer_and_checker 	= DMAccessFactory.createWriterAndChecker(this);
		
		resume_handler		= new RDResumeHandler( this, writer_and_checker );
	
		piece_picker		= DMPiecePickerFactory.create( this );
	}

	public void 
	start() 
	{
		if ( used ){
			
			Debug.out( "DiskManager reuse not supported!!!!" );
		}
		
		used	= true;
		
		try{
			this_mon.enter();
		
			if ( started ){
				
				return;
			}
			
			if ( getState() == FAULTY ){
				
				Debug.out( "starting a faulty disk manager");
				
				return;
			}
			
			started = true;
	       
		    Thread init = 
		    	new AEThread("DiskManager:start") 
				{
					public void 
					runSupport() 
					{
						startSupport();
						
						if (DiskManagerImpl.this.getState() == DiskManager.FAULTY){
							
							DiskManagerImpl.this.stop();
						}
					}
				};
				
			init.setPriority(Thread.MIN_PRIORITY);
			
			init.start();
			
		}finally{
			
			this_mon.exit();
		}
	}

	private void 
	startSupport() 
	{		
			//if the data file is already in the completed files dir, we want to use it
		
		boolean moveWhenDone = COConfigurationManager.getBooleanParameter("Move Completed When Done", false);
		
		String moveToDir = COConfigurationManager.getStringParameter("Completed Files Directory", "");
   
		if ( moveWhenDone && moveToDir.length() > 0 ){
		
				//if the data file already resides in the completed files dir
					
			if ( filesExist( moveToDir )){
				
				alreadyMoved = true;
		
				download_manager.setTorrentSaveDir( moveToDir );
			}
		}

		writer_and_checker.start();
		
		reader.start();
		
			//allocate / check every file

		files = new DiskManagerFileInfoImpl[piece_mapper.getFileList().size()];
      
		int newFiles = allocateFiles();
      
		if ( getState() == FAULTY){
			
			return;
		}
    
        pieceMap = piece_mapper.constructPieceMap();

		constructFilesPieces();
		
		piece_picker.start();
		
		resume_handler.start();
		  
		if (newFiles == 0){
			
			resume_handler.checkAllPieces(false);
			
		}else if ( newFiles != files.length ){
			
				//	if not a fresh torrent, check pieces ignoring fast resume data
			
			resume_handler.checkAllPieces(true);
		}
		
			//3.Change State   
		
		setState( READY );
	}

	public void 
	stop() 
	{	
		if ( !started ){
			
			return;
		}
		
		started	= false;
		
    	writer_and_checker.stop();
    	
		reader.stop();
		
		resume_handler.stop();
		
		piece_picker.stop();
		
		if (files != null){
			
			for (int i = 0; i < files.length; i++){
				
				try{
					if (files[i] != null) {
						
						files[i].getCacheFile().close();
					}
				}catch (Exception e){
					
					Debug.printStackTrace( e );
				}
			}
		}
	}

	
	
	
	
	
	public boolean
	filesExist()
	{
		return( filesExist( download_manager.getTorrentSaveDir()));
	}

	protected boolean 
	filesExist(
		String	root_dir )
	{
		if ( !torrent.isSimpleTorrent()){
			
			root_dir += File.separator + download_manager.getTorrentSaveFile();
		}
		
		File	root_dir_file = new File( root_dir );
		
		if ( !root_dir_file.exists()){
			
				// look for something sensible to report
			
		  File current = root_dir_file;
		  
		  while( !current.exists()){
			
		  	File	parent = current.getParentFile();
		  	
		  	if ( parent == null ){
		  		
		  		break;
		  		
		  	}else if ( !parent.exists()){
		  		
		  		current	= parent;
		  		
		  	}else{
		  		
		  		if ( parent.isDirectory()){
		  			
		  			errorMessage = current.toString() + " not found.";
		  			
		  		}else{
		  			
		  			errorMessage = parent.toString() + " is not a directory.";
		  		}
		  		
		  		return( false );
		  	}
		  }
		  
		  errorMessage = current + " not found.";
			  
		  return false;
			  
		}else if ( !root_dir_file.isDirectory()){
			
		  errorMessage = root_dir + " is not a directory.";
			  
		  return false;	
		}
		
		root_dir	+= File.separator;
		
		// System.out.println( "root dir = " + root_dir_file );
		
		List btFileList	= piece_mapper.getFileList();
		
		for (int i = 0; i < btFileList.size(); i++) {
				//get the BtFile
			DiskManagerPieceMapper.fileInfo tempFile = (DiskManagerPieceMapper.fileInfo)btFileList.get(i);
				//get the path
			String tempPath = root_dir + tempFile.getPath();
				//get file name
			String tempName = tempFile.getName();
				//System.out.println( "\ttempPath="+tempPath+",tempName="+tempName );
				//get file length
			long length = tempFile.getLength();

			File f = new File(tempPath, tempName);

			if (!f.exists()){
				
			  errorMessage = f.toString() + " not found.";
			  
			  return false;
			  
			}else{
			
					// use the cache file to ascertain length in case the caching/writing algorithm
					// fiddles with the real length
					// Unfortunately we may be called here BEFORE the disk manager has been 
					// started and hence BEFORE the file info has been setup...
					// Maybe one day we could allocate the file info earlier. However, if we do
					// this then we'll need to handle the "already moved" stuff too...
				
				DiskManagerFileInfoImpl	file_info = tempFile.getFileInfo();
				
				boolean	close_it	= false;
				
				try{
					if ( file_info == null ){
						
						file_info = new DiskManagerFileInfoImpl( this, f, tempFile.getTorrentFile());
		
						close_it	= true;					
					}
					
					try{
							// only test for too big as if incremental creation selected
							// then too small is OK
						
						long	existing_length = file_info.getCacheFile().getLength();
						
						if ( existing_length > length ){
							

⌨️ 快捷键说明

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