Package com.aelitis.azureus.core.download

Source Code of com.aelitis.azureus.core.download.DiskManagerFileInfoDelegate$channel

/*
* Created on Feb 11, 2009
* Created by Paul Gardner
*
* Copyright 2009 Vuze, Inc.  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; version 2 of the License only.
*
* 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.
*/


package com.aelitis.azureus.core.download;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;

import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SHA1Simple;
import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import org.gudy.azureus2.plugins.disk.DiskManagerListener;
import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.download.DownloadException;
import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;

import com.aelitis.azureus.core.util.CopyOnWriteList;
import com.aelitis.azureus.core.util.QTFastStartRAF;

public class
DiskManagerFileInfoDelegate
  implements DiskManagerFileInfo
{
  private DiskManagerFileInfo    delegate;
  private byte[]          hash;
 
  public
  DiskManagerFileInfoDelegate(
    DiskManagerFileInfo    _delegate )
 
    throws DownloadException
  {
    delegate    = _delegate;
   
    if ( delegate.getDownload() == null ){
     
      throw( new DownloadException( "Not supported" ));
    }
   
    byte[]  delegate_hash = delegate.getDownloadHash();
     
    hash = delegate_hash.clone();
     
    hash[0] ^= 0x01;
  }
 
  public void
  setPriority(
    boolean b )
  {
    delegate.setPriority( b );
  }
 
  public int
  getNumericPriorty()
  {
    return( delegate.getNumericPriorty());
  }
 
  public void
  setNumericPriority(
    int priority)
  {
    delegate.setNumericPriority(priority);
  }
 
  public void
  setSkipped(
    boolean b )
  {
    delegate.setSkipped( b );
  }
 
  public void
  setDeleted(boolean b)
  {
    delegate.setDeleted(b);
  }
 
  public void
  setLink(
    File  link_destination )
  { 
    delegate.setLink( link_destination );
  }
 
  public File
  getLink()
  {
    return( delegate.getLink());
  }
      
  public int
  getAccessMode()
  {
    return( delegate.getAccessMode());
  }
 
  public long
  getDownloaded()
  {
    return( delegate.getDownloaded());
  }
 
  public long
  getLength()
  {
    return( delegate.getLength());
  }
 
  public File
  getFile()
  {
    return( delegate.getFile());
  }
 
  public File
  getFile(
    boolean follow_link )
  {
    return( delegate.getFile(follow_link));
  }
 
  public int
  getIndex()
  {
    return( delegate.getIndex());
  }
 
  public int
  getFirstPieceNumber()
  {
    return( delegate.getFirstPieceNumber());
  }
 
  public long
  getPieceSize()
  {
    return( delegate.getPieceSize());
  }
 
  public int
  getNumPieces()
  {
    return( delegate.getNumPieces());
  }
   
  public boolean
  isPriority()
  {
    return( delegate.isPriority());
  }
 
  public boolean
  isSkipped()
  {
    return( delegate.isSkipped());
  }
 
  public boolean
  isDeleted()
  {
    return( delegate.isDeleted());
  }
 
  public byte[]
  getDownloadHash()
    {
    return( hash );
    }
 
  public Download
  getDownload()
 
      throws DownloadException
    {
    throw( new DownloadException( "Not supported" ));
    }
 
  public DiskManagerChannel
  createChannel()
 
    throws DownloadException
  {
    return( new channel());
  }
 
  private class
  channel
    implements DiskManagerChannel
  {
    private DiskManagerChannel  delegate_channel;
   
    private volatile boolean  channel_destroyed;
    private volatile long    channel_position;
   
    private
    channel()
   
      throws DownloadException
    {
      delegate_channel = delegate.createChannel();
    }
   
    public DiskManagerRequest
    createRequest()
    {
      return( new request());
    }
   
    public DiskManagerFileInfo
    getFile()
    {
      return( DiskManagerFileInfoDelegate.this );
    }
   
    public long
    getPosition()
    {
      return( delegate_channel.getPosition());
    }
   
    public boolean
    isDestroyed()
    {
      return( delegate_channel.isDestroyed());
    }
   
    public void
    destroy()
    {
      delegate_channel.destroy();
    }
   
    protected class
    request
      implements DiskManagerRequest
    {
      private DiskManagerRequest  delegate_request;
      private volatile boolean  using_delegate;
     
      private long    offset;
      private long    length;
     
      private volatile long  position;
     
      private String    user_agent;

      private int      max_read_chunk = 128*1024;;

      private volatile boolean  cancelled;
     
     
      private CopyOnWriteList<DiskManagerListener>    listeners = new CopyOnWriteList<DiskManagerListener>();
     
      private
      request()
      {
        delegate_request = delegate_channel.createRequest();
      }
     
      public void
      setType(
        int      type )
      {
        if ( type != DiskManagerRequest.REQUEST_READ ){
         
          throw( new RuntimeException( "Not supported" ));
        }
       
        delegate_request.setType( type );
      }
     
      public void
      setOffset(
        long    _offset )
      {
        offset    = _offset;
       
        delegate_request.setOffset( offset );
      }
     
      public void
      setLength(
        long    _length )
      {
        if ( _length < 0 ){
         
          throw( new RuntimeException( "Illegal argument" ));
        }
       
        length    = _length;
       
        delegate_request.setLength( length );
      }
       
      public void
      setMaximumReadChunkSize(
        int   size )
      {
        max_read_chunk = size;
       
        delegate_request.setMaximumReadChunkSize( size );
      }
     
      public void
      setUserAgent(
        String    agent )
      { 
        user_agent  = agent;
       
        delegate_request.setUserAgent( agent );
      }

      public long
      getAvailableBytes()
      {
        if ( using_delegate ){
         
          return( delegate_request.getAvailableBytes());
        }
       
        return( getRemaining());
      }
           
      public long
      getRemaining()
      {
        if ( using_delegate ){
         
          return( delegate_request.getRemaining());
        }
       
        return( offset + length - position );
      }
     
      public void
      run()
      {
        boolean  for_stream = user_agent != null;
       
        if ( for_stream ){
         
          File file = delegate.getFile();
         
          String name = file.getName();
         
          int  dot_pos = name.lastIndexOf('.');
         
          String ext = dot_pos<0?"":name.substring(dot_pos+1);

          for_stream = QTFastStartRAF.isSupportedExtension( ext );
        }
       
        if ( for_stream ){
         
          QTFastStartRAF  raf = null;
         
          try{
            raf = new QTFastStartRAF( getAccessor( max_read_chunk, user_agent ), true );
           
            raf.seek( offset );
       
            byte[] buffer = new byte[max_read_chunk];
           
            long  rem    = length;
            long  pos   = offset;
           
            while( rem > 0 ){
             
              if ( cancelled ){
               
                throw( new Exception( "Cancelled" ));
               
              }else if ( channel_destroyed ){
               
                throw( new Exception( "Destroyed" ));
              }
             
              int  chunk = (int)Math.min( rem, max_read_chunk );
             
              int  len = raf.read( buffer, 0, chunk );
                         
              sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
             
              rem -= len;
              pos  += len;
             
              position += len;
            }
          }catch( Throwable e ){
           
            sendEvent( new event( e ));
           
          }finally{
           
            if ( raf != null ){
             
              try{
                raf.close();
               
              }catch( Throwable e ){
               
                Debug.out( e );
              }
            }
          }
        }else{
         
          using_delegate  = true;
         
          delegate_request.addListener(
            new DiskManagerListener()
            {
              public void
              eventOccurred(
                DiskManagerEvent  event )
              {
                sendEvent( event );
              }
            });
           
          delegate_request.run();
        }
      }
     
      public void
      cancel()
      {
        cancelled = true;
       
        delegate_request.cancel();
      }
           
      protected void
      sendEvent(
        DiskManagerEvent    ev )
      {         
        for ( DiskManagerListener l: listeners ){
         
          l.eventOccurred( ev );
        }
      }
     
      public void
      addListener(
        DiskManagerListener  listener )
      {
        listeners.add( listener );
      }
     
      public void
      removeListener(
        DiskManagerListener  listener )
      {
        listeners.remove( listener );
      }
   
      protected class
      event
        implements DiskManagerEvent
      {
        private int          event_type;
        private Throwable      error;
        private PooledByteBuffer  buffer;
        private long        event_offset;
        private int          event_length;
       
        protected
        event(
          Throwable    _error )
        {
          event_type  = DiskManagerEvent.EVENT_TYPE_FAILED;
          error    = _error;
        }
               
        protected
        event(
          PooledByteBuffer  _buffer,
          long        _offset,
          int          _length )
        {
          event_type    = DiskManagerEvent.EVENT_TYPE_SUCCESS;
          buffer      = _buffer;
          event_offset  = _offset;
          event_length  = _length;
         
          channel_position = _offset + _length - 1;
        }
       
        public int
        getType()
        {
          return( event_type );
        }
       
        public DiskManagerRequest
        getRequest()
        {
          return( request.this );
        }
       
        public long
        getOffset()
        {
          return( event_offset );
        }
       
        public int
        getLength()
        {
          return( event_length );
        }
       
        public PooledByteBuffer
        getBuffer()
        {
          return( buffer );
        }
       
        public Throwable
        getFailure()
        {
          return( error );
        }
      }
    }
   
    private QTFastStartRAF.FileAccessor
    getAccessor(
      final int      max_req_size,
      final String    user_agent )
    {
      return(
        new QTFastStartRAF.FileAccessor()
        {
          private long        seek_position;
          private DiskManagerRequest   current_request;
          private volatile boolean  closed;
         
          public String
          getName()
          {
            try{
              return( delegate.getDownload().getName() + "/" + delegate.getFile().getName());
             
            }catch( Throwable e ){
             
              Debug.out( e );
             
              return( delegate.getFile().getAbsolutePath());
            }
          }
         
          public long
          getFilePointer()
         
            throws IOException
          {
            return( seek_position );
          }
         
          public void
          seek(
            long    pos )
         
            throws IOException
          {
            seek_position = pos;
          }

          public void
          skipBytes(
            int    num )
         
            throws IOException
          {
            seek_position += num;
          }
         
          public long
          length()
         
            throws IOException
          {
            return( getLength());
          }
         
          public int
          read(
            final byte[]  buffer,
            final int    pos,
            final int    len )
         
            throws IOException
          {
            synchronized( this ){
             
              if ( closed ){
               
                throw( new IOException( "closed" ));
              }
             
              current_request = delegate_channel.createRequest();
            }
           
            current_request.setType( DiskManagerRequest.REQUEST_READ );
            current_request.setOffset( seek_position );
            current_request.setLength( len );
           
            current_request.setMaximumReadChunkSize( max_req_size );
           
            if ( user_agent != null ){
           
              current_request.setUserAgent( user_agent );
            }
           
            final AESemaphore  sem = new AESemaphore( "waiter" );
            final Throwable[]  error = {null};
           
            current_request.addListener(
              new DiskManagerListener()
              {
                private int write_pos   = pos;
                private int  rem      = len;
               
                public void
                eventOccurred(
                  DiskManagerEvent  event )
                {
                  int  type = event.getType();
                 
                  if ( type == DiskManagerEvent.EVENT_TYPE_SUCCESS ){
                   
                    PooledByteBuffer p_buffer = event.getBuffer();
                   
                    try{
                      ByteBuffer  bb = p_buffer.toByteBuffer();
                                         
                      bb.position( 0 );
                     
                      int  read = bb.remaining();

                      bb.get( buffer, write_pos, read );
                     
                      write_pos   += read;
                      rem      -= read;
                     
                      if ( rem == 0 ){
                       
                        sem.release();
                      }
                    }finally{
                     
                      p_buffer.returnToPool();
                    }
                  }else if ( type == DiskManagerEvent.EVENT_TYPE_FAILED ){
                 
                    error[0] = event.getFailure();
                   
                    sem.release();
                  }
                }
              });
           
            current_request.run();
           
            while( true ){
             
              if ( sem.reserve( 1000 )){
               
                if ( error[0] != null ){
                 
                  throw( new IOException( Debug.getNestedExceptionMessage( error[0] )));
                }
               
                seek_position += len;
               
                return( len );
               
              }else{
               
                if ( closed ){
                 
                  throw( new IOException( "Closed" ));
                }
              }
            }
          }
         
          public int
          readInt()
         
            throws IOException
          {
            byte[]  readBuffer = new byte[4];
           
            readFully( readBuffer );
           
            return ((readBuffer[0] << 24) +
                ((readBuffer[1]&0xff) << 16) +
                ((readBuffer[2]&0xff) << 8) +
                ((readBuffer[3]&0xff) << 0));
          }
         
          public long
          readLong()
         
            throws IOException
          {
            byte[]  readBuffer = new byte[8];
           
            readFully( readBuffer );
           
            return (  ((long)readBuffer[0] << 56) +
                          ((long)(readBuffer[1]&0xff) << 48) +
                          ((long)(readBuffer[2]&0xff) << 40) +
                          ((long)(readBuffer[3]&0xff) << 32) +
                          ((long)(readBuffer[4]&0xff) << 24) +
                          ((readBuffer[5]&0xff) << 16) +
                          ((readBuffer[6]&0xff) <<  8) +
                          ((readBuffer[7]&0xff) <<  0));         
          }
         
          public void
          readFully(
            byte[]  buffer )
         
            throws IOException
          {
            read( buffer, 0, buffer.length );
          }
             
          public void
          close()
         
            throws IOException
          {
            synchronized( this ){
           
              closed  = true;
             
              if ( current_request != null ){
               
                current_request.cancel();
              }
            }
          }
        });
    }
  }
}
TOP

Related Classes of com.aelitis.azureus.core.download.DiskManagerFileInfoDelegate$channel

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.