rdresumehandler.java
来自「Azureus is a powerful, full-featured, cr」· Java 代码 · 共 784 行 · 第 1/2 页
JAVA
784 行
/*
* Created on 31-Jul-2004
* Created by Paul Gardner
* Copyright (C) 2004 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, SARL au capital de 30,000 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.disk.impl.resume;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.io.File;
import org.gudy.azureus2.core3.logging.LGLogger;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.download.*;
import org.gudy.azureus2.core3.disk.impl.*;
import org.gudy.azureus2.core3.disk.impl.access.*;
import org.gudy.azureus2.core3.disk.*;
import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException;
/**
* @author parg
*
*/
public class
RDResumeHandler
implements ParameterListener
{
protected DiskManagerHelper disk_manager;
protected DMWriterAndChecker writer_and_checker;
protected DownloadManagerState download_manager_state;
protected TOTorrent torrent;
protected int nbPieces;
protected int pieceLength;
protected int lastPieceLength;
protected boolean bOverallContinue;
protected boolean useFastResume = COConfigurationManager.getBooleanParameter("Use Resume", true);
public
RDResumeHandler(
DiskManagerHelper _disk_manager,
DMWriterAndChecker _writer_and_checker )
{
disk_manager = _disk_manager;
writer_and_checker = _writer_and_checker;
download_manager_state = disk_manager.getDownloadManager().getDownloadState();
torrent = disk_manager.getTorrent();
nbPieces = disk_manager.getNumberOfPieces();
pieceLength = disk_manager.getPieceLength();
lastPieceLength = disk_manager.getLastPieceLength();
}
public void
start()
{
COConfigurationManager.addParameterListener("Use Resume", this);
bOverallContinue = true;
}
public void
stop()
{
bOverallContinue = false;
COConfigurationManager.removeParameterListener("Use Resume", this);
}
public void
parameterChanged(
String parameterName )
{
useFastResume = COConfigurationManager.getBooleanParameter("Use Resume", true);
}
public void
checkAllPieces(
boolean newfiles )
{
//long start = System.currentTimeMillis();
try{
disk_manager.setState( DiskManager.CHECKING );
boolean resumeEnabled = useFastResume;
//disable fast resume if a new file was created
if (newfiles){
resumeEnabled = false;
}
boolean resume_data_complete = false;
final AESemaphore pending_checks_sem = new AESemaphore( "RD:PendingChecks" );
int pending_check_num = 0;
DiskManagerPiece[] pieces = disk_manager.getPieces();
if ( resumeEnabled ){
boolean resumeValid = false;
byte[] resumeArray = null;
Map partialPieces = null;
Map resumeMap = download_manager_state.getResumeData();
if ( resumeMap != null ){
// backward compatability here over path management changes :(
String resume_key =
torrent.isSimpleTorrent()?
disk_manager.getDownloadManager().getTorrentSaveDir():
disk_manager.getDownloadManager().getTorrentSaveDirAndFile();
String[] resume_keys = new String[4];
// see bug 869749 for explanation of this mangling
// unfortunately, if the torrent hasn't been saved and restored then the
// mangling with not yet have taken place. So we have to also try the
// original key (see 878015)
// also I've introduced canonicalisation into the resume key (2.1.0.5), so until any migration
// issues have been resolved we need to support both original + non-canonicalised forms
resume_keys[0] = resume_key;
try{
resume_keys[1]= new String( resume_key.getBytes(Constants.DEFAULT_ENCODING),Constants.BYTE_ENCODING);
// System.out.println( "resume: path = " + ByteFormatter.nicePrint(path )+ ", mangled_path = " + ByteFormatter.nicePrint(mangled_path));
}catch( Throwable e ){
Debug.printStackTrace( e );
}
resume_keys[2] = getCanonicalResumeKey( resume_key );
try{
resume_keys[3]= new String( resume_keys[2].getBytes(Constants.DEFAULT_ENCODING),Constants.BYTE_ENCODING);
// System.out.println( "resume: path = " + ByteFormatter.nicePrint(path )+ ", mangled_path = " + ByteFormatter.nicePrint(mangled_path));
}catch( Throwable e ){
Debug.printStackTrace( e );
}
Map resumeDirectory = null;
for (int i=0;i<resume_keys.length;i++){
String rk = resume_keys[i];
if ( rk != null ){
resumeDirectory = (Map)resumeMap.get(rk);
if ( resumeDirectory != null ){
break;
}
}
}
if ( resumeDirectory != null ){
try {
resumeArray = (byte[])resumeDirectory.get("resume data");
if ( resumeArray != null ){
if ( resumeArray.length != pieces.length ){
Debug.out( "Resume data array length mismatch: " + resumeArray.length + "/" + pieces.length );
resumeArray = null;
}
}
partialPieces = (Map)resumeDirectory.get("blocks");
resumeValid = ((Long)resumeDirectory.get("valid")).intValue() == 1;
// if the torrent download is complete we don't need to invalidate the
// resume data
if ( isTorrentResumeDataComplete(
download_manager_state,
disk_manager.getDownloadManager().getTorrentSaveDir(),
disk_manager.getDownloadManager().getTorrentSaveFile())){
resume_data_complete = true;
}else{
resumeDirectory.put("valid", new Long(0));
download_manager_state.save();
}
}catch(Exception ignore){
// ignore.printStackTrace();
}
}else{
// System.out.println( "resume dir not found");
}
}
if ( resumeArray == null ){
resumeValid = false;
resumeArray = new byte[pieces.length];
}
// calculate the current file sizes up front for performance reasons
DiskManagerFileInfo[] files = disk_manager.getFiles();
Map file_sizes = new HashMap();
for (int i=0;i<files.length;i++){
try{
Long len = new Long(((DiskManagerFileInfoImpl)files[i]).getCacheFile().getLength());
file_sizes.put( files[i], len );
}catch( CacheFileManagerException e ){
Debug.printStackTrace(e);
}
}
for (int i = 0; i < pieces.length && bOverallContinue; i++){
DiskManagerPiece dm_piece = pieces[i];
disk_manager.setPercentDone(((i + 1) * 1000) / nbPieces );
boolean ok = resumeArray[i] == 1;
// valid resume data means that the resume array correctly represents
// the state of pieces on disk, be they done or not
if ( ok ){
// at least check that file sizes are OK for this piece to be valid
PieceList list = disk_manager.getPieceList(i);
for (int j=0;j<list.size();j++){
PieceMapEntry entry = list.get(j);
Long file_size = (Long)file_sizes.get(entry.getFile());
if ( file_size == null ){
ok = false;
LGLogger.log(0, 0, LGLogger.INFORMATION, "Piece #" + i + ": file is missing, fails re-check." );
break;
}
long expected_size = entry.getOffset() + entry.getLength();
if ( file_size.longValue() < expected_size ){
ok = false;
LGLogger.log(0, 0, LGLogger.INFORMATION, "Piece #" + i + ": file is too small, fails re-check. File size = " + file_size + ", piece needs " + expected_size );
break;
}
}
}
if ( ok ){
dm_piece.setDone( ok );
}else{
// We only need to recheck blocks that are marked as not-ok
// if the resume data is invalid
if ( !resumeValid ){
try{
writer_and_checker.checkPiece(
i,
new CheckPieceResultHandler()
{
public void
processResult(
int piece_number,
int result,
Object user_data )
{
LGLogger.log(0, 0, LGLogger.INFORMATION, "Piece #" + piece_number + (result==CheckPieceResultHandler.OP_SUCCESS?" passed":" failed") + " re-check.");
pending_checks_sem.release();
}
},
null );
pending_check_num++;
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
}
if ( partialPieces != null && resumeValid ){
Iterator iter = partialPieces.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry key = (Map.Entry)iter.next();
int pieceNumber = Integer.parseInt((String)key.getKey());
List blocks = (List)partialPieces.get(key.getKey());
Iterator iterBlock = blocks.iterator();
while (iterBlock.hasNext()) {
pieces[pieceNumber].setWritten(((Long)iterBlock.next()).intValue());
}
}
}
}else{
// resume not enabled, recheck everything
for (int i = 0; i < pieces.length && bOverallContinue; i++){
disk_manager.setPercentDone(((i + 1) * 1000) / nbPieces );
try{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?