📄 diskmanagerimpl.java
字号:
/*
* 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, 2005, 2006 Aelitis, All Rights Reserved.
*
*/
package org.gudy.azureus2.core3.disk.impl;
import java.io.*;
import java.util.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.disk.impl.access.*;
import org.gudy.azureus2.core3.disk.impl.piecemapper.*;
import org.gudy.azureus2.core3.disk.impl.resume.RDResumeHandler;
import org.gudy.azureus2.core3.download.*;
import org.gudy.azureus2.core3.download.impl.DownloadManagerDefaultPaths;
import org.gudy.azureus2.core3.internat.*;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.platform.*;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import com.aelitis.azureus.core.diskmanager.access.*;
import com.aelitis.azureus.core.diskmanager.cache.*;
import com.aelitis.azureus.core.diskmanager.file.FMFileManagerFactory;
import com.aelitis.azureus.core.util.CaseSensitiveFileMap;
/**
*
* The disk Wrapper.
*
* @author Tdv_VgA
* @author MjrTom
* 2005/Oct/08: new piece-picking support changes
* 2006/Jan/02: refactoring piece picking related code
*
*/
public class
DiskManagerImpl
extends LogRelation
implements DiskManagerHelper
{
private static final LogIDs LOGID = LogIDs.DISK;
private static DiskAccessController disk_access_controller;
static {
int max_read_threads = COConfigurationManager.getIntParameter( "diskmanager.perf.read.maxthreads" );
int max_read_mb = COConfigurationManager.getIntParameter( "diskmanager.perf.read.maxmb" );
int max_write_threads = COConfigurationManager.getIntParameter( "diskmanager.perf.write.maxthreads" );
int max_write_mb = COConfigurationManager.getIntParameter( "diskmanager.perf.write.maxmb" );
disk_access_controller =
DiskAccessControllerFactory.create(
max_read_threads, max_read_mb,
max_write_threads, max_write_mb );
if (Logger.isEnabled()){
Logger.log(
new LogEvent(
LOGID,
"Disk access controller params: " +
max_read_threads + "/" + max_read_mb + "/" + max_write_threads + "/" + max_write_mb ));
}
}
private static DiskManagerRecheckScheduler recheck_scheduler = new DiskManagerRecheckScheduler();
private static DiskManagerAllocationScheduler allocation_scheduler = new DiskManagerAllocationScheduler();
private static ThreadPool start_pool = new ThreadPool( "DiskManager:start", 64, true );
static{
start_pool.setThreadPriority( Thread.MIN_PRIORITY );
}
private static AEMonitor cache_read_mon = new AEMonitor( "DiskManager:cacheRead" );
private boolean used = false;
private boolean started = false;
private AESemaphore started_sem = new AESemaphore( "DiskManager::started" );
private boolean starting;
private boolean stopping;
private int state_set_via_method;
protected String errorMessage = "";
private int pieceLength;
private int lastPieceLength;
private int nbPieces; // total # pieces in this torrent
private long totalLength; // total # bytes in this torrent
private int percentDone;
private long allocated;
private long remaining;
private TOTorrent torrent;
private DMReader reader;
private DMChecker checker;
private DMWriter writer;
private RDResumeHandler resume_handler;
private DMPieceMapper piece_mapper;
private DiskManagerPieceImpl[] pieces;
private DMPieceList[] pieceMap;
private DiskManagerFileInfoImpl[] files;
protected DownloadManager download_manager;
private boolean alreadyMoved = false;
private boolean skipped_file_set_changed =true; // go over them once when starting
private long skipped_file_set_size;
private long skipped_but_downloaded;
// DiskManager listeners
private static final int LDT_STATECHANGED = 1;
private static final int LDT_PRIOCHANGED = 2;
private static final int LDT_PIECE_DONE_CHANGED = 3;
private static final int LDT_ACCESS_MODE_CHANGED = 4;
protected static ListenerManager listeners_aggregator = ListenerManager.createAsyncManager(
"DiskM:ListenAggregatorDispatcher",
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]);
}else if (type == LDT_PRIOCHANGED) {
listener.filePriorityChanged((DiskManagerFileInfo)value);
}else if (type == LDT_PIECE_DONE_CHANGED) {
listener.pieceDoneChanged((DiskManagerPiece)value);
}else if (type == LDT_ACCESS_MODE_CHANGED) {
Object[] o = (Object[])value;
listener.fileAccessModeChanged(
(DiskManagerFileInfo)o[0],
((Integer)o[1]).intValue(),
((Integer)o[2]).intValue());
}
}
});
private ListenerManager listeners = ListenerManager.createManager(
"DiskM:ListenDispatcher",
new ListenerManagerDispatcher()
{
public void
dispatch(
Object listener,
int type,
Object value )
{
listeners_aggregator.dispatch( listener, type, value );
}
});
private AEMonitor start_stop_mon = new AEMonitor( "DiskManager:startStop" );
private AEMonitor file_piece_mon = new AEMonitor( "DiskManager:filePiece" );
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 ){
errorMessage = "Torrent not available";
setState( FAULTY );
return;
}
LocaleUtilDecoder locale_decoder = null;
try{
locale_decoder = LocaleTorrentUtil.getTorrentEncoding( torrent );
}catch( TOTorrentException e ){
Debug.printStackTrace( e );
errorMessage = TorrentUtils.exceptionToText(e);
setState( FAULTY );
return;
}catch( Throwable e ){
Debug.printStackTrace( e );
errorMessage = "Initialisation failed - " + Debug.getNestedExceptionMessage(e);
setState( FAULTY );
return;
}
piece_mapper = DMPieceMapperFactory.create( torrent );
try{
piece_mapper.construct( locale_decoder, download_manager.getAbsoluteSaveLocation().getName());
}catch( Throwable e ){
Debug.printStackTrace( e );
errorMessage = "Failed to build piece map - " + Debug.getNestedExceptionMessage(e);
setState( 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 <nbPieces; i++)
{
pieces[i] =new DiskManagerPieceImpl(this, i);
}
reader = DMAccessFactory.createReader(this);
checker = DMAccessFactory.createChecker(this);
writer = DMAccessFactory.createWriter(this);
resume_handler = new RDResumeHandler( this, checker );
}
public void
start()
{
try{
start_stop_mon.enter();
if ( used ){
Debug.out( "DiskManager reuse not supported!!!!" );
}
used = true;
if ( getState() == FAULTY ){
Debug.out( "starting a faulty disk manager");
return;
}
started = true;
starting = true;
start_pool.run(
new AERunnable()
{
public void
runSupport()
{
try{
// now we use a limited pool to manage disk manager starts there
// is an increased possibility of us being stopped before starting
// handle this situation better by avoiding an un-necessary "startSupport"
try{
start_stop_mon.enter();
if ( stopping ){
throw( new Exception( "Stopped during startup" ));
}
}finally{
start_stop_mon.exit();
}
startSupport();
}catch( Throwable e ){
errorMessage = Debug.getNestedExceptionMessage(e) + " (start)";
Debug.printStackTrace(e);
setState( FAULTY );
}finally{
started_sem.release();
}
boolean stop_required;
try{
start_stop_mon.enter();
stop_required = DiskManagerImpl.this.getState() == DiskManager.FAULTY || stopping;
starting = false;
}finally{
start_stop_mon.exit();
}
if ( stop_required ){
DiskManagerImpl.this.stop( false );
}
}
});
}finally{
start_stop_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 && download_manager.isPersistent()){
//if the data file already resides in the completed files dir
if ( filesExist( moveToDir )){
alreadyMoved = true;
download_manager.setTorrentSaveDir( moveToDir );
}
}
reader.start();
checker.start();
writer.start();
//allocate / check every file
int newFiles = allocateFiles();
if ( getState() == FAULTY ){
// bail out if broken in the meantime
// state will be "faulty" if the allocation process is interrupted by a stop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -