FileDocCategorySizeDatePackage
DiskManagerPieceImpl.javaAPI DocAzureus 3.0.3.49620Fri Jul 20 09:13:22 BST 2007org.gudy.azureus2.core3.disk.impl

DiskManagerPieceImpl

public class DiskManagerPieceImpl extends Object implements DiskManagerPiece
author
parg
author
MjrTom 2005/Oct/08: startPriority/resumePriority handling and minor clock fixes 2006/Jan/02: refactoring, change booleans to statusFlags

Fields Summary
private static final byte
PIECE_STATUS_NEEDED
private static final byte
PIECE_STATUS_WRITTEN
private static final byte
PIECE_STATUS_CHECKING
private static final byte
PIECE_STATUS_MASK_DOWNLOADABLE
private static final byte
PIECE_STATUS_MASK_NEEDS_CHECK
private final DiskManagerHelper
diskManager
private final int
pieceNumber
private final short
nbBlocks
the number of blocks in this piece: can be short as this gives up to .5GB piece sizes with 16K blocks
protected volatile boolean[]
written
private byte
statusFlags
private short
read_count
it's *very* important to accurately maintain the "done" state of a piece. Currently the statusFlags are updated in a non-thread-safe manner so a 'done' field is maintained seperatly. Synchronizing access to statusFlags or done would cause a tremendous performance hit.
private boolean
done
Constructors Summary
public DiskManagerPieceImpl(DiskManagerHelper _disk_manager, int pieceIndex, int length)

    
	         
	
		diskManager =_disk_manager;
		pieceNumber = pieceIndex;
		
		nbBlocks =(short)((length +DiskManager.BLOCK_SIZE -1) /DiskManager.BLOCK_SIZE);

		statusFlags = PIECE_STATUS_NEEDED;
	
Methods Summary
public booleancalcDone()

		return done;
	
public booleancalcNeeded()

		boolean filesNeeded =false;
		final DMPieceList pieceList =diskManager.getPieceList(pieceNumber);
		for (int i =0; i <pieceList.size(); i++)
		{
			final DiskManagerFileInfoImpl file =pieceList.get(i).getFile();
			final long fileLength =file.getLength();
			filesNeeded |=fileLength >0 &&file.getDownloaded() <fileLength &&!file.isSkipped();
		}
		if (filesNeeded)
		{
			statusFlags |=PIECE_STATUS_NEEDED;
			return true;
		}
		statusFlags &=~PIECE_STATUS_NEEDED;
		return false;
	
public voidclearNeeded()

		statusFlags &=~PIECE_STATUS_NEEDED;
	
public intgetBlockSize(int blockNumber)

        if ( blockNumber == nbBlocks -1 ){
        
        	int	len = getLength() % DiskManager.BLOCK_SIZE;
        	
        	if ( len != 0 ){
        		
        		return( len );
        	}
        }
        
        return DiskManager.BLOCK_SIZE;
    
public intgetLength()

return
int number of bytes in the piece

		return( diskManager.getPieceLength( pieceNumber ));
	
public DiskManagergetManager()

		return diskManager;
	
public intgetNbBlocks()

		return nbBlocks;
	
public intgetNbWritten()

		if (done)
			return nbBlocks;
		final boolean[] writtenRef =written;
		if (writtenRef ==null)
			return 0;
		int res =0;
		for (int i =0; i <nbBlocks; i++ )
		{
			if (writtenRef[i])
				res++;
		}
		return res;
	
public intgetPieceNumber()

		return pieceNumber;
	
public shortgetReadCount()

		return( read_count );
	
public java.lang.StringgetString()

		String	text = "";
		
		text += ( isNeeded()?"needed,":"" );
		text += ( isDone()?"done,":"" );
		
		if ( !isDone()){
			text += ( isDownloadable()?"downable,":"" );
			text += ( isWritten()?"written":("written " + getNbWritten())) + ",";
			text += ( isChecking()?"checking":"" );
		}
		
		if ( text.endsWith(",")){
			text = text.substring(0,text.length()-1);
		}
		return( text );
	
public boolean[]getWritten()
written[] can be null, in which case if the piece is Done, all blocks are complete otherwise no blocks are complete

		return written;
	
public booleanisChecking()

		return (statusFlags &PIECE_STATUS_CHECKING) !=0;
	
public booleanisDone()

		return done;
	
public booleanisDownloadable()

		return !done &&(statusFlags &PIECE_STATUS_MASK_DOWNLOADABLE) == PIECE_STATUS_NEEDED;
	
public booleanisInteresting()

return
true if the piece is Needed and not Done

		return !done &&(statusFlags &PIECE_STATUS_NEEDED) != 0;
	
public booleanisNeeded()

		return (statusFlags &PIECE_STATUS_NEEDED) !=0;
	
public booleanisNeedsCheck()

    	return !done &&(statusFlags &PIECE_STATUS_MASK_NEEDS_CHECK) ==PIECE_STATUS_WRITTEN;
    
public booleanisSkipped()

		final DMPieceList pieceList =diskManager.getPieceList(pieceNumber);
		for (int i =0; i <pieceList.size(); i++){
			if ( !pieceList.get(i).getFile().isSkipped()){
				return( false );
			}
		}
		return( true );
    
public booleanisWritten()

		return (statusFlags &PIECE_STATUS_WRITTEN) !=0;
	
public booleanisWritten(int blockNumber)

		if (done)
			return true;
		final boolean[] writtenRef =written;
		if (writtenRef ==null)
			return false;
		return writtenRef[blockNumber];
	
public voidreDownloadBlock(int blockNumber)

		final boolean[] written_ref = written;
		if (written_ref !=null)
		{
			written_ref[blockNumber] =false;
			setDownloadable();
		}
	
public voidreset()

		setDownloadable();
		written =null;
	
public voidsetChecking()

		statusFlags |=PIECE_STATUS_CHECKING;
	
public voidsetDone(boolean b)

		// we delegate this operation to the disk manager so it can synchronise the activity
        if (b !=done)
        {
            diskManager.setPieceDone(this, b);
        }
	
public voidsetDoneSupport(boolean b)
this is ONLY used by the disk manager to update the done state while synchronized i.e. don't use it else where!

param
b

        done =b;
        if (done)
            written =null;
	
public voidsetDownloadable()

		
		setDone(false);
		statusFlags &=~(PIECE_STATUS_MASK_DOWNLOADABLE);
		calcNeeded();	// Needed wouldn't have been calced before if couldn't download more
	
public voidsetNeeded()

		statusFlags |=PIECE_STATUS_NEEDED;
	
public voidsetNeeded(boolean b)

		if (b)
			statusFlags |=PIECE_STATUS_NEEDED;
		else
			statusFlags &=~PIECE_STATUS_NEEDED;
	
public voidsetReadCount(short c)

		read_count	= c;
	
public voidsetWritten(int blockNumber)

		if (written ==null)
			written =new boolean[nbBlocks];
		final boolean[] written_ref =written;
		
		written_ref[blockNumber] =true;
		for (int i =0; i <nbBlocks; i++)
		{
			if (!written_ref[i])
				return;
		}
		statusFlags |=PIECE_STATUS_WRITTEN;