// files for dnd files which then force a recheck when the download
// starts for the first time)
if ( target_file.exists()){
CacheFile cache_file =
CacheFileManagerFactory.getSingleton().createFile(
new CacheFileOwner()
{
public String
getCacheFileOwnerName()
{
return( download_manager.getInternalName());
}
public TOTorrentFile
getCacheFileTorrentFile()
{
return( res[idx].getTorrentFile() );
}
public File
getCacheFileControlFileDir()
{
return( download_manager.getDownloadState().getStateFile( ));
}
public int
getCacheMode()
{
return( CacheFileOwner.CACHE_MODE_NORMAL );
}
},
target_file,
DiskManagerUtil.convertDMStorageTypeToCache( newStorageType ));
cache_file.close();
toSkip[i] = ( newStorageType == FileSkeleton.ST_COMPACT || newStorageType == FileSkeleton.ST_REORDER_COMPACT )&& !res[i].isSkipped();
if(toSkip[i])
toSkipCount++;
}
modified[i] = true;
}catch( Throwable e ){
Debug.printStackTrace(e);
Logger.log(
new LogAlert(download_manager,
LogAlert.REPEATABLE,
LogAlert.AT_ERROR,
"Failed to change storage type for '" + res[i].getFile(true) +"': " + Debug.getNestedExceptionMessage(e)));
// download's not running - tag for recheck
RDResumeHandler.recheckFile( download_manager, res[i] );
}
types[i] = DiskManagerUtil.convertDMStorageTypeToString( newStorageType );
}
/*
* set storage type and skipped before we do piece clearing and file
* clearing checks as those checks work better when skipped/stype is set
* properly
*/
dmState.setListAttribute( DownloadManagerState.AT_FILE_STORE_TYPES, types);
if(toSkipCount > 0)
setSkipped(toSkip, true);
for(int i=0;i<res.length;i++)
{
if(!toChange[i])
continue;
// download's not running, update resume data as necessary
int cleared = RDResumeHandler.storageTypeChanged( download_manager, res[i] );
// try and maintain reasonable figures for downloaded. Note that because
// we don't screw with the first and last pieces of the file during
// storage type changes we don't have the problem of dealing with
// the last piece being smaller than torrent piece size
if (cleared > 0)
{
res[i].downloaded = res[i].downloaded - cleared * res[i].getTorrentFile().getTorrent().getPieceLength();
if (res[i].downloaded < 0) res[i].downloaded = 0;
}
}
DiskManagerImpl.storeFileDownloaded( download_manager, res, true );
doFileExistenceChecks(this, toChange, download_manager, newStorageType == FileSkeleton.ST_LINEAR || newStorageType == FileSkeleton.ST_REORDER );
} finally {
dmState.suppressStateSave(false);
dmState.save();
}
return modified;
}
};
for (int i=0;i<res.length;i++){
final TOTorrentFile torrent_file = torrent_files[i];
final int file_index = i;
FileSkeleton info = new FileSkeleton() {
private CacheFile read_cache_file;
// do not access this field directly, use lazyGetFile() instead
private WeakReference dataFile = new WeakReference(null);
public void
setPriority(int b)
{
priority = b;
DiskManagerImpl.storeFilePriorities( download_manager, res );
listener.filePriorityChanged( this );
}
public void
setSkipped(boolean _skipped)
{
if ( !_skipped && getStorageType() == ST_COMPACT ){
if ( !setStorageType( ST_LINEAR )){
return;
}
}
if ( !_skipped && getStorageType() == ST_REORDER_COMPACT ){
if ( !setStorageType( ST_REORDER )){
return;
}
}
skipped = _skipped;
DiskManagerImpl.storeFilePriorities( download_manager, res );
if(!_skipped)
{
boolean[] toCheck = new boolean[fileSetSkeleton.nbFiles()];
toCheck[file_index] = true;
doFileExistenceChecks(fileSetSkeleton, toCheck, download_manager, true);
}
listener.filePriorityChanged( this );
}
public int
getAccessMode()
{
return( READ );
}
public long
getDownloaded()
{
return( downloaded );
}
public void
setDownloaded(
long l )
{
downloaded = l;
}
public String
getExtension()
{
String ext = lazyGetFile().getName();
if ( incomplete_suffix != null && ext.endsWith( incomplete_suffix )){
ext = ext.substring( 0, ext.length() - incomplete_suffix.length());
}
int separator = ext.lastIndexOf(".");
if (separator == -1)
separator = 0;
return ext.substring(separator);
}
public int
getFirstPieceNumber()
{
return( torrent_file.getFirstPieceNumber());
}
public int
getLastPieceNumber()
{
return( torrent_file.getLastPieceNumber());
}
public long
getLength()
{
return( torrent_file.getLength());
}
public int
getIndex()
{
return( file_index );
}
public int
getNbPieces()
{
return( torrent_file.getNumberOfPieces());
}
public int
getPriority()
{
return( priority );
}
public boolean
isSkipped()
{
return( skipped );
}
public DiskManager
getDiskManager()
{
return( null );
}
public DownloadManager
getDownloadManager()
{
return( download_manager );
}
public File
getFile(
boolean follow_link )
{
if ( follow_link ){
File link = getLink();
if ( link != null ){
return( link );
}
}
return lazyGetFile();
}
private File lazyGetFile()
{
File toReturn = (File)dataFile.get();
if(toReturn != null)
return toReturn;
TOTorrent tor = download_manager.getTorrent();
String path_str = root_dir;
File simpleFile = null;
// for a simple torrent the target file can be changed
if ( tor.isSimpleTorrent()){
simpleFile = download_manager.getAbsoluteSaveLocation();
}else{
byte[][]path_comps = torrent_file.getPathComponents();
for (int j=0;j<path_comps.length;j++){
String comp;
try
{
comp = locale_decoder.decodeString( path_comps[j] );
} catch (UnsupportedEncodingException e)
{
Debug.printStackTrace(e);
comp = "undecodableFileName"+file_index;
}
comp = FileUtil.convertOSSpecificChars( comp, j != path_comps.length-1 );
path_str += (j==0?"":File.separator) + comp;
}
}
dataFile = new WeakReference(toReturn = simpleFile != null ? simpleFile : new File( path_str ));
//System.out.println("new file:"+toReturn);
return toReturn;
}
public TOTorrentFile
getTorrentFile()
{
return( torrent_file );
}
public boolean
setLink(
File link_destination )
{
/**
* If we a simple torrent, then we'll redirect the call to the download and move the
* data files that way - that'll keep everything in sync.
*/
if (download_manager.getTorrent().isSimpleTorrent()) {
try {
download_manager.moveDataFiles(link_destination.getParentFile(), link_destination.getName());
return true;
}
catch (DownloadManagerException e) {
// What should we do with the error?
return false;
}
}
return setLinkAtomic(link_destination);
}
public boolean
setLinkAtomic(
File link_destination )
{
return( setFileLink( download_manager, res, this, lazyGetFile(), link_destination ));
}
public File
getLink()
{
return( download_manager.getDownloadState().getFileLink( lazyGetFile() ));
}
public boolean setStorageType(int type) {
boolean[] change = new boolean[res.length];
change[file_index] = true;
return fileSetSkeleton.setStorageTypes(change, type)[file_index];
}
public int
getStorageType()
{
return( DiskManagerUtil.convertDMStorageTypeFromString( DiskManagerImpl.getStorageType(download_manager, file_index)));
}
public void
flushCache()
{
}
public DirectByteBuffer
read(
long offset,
int length )
throws IOException
{
CacheFile temp;;
try{
cache_read_mon.enter();
if ( read_cache_file == null ){
try{
int type = convertDMStorageTypeFromString( DiskManagerImpl.getStorageType(download_manager, file_index));
read_cache_file =
CacheFileManagerFactory.getSingleton().createFile(
new CacheFileOwner()
{
public String
getCacheFileOwnerName()
{
return( download_manager.getInternalName());
}
public TOTorrentFile
getCacheFileTorrentFile()
{
return( torrent_file );
}
public File
getCacheFileControlFileDir()
{
return( download_manager.getDownloadState().getStateFile( ));
}
public int
getCacheMode()
{
return( CacheFileOwner.CACHE_MODE_NORMAL );
}
},
getFile( true ),
convertDMStorageTypeToCache( type ));
}catch( Throwable e ){
Debug.printStackTrace(e);
throw( new IOException( e.getMessage()));
}
}
temp = read_cache_file;
}finally{
cache_read_mon.exit();
}
DirectByteBuffer buffer =
DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_DM_READ, length );
try{
temp.read( buffer, offset, CacheFile.CP_READ_CACHE );
}catch( Throwable e ){
buffer.returnToPool();
Debug.printStackTrace(e);
throw( new IOException( e.getMessage()));
}
return( buffer );
}
public void
close()
{
CacheFile temp;
try{
cache_read_mon.enter();
temp = read_cache_file;
read_cache_file = null;
}finally{
cache_read_mon.exit();
}
if ( temp != null ){
try{
temp.close();
}catch( Throwable e ){
Debug.printStackTrace(e);
}