Package com.aelitis.azureus.core.diskmanager.cache.impl

Source Code of com.aelitis.azureus.core.diskmanager.cache.impl.CacheFileWithoutCacheMT

/*
* Created on Sep 27, 2007
* Created by Paul Gardner
* Copyright (C) 2007 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, SAS au capital de 63.529,40 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/


package com.aelitis.azureus.core.diskmanager.cache.impl;

import java.io.File;

import org.gudy.azureus2.core3.torrent.TOTorrentFile;
import org.gudy.azureus2.core3.util.DirectByteBuffer;

import com.aelitis.azureus.core.diskmanager.cache.CacheFile;
import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerException;
import com.aelitis.azureus.core.diskmanager.file.FMFile;
import com.aelitis.azureus.core.diskmanager.file.FMFileManagerException;

public class
CacheFileWithoutCacheMT
  implements CacheFile
{
  private static final int MAX_CLONES  = 20;
 
  private static int  num_clones;
  private static int  max_clone_depth;
 
  private CacheFileManagerImpl    manager;
  private FMFile            base_file;
  private FMFile[]          files;
  private int[]            files_use_count;
  private TOTorrentFile        torrent_file;
  private boolean            moving;
 
  protected
  CacheFileWithoutCacheMT(
    CacheFileManagerImpl  _manager,
    FMFile          _file,
    TOTorrentFile      _torrent_file )
  {
    manager      = _manager;
    base_file    = _file;
    torrent_file  = _torrent_file;
   
    files = new FMFile[]{ base_file };
   
    files_use_count = new int[]{ 0 };
  }

  public TOTorrentFile
  getTorrentFile()
  {
    return( torrent_file );
  }
 
  public boolean
  exists()
  {
    return( base_file.exists());
  }
 
  public void
  moveFile(
    File    new_file )
 
    throws CacheFileManagerException
  {
    try{
      synchronized( this ){

        moving = true;
      }
     
      while( true ){
               
        synchronized( this ){
       
          boolean  surviving = false;

          for (int i=1;i<files_use_count.length;i++){
           
            if ( files_use_count[i] > 0 ){
             
              surviving = true;
             
              break;
            }
          }
       
          if ( !surviving ){
           
            for (int i=1;i<files_use_count.length;i++){
             
              FMFile file = files[i];
             
              if ( file.isClone()){
               
                // System.out.println( "Destroyed clone " + file.getName());
               
                synchronized( CacheFileWithoutCacheMT.class ){
                 
                  num_clones--;
                }
              }
             
              file.close();
            }
           
            files = new FMFile[]{ base_file };
           
            files_use_count = new int[]{ files_use_count[0] };
           
            base_file.moveFile( new_file );
 
            break;
          }
        }
       
        try{
          System.out.println( "CacheFileWithoutCacheMT: waiting for clones to die" );
         
          Thread.sleep(250);
         
        }catch( Throwable e ){
         
        }
      }
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
     
    }finally{
     
      synchronized( this ){

        moving = false;
      }
    }
  }
 
  public void
  renameFile(
    String    new_file )
 
    throws CacheFileManagerException
  {
    try{
      synchronized( this ){

        moving = true;
      }
     
      while( true ){
               
        synchronized( this ){
       
          boolean  surviving = false;

          for (int i=1;i<files_use_count.length;i++){
           
            if ( files_use_count[i] > 0 ){
             
              surviving = true;
             
              break;
            }
          }
       
          if ( !surviving ){
           
            for (int i=1;i<files_use_count.length;i++){
             
              FMFile file = files[i];
             
              if ( file.isClone()){
               
                // System.out.println( "Destroyed clone " + file.getName());
               
                synchronized( CacheFileWithoutCacheMT.class ){
                 
                  num_clones--;
                }
              }
             
              file.close();
            }
           
            files = new FMFile[]{ base_file };
           
            files_use_count = new int[]{ files_use_count[0] };
           
            base_file.renameFile( new_file );
 
            break;
          }
        }
       
        try{
          System.out.println( "CacheFileWithoutCacheMT: waiting for clones to die" );
         
          Thread.sleep(250);
         
        }catch( Throwable e ){
         
        }
      }
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
     
    }finally{
     
      synchronized( this ){

        moving = false;
      }
    }
  }
 
 
 
  public void
  setAccessMode(
    int    mode )
 
    throws CacheFileManagerException
  {
    try{
      synchronized( this ){
     
        for (int i=0;i<files.length;i++){
         
          files[i].setAccessMode( mode==CF_READ?FMFile.FM_READ:FMFile.FM_WRITE );
        }
      }
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
   
  }
 
  public int
  getAccessMode()
  {
    return( base_file.getAccessMode()==FMFile.FM_READ?CF_READ:CF_WRITE );
  }
 
  public void
  setStorageType(
    int    type )
 
    throws CacheFileManagerException
  {
    throw( new CacheFileManagerException( this, "Not Implemented" ))
  }
 
  public int
  getStorageType()
  {
    return( CacheFileManagerImpl.convertFileToCacheType( base_file.getStorageType()));
  }

  public long
  getLength()
 
    throws CacheFileManagerException
  {
    try{
           
      return( base_file.exists() ? base_file.getLength() : 0);
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
     
      return( 0 );
    }
  }
 
  public long
  compareLength(
    long  compare_to )
 
    throws CacheFileManagerException
  {
    return( getLength() - compare_to );
  }
 
  public void
  setLength(
    long    length )
 
    throws CacheFileManagerException
  {
    try{         
      base_file.setLength( length );
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
    }
  }
 
  public void
  setPieceComplete(
    int          piece_number,
    DirectByteBuffer  piece_data )
 
    throws CacheFileManagerException
  {
    try{
      base_file.setPieceComplete( piece_number, piece_data );
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);
    }
  }
 
  protected FMFile
  getFile()
 
    throws CacheFileManagerException
  {
    synchronized( this ){
     
      if ( moving ){
       
        files_use_count[0]++;
       
        return( files[0] );
      }
     
      int  min_index  = -1;
      int  min      = Integer.MAX_VALUE;
     
      for (int i=0;i<files_use_count.length;i++){
       
        int  count = files_use_count[i];
       
        if ( count < min ){
         
          min      = count;
          min_index  = i;
        }
      }
     
      if ( min == 0 || files_use_count.length == MAX_CLONES ){
       
        files_use_count[min_index]++;
       
        return( files[min_index] );
      }
     
        // all files already in use
     
      try{
        FMFile clone = base_file.createClone();
               
        //System.out.println( "Created clone " + clone.getName());
       
        int  old_num  = files.length;
        int  new_num = old_num + 1;
       
        synchronized( CacheFileWithoutCacheMT.class ){
         
          num_clones++;
         
          if ( num_clones % 100 == 0 ){
           
            //System.out.println( "File clones=" + num_clones );
          }
         
          if ( new_num == MAX_CLONES || new_num > max_clone_depth ){
           
            max_clone_depth = new_num;
           
            //System.out.println( "Clone depth of " + new_num + " for " + clone.getName());
          }
        }

        FMFile[]  new_files       = new FMFile[ new_num ];   
        int[]    new_files_use_count = new int[new_num];
       
        System.arraycopy(files, 0, new_files, 0, old_num );
        System.arraycopy(files_use_count, 0, new_files_use_count, 0, old_num );
       
        new_files[old_num]        = clone;
        new_files_use_count[old_num]   = 1;
       
        files      = new_files;
        files_use_count  = new_files_use_count;
       
        return( clone );
       
      }catch( FMFileManagerException e ){
       
        manager.rethrow( this, e );
       
        return( null );
      }
    }
  }
 
  protected void
  releaseFile(
    FMFile  file )
  {
    synchronized( this ){

      for (int i=0;i<files_use_count.length;i++){

        if ( files[i] == file ){
         
          int count = files_use_count[i];
         
          if ( count > 0 ){
           
            count--;
          }
         
          files_use_count[i] = count;
         
          break;
        }
      }
    }
  }
 
  public void
  read(
    DirectByteBuffer[]  buffers,
    long        position,
    short        policy )
 
    throws CacheFileManagerException
  {
    int  read_length  = 0;
   
    for (int i=0;i<buffers.length;i++){
     
      read_length += buffers[i].remaining(DirectByteBuffer.SS_CACHE);
    }
   
    FMFile file = null;
   
    try
      file  = getFile();
     
      file.read( buffers, position );
     
      manager.fileBytesRead( read_length );

    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
     
    }finally{
     
      releaseFile( file );
    }
  }
 
  public void
  read(
    DirectByteBuffer  buffer,
    long        position,
    short        policy )
 
    throws CacheFileManagerException
  {
    int  read_length  = buffer.remaining(DirectByteBuffer.SS_CACHE);

    FMFile file = null;
   
    try
      file  = getFile();
     
      file.read( buffer, position );
     
      manager.fileBytesRead( read_length );

    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
     
    }finally{
     
      releaseFile( file );
    }
  }
 
  public void
  write(
    DirectByteBuffer  buffer,
    long        position )
 
    throws CacheFileManagerException
  {
    int  write_length = buffer.remaining(DirectByteBuffer.SS_CACHE);
   
    try{     
      base_file.write( buffer, position );
     
      manager.fileBytesWritten( write_length );

    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
    }
  }
 
  public void
  write(
    DirectByteBuffer[]  buffers,
    long        position )
 
    throws CacheFileManagerException
  {
    int  write_length  = 0;
   
    for (int i=0;i<buffers.length;i++){
     
      write_length += buffers[i].remaining(DirectByteBuffer.SS_CACHE);
    }
   
    try{     
      base_file.write( buffers, position );
     
      manager.fileBytesWritten( write_length );

    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
    }
  }
 
  public void
  writeAndHandoverBuffer(
    DirectByteBuffer  buffer,
    long        position )
 
    throws CacheFileManagerException
  {
    int  write_length = buffer.remaining(DirectByteBuffer.SS_CACHE);
   
    boolean  write_ok  = false;
   
    try{     
      base_file.write( buffer, position );
     
      manager.fileBytesWritten( write_length );

      write_ok  = true;
     
    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
     
    }finally{
     
      if ( write_ok ){
       
        buffer.returnToPool();
      }
    }
  }
 
  public void
  writeAndHandoverBuffers(
    DirectByteBuffer[]  buffers,
    long        position )
 
    throws CacheFileManagerException
  {
    int  write_length  = 0;
   
    for (int i=0;i<buffers.length;i++){
     
      write_length += buffers[i].remaining(DirectByteBuffer.SS_CACHE);
    }
   
    boolean  write_ok  = false;
   
    try{     
      base_file.write( buffers, position );
     
      manager.fileBytesWritten( write_length );

      write_ok  = true;
     
    }catch( FMFileManagerException e ){
       
      manager.rethrow(this,e);
     
    }finally{
     
      if ( write_ok ){
       
        for (int i=0;i<buffers.length;i++){

          buffers[i].returnToPool();
        }
      }
    }
  }
 
  public void
  flushCache()
 
    throws CacheFileManagerException
  {
    try{
      base_file.flush();
   
    }catch( FMFileManagerException e ){
   
      manager.rethrow(this,e);
    }
  }
 
  public void
  clearCache()
 
    throws CacheFileManagerException
  {
  }
 
  public void
  close()
 
    throws CacheFileManagerException
  {
    try{   
      synchronized( this ){
       
        for (int i=0;i<files.length;i++){
         
          FMFile file = files[i];
         
          if ( file.isClone()){
         
            // System.out.println( "Destroyed clone " + file.getName());
           
            synchronized( CacheFileWithoutCacheMT.class ){
             
              num_clones--;
            }
          }
         
          file.close();
        }
      }     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);     
    }
  }
 
  public boolean
  isOpen()
  {
    return( base_file.isOpen());
  }
 
  public void
  delete()
 
    throws CacheFileManagerException
  {
    try{
     
      base_file.delete();
     
    }catch( FMFileManagerException e ){
     
      manager.rethrow(this,e);     
    }
  }
}
TOP

Related Classes of com.aelitis.azureus.core.diskmanager.cache.impl.CacheFileWithoutCacheMT

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.