FMFileAccessLinearpublic 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 void | flush()
// no state to flush
| public long | getLength(java.io.RandomAccessFile raf)
try{
return( raf.length());
}catch( Throwable e ){
throw( new FMFileManagerException( "getLength fails", e ));
}
| public java.lang.String | getString()
return( "linear" );
| public void | read(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 void | read(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 void | setLength(java.io.RandomAccessFile raf, long length)
try{
raf.setLength( length );
}catch( Throwable e ){
throw( new FMFileManagerException( "setLength fails", e ));
}
| public void | write(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 ));
}
|
|