FileDocCategorySizeDatePackage
FMFileAccessLinear.javaAPI DocAzureus 3.0.3.48321Fri Dec 15 08:41:18 GMT 2006com.aelitis.azureus.core.diskmanager.file.impl

FMFileAccessLinear

public class FMFileAccessLinear extends Object implements FMFileAccess

Fields Summary
private static final int
WRITE_RETRY_LIMIT
private static final int
WRITE_RETRY_DELAY
private static final int
READ_RETRY_LIMIT
private static final int
READ_RETRY_DELAY
private static final boolean
DEBUG
private static final boolean
DEBUG_VERBOSE
private FMFileImpl
owner
Constructors Summary
protected FMFileAccessLinear(FMFileImpl _owner)

	
	
	
				 
	
		owner	= _owner;
	
Methods Summary
public voidflush()

		// no state to flush
	
public longgetLength(java.io.RandomAccessFile raf)

		try{
			return( raf.length());
			
		}catch( Throwable e ){
			
			throw( new FMFileManagerException( "getLength fails", e ));
		}
	
public java.lang.StringgetString()

		return( "linear" );
	
public voidread(java.io.RandomAccessFile raf, org.gudy.azureus2.core3.util.DirectByteBuffer buffer, long offset)

		if (raf == null){
			
			throw new FMFileManagerException( "read: raf is null" );
		}
    
		FileChannel fc = raf.getChannel();
    		
		if ( !fc.isOpen()){
			
			Debug.out("FileChannel is closed: " + owner.getName());
			
			throw( new FMFileManagerException( "read - file is closed"));
		}

		try{
			fc.position(offset);
			
			while (fc.position() < fc.size() && buffer.hasRemaining(DirectByteBuffer.SS_FILE)){
				
				buffer.read(DirectByteBuffer.SS_FILE,fc);
			}
			
		}catch ( Exception e ){
			
			Debug.printStackTrace( e );
			
			throw( new FMFileManagerException( "read fails", e ));
		}
	
public voidread(java.io.RandomAccessFile raf, org.gudy.azureus2.core3.util.DirectByteBuffer[] buffers, long offset)

		if ( raf == null ){
			
			throw new FMFileManagerException( "read: raf is null" );
		}
    
		FileChannel fc = raf.getChannel();
    		
		if ( !fc.isOpen()){
			
			Debug.out("FileChannel is closed: " + owner.getName());
			
			throw( new FMFileManagerException( "read - file is closed"));
		}
		
		try{			
			fc.position(offset);
			
			ByteBuffer[]	bbs = new ByteBuffer[buffers.length];
			
			ByteBuffer	last_bb	= null;
			
			for (int i=0;i<bbs.length;i++){
				
				bbs[i] = buffers[i].getBuffer(DirectByteBuffer.SS_FILE);
				
				if ( bbs[i].position() != bbs[i].limit()){
					
					last_bb	= bbs[i];
				}
			}
			
			if ( last_bb != null ){
									  
				int		loop			= 0;
				
					// we sometimes read off the end of the file (when rechecking) so
					// bail out if we've completed the read or got to file end
					// a "better" fix would be to prevent the over-read in the first
					// place, but hey, we're just about to release and there may be other
					// instances of this...

				while ( fc.position() < fc.size() && last_bb.hasRemaining()){
					
					long	read = fc.read( bbs );
									
					if ( read > 0 ){
						
						loop	= 0;
						
					}else{
					
						loop++;
						
						if ( loop == READ_RETRY_LIMIT ){
							
							Debug.out( "FMFile::read: zero length read - abandoning" );
						
							throw( new FMFileManagerException( "read fails: retry limit exceeded"));
							
						}else{
							
							if ( DEBUG_VERBOSE ){
								
								Debug.out( "FMFile::read: zero length read - retrying" );
							}
							
							try{
								Thread.sleep( READ_RETRY_DELAY*loop );
								
							}catch( InterruptedException e ){
								
								throw( new FMFileManagerException( "read fails: interrupted" ));
							}
						}
					}						
				}
			}
		}catch ( Exception e ){
			
			try{
				Debug.out( "Read failed: " + owner.getString() + ": raf open=" + raf.getChannel().isOpen() + ", len=" + raf.length() + ",off=" + offset );
				
			}catch( IOException f ){
			}
			
			Debug.printStackTrace( e );
			
			throw( new FMFileManagerException( "read fails", e ));
		}
	
public voidsetLength(java.io.RandomAccessFile raf, long length)

		try{			
			raf.setLength( length );
			
		}catch( Throwable e ){
			
			throw( new FMFileManagerException( "setLength fails", e ));
		}
	
public voidwrite(java.io.RandomAccessFile raf, org.gudy.azureus2.core3.util.DirectByteBuffer[] buffers, long position)

		if (raf == null){
			
			throw( new FMFileManagerException( "write fails: raf is null" ));
		}
    
		FileChannel fc = raf.getChannel();
    
		try{
			if (fc.isOpen()){
				
				long	expected_write 	= 0;
				long	actual_write	= 0;
				boolean	partial_write	= false;
				
				if ( DEBUG ){
				
					for (int i=0;i<buffers.length;i++){
						
						expected_write += buffers[i].limit(DirectByteBuffer.SS_FILE) - buffers[i].position(DirectByteBuffer.SS_FILE);
					}
				}
				
				fc.position( position );
									
				ByteBuffer[]	bbs = new ByteBuffer[buffers.length];
				
				ByteBuffer	last_bb	= null;
				
				for (int i=0;i<bbs.length;i++){
					
					bbs[i] = buffers[i].getBuffer(DirectByteBuffer.SS_FILE);
					
					if ( bbs[i].position() != bbs[i].limit()){
						
						last_bb	= bbs[i];
					}
				}
				
				if ( last_bb != null ){
										  
					int		loop			= 0;
					
					while( last_bb.position() != last_bb.limit()){
						
						long	written = fc.write( bbs );
						
						actual_write	+= written;
						
						if ( written > 0 ){
							
							loop	= 0;
							
							if ( DEBUG ){
								
								if ( last_bb.position() != last_bb.limit()){
								
									partial_write	= true;
									
									if ( DEBUG_VERBOSE ){
										
										Debug.out( "FMFile::write: **** partial write **** this = " + written + ", total = " + actual_write + ", target = " + expected_write );
									}
								}
							}
							
						}else{
						
							loop++;
							
							if ( loop == WRITE_RETRY_LIMIT ){
								
								Debug.out( "FMFile::write: zero length write - abandoning" );
							
								throw( new FMFileManagerException( "write fails: retry limit exceeded"));
								
							}else{
								
								if ( DEBUG_VERBOSE ){
									
									Debug.out( "FMFile::write: zero length write - retrying" );
								}
								
								try{
									Thread.sleep( WRITE_RETRY_DELAY*loop );
									
								}catch( InterruptedException e ){
									
									throw( new FMFileManagerException( "write fails: interrupted" ));
								}
							}
						}						
					}
				}
				
				if ( DEBUG ){

					if ( expected_write != actual_write ){
						
						Debug.out( "FMFile::write: **** partial write **** failed: expected = " + expected_write + ", actual = " + actual_write );

						throw( new FMFileManagerException( "write fails: expected write/actual write mismatch" ));
					
					}else{
						
						if ( partial_write && DEBUG_VERBOSE ){
							
							Debug.out( "FMFile::write: **** partial write **** completed ok" );
						}
					}
				}
			}else{
								
				throw( new FMFileManagerException( "write fails, channel not open" ));
			}
			
		}catch (Exception e ){
						
			throw( new FMFileManagerException( "write fails", e ));
		}