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 + -
显示快捷键?