📄 cachefilewithcache.java
字号:
throws CacheFileManagerException
{
if ( manager.isCacheEnabled()){
if (TRACE)
Logger.log(new LogEvent(torrent, LOGID, "flushCache: " + getName()
+ ", rel = " + release_entries + ", min = " + minumum_to_release));
flushCache( file_start_position, -1, release_entries, minumum_to_release, 0, -1 );
}
}
// this is the flush method used by the public methods directly (as opposed to those use when reading, writing etc)
// and it is the place that pending exceptions are checked for. We don't want to check for this in the internal
// logic for flushing as we need to be able to flush from files that have a pending error to clear the cache
// state
protected void
flushCachePublic(
boolean release_entries,
long minumum_to_release )
throws CacheFileManagerException
{
checkPendingException();
flushCache(0, release_entries, minumum_to_release );
}
protected void
flushOldDirtyData(
long oldest_dirty_time,
long min_chunk_size )
throws CacheFileManagerException
{
if ( manager.isCacheEnabled()){
if (TRACE)
Logger.log(new LogEvent(torrent, LOGID, "flushOldDirtyData: "
+ getName()));
flushCache( 0, -1, false, -1, oldest_dirty_time, min_chunk_size );
}
}
protected void
flushOldDirtyData(
long oldest_dirty_time )
throws CacheFileManagerException
{
flushOldDirtyData( oldest_dirty_time, -1 );
}
protected long
getBytesInCache(
long offset,
long length )
{
try{
this_mon.enter();
long result = 0;
Iterator it = cache.iterator();
long start_pos = offset;
long end_pos = offset + length;
while( it.hasNext()){
CacheEntry entry = (CacheEntry)it.next();
long this_start = entry.getFilePosition();
int entry_length = entry.getLength();
long this_end = this_start + entry_length;
if ( this_end <= start_pos ){
continue;
}
if ( end_pos <= this_start ){
break;
}
long bit_start = start_pos<this_start?this_start:start_pos;
long bit_end = end_pos>=this_end?this_end:end_pos;
result += bit_end - bit_start;
}
return( result );
}finally{
this_mon.exit();
}
}
// support methods
protected void
checkPendingException()
throws CacheFileManagerException
{
if ( pending_exception != null ){
throw( pending_exception );
}
}
protected void
setPendingException(
CacheFileManagerException e )
{
pending_exception = e;
}
protected String
getName()
{
return( file.getName());
}
protected FMFile
getFMFile()
{
return( file );
}
// public methods
public boolean
exists()
{
return( file.exists());
}
public void
moveFile(
File new_file )
throws CacheFileManagerException
{
try{
flushCachePublic( true, -1 );
file.moveFile( new_file );
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}
}
public void
setAccessMode(
int mode )
throws CacheFileManagerException
{
try{
this_mon.enter();
if ( access_mode != mode ){
flushCachePublic( false, -1 );
}
file.setAccessMode( mode==CF_READ?FMFile.FM_READ:FMFile.FM_WRITE );
access_mode = mode;
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}finally{
this_mon.exit();
}
}
public int
getAccessMode()
{
return( access_mode );
}
public void
setStorageType(
int type )
throws CacheFileManagerException
{
try{
this_mon.enter();
if ( getStorageType() != type ){
flushCachePublic( false, -1 );
}
file.setStorageType( type==CT_COMPACT?FMFile.FT_COMPACT:FMFile.FT_LINEAR );
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}finally{
this_mon.exit();
}
}
public int
getStorageType()
{
return( file.getStorageType()==FMFile.FT_COMPACT?CT_COMPACT:CT_LINEAR );
}
public void
ensureOpen(
String reason )
throws CacheFileManagerException
{
try{
// no cache flush required here
file.ensureOpen( reason );
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}
}
public long
getLength()
throws CacheFileManagerException
{
// not sure of the difference between "size" and "length" here. Old code
// used to use "size" so I'm going to carry on for the moment in case
// there is some weirdness here
try{
// bug found here with "incremental creation" failing with lots of hash
// fails. Caused by the reported length not taking into account the cache
// entries that have yet to be flushed.
if ( manager.isCacheEnabled()){
try{
this_mon.enter();
long physical_size = file.getLength();
Iterator it = cache.iterator();
// last entry is furthest down the file
while( it.hasNext()){
CacheEntry entry = (CacheEntry)it.next();
if ( !it.hasNext()){
long entry_file_position = entry.getFilePosition();
int entry_length = entry.getLength();
long logical_size = entry_file_position + entry_length;
if ( logical_size > physical_size ){
physical_size = logical_size;
}
}
}
return( physical_size );
}finally{
this_mon.exit();
}
}else{
return( file.getLength());
}
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
return( 0 );
}
}
public long
compareLength(
long compare_to )
throws CacheFileManagerException
{
try{
// we can optimise this if the file's already big enough as cache entries can
// only make it bigger
long physical_length = file.getLength();
long res = physical_length - compare_to;
if ( res >= 0 ){
return( res );
}
return( getLength() - compare_to );
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
return( 0 );
}
}
public void
setLength(
long length )
throws CacheFileManagerException
{
try{
// flush in case length change will invalidate cache data (unlikely but possible)
flushCachePublic( true, -1 );
file.setLength( length );
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}
}
public void
read(
DirectByteBuffer[] buffers,
long position,
short policy )
throws CacheFileManagerException
{
for (int i=0;i<buffers.length;i++){
DirectByteBuffer buffer = buffers[i];
int len = buffer.remaining( DirectByteBuffer.SS_CACHE );
try{
read( buffer, position, policy );
position += len;
}catch( CacheFileManagerException e ){
throw( new CacheFileManagerException( this, e.getMessage(), e, i ));
}
}
}
public void
read(
DirectByteBuffer buffer,
long position,
short policy )
throws CacheFileManagerException
{
boolean read_cache = ( policy & CP_READ_CACHE ) != 0;
boolean flush = ( policy & CP_FLUSH ) != 0;
if ( flush ){
int file_buffer_position = buffer.position(DirectByteBuffer.SS_CACHE);
int file_buffer_limit = buffer.limit(DirectByteBuffer.SS_CACHE);
int read_length = file_buffer_limit - file_buffer_position;
flushCache( position, read_length, false, -1, 0, -1 );
}
readCache( buffer, position, false, !read_cache );
}
public void
write(
DirectByteBuffer buffer,
long position )
throws CacheFileManagerException
{
writeCache( buffer, position, false );
}
public void
write(
DirectByteBuffer[] buffers,
long position )
throws CacheFileManagerException
{
for (int i=0;i<buffers.length;i++){
DirectByteBuffer buffer = buffers[i];
int len = buffer.remaining( DirectByteBuffer.SS_CACHE );
try{
write( buffer, position );
position += len;
}catch( CacheFileManagerException e ){
throw( new CacheFileManagerException( this, e.getMessage(), e, i ));
}
}
}
public void
writeAndHandoverBuffer(
DirectByteBuffer buffer,
long position )
throws CacheFileManagerException
{
writeCache( buffer, position, true );
}
public void
writeAndHandoverBuffers(
DirectByteBuffer[] buffers,
long position )
throws CacheFileManagerException
{
for (int i=0;i<buffers.length;i++){
DirectByteBuffer buffer = buffers[i];
int len = buffer.remaining( DirectByteBuffer.SS_CACHE );
try{
writeAndHandoverBuffer( buffer, position );
position += len;
}catch( CacheFileManagerException e ){
throw( new CacheFileManagerException( this, e.getMessage(), e, i ));
}
}
}
public void
flushCache()
throws CacheFileManagerException
{
try{
flushCachePublic( false, -1 );
file.flush();
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}
}
public void
clearCache()
throws CacheFileManagerException
{
flushCachePublic(true, -1);
}
public void
close()
throws CacheFileManagerException
{
// we've got to always close the file here, even if the flush fails
boolean fm_file_closed = false;
try{
flushCachePublic( true, -1 );
file.close();
fm_file_closed = true;
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}finally{
if ( !fm_file_closed ){
try{
file.close();
}catch( Throwable e ){
// we're already on our way out via exception, no need to
// throw a new one
}
}
manager.closeFile( this );
}
}
public void
delete()
throws CacheFileManagerException
{
try{
file.delete();
}catch( FMFileManagerException e ){
manager.rethrow(this,e);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -