(trunk libT) more efficient closing of a torrent's open files
This commit is contained in:
parent
a8a4259f3a
commit
ef9896e223
|
@ -86,6 +86,7 @@ struct tr_openfile
|
|||
tr_bool isCheckedOut;
|
||||
tr_bool isWritable;
|
||||
tr_bool closeWhenDone;
|
||||
int torrentId;
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
int fd;
|
||||
uint64_t date;
|
||||
|
@ -380,7 +381,8 @@ fileIsCheckedOut( const struct tr_openfile * o )
|
|||
|
||||
/* returns an fd on success, or a -1 on failure and sets errno */
|
||||
int
|
||||
tr_fdFileCheckout( const char * folder,
|
||||
tr_fdFileCheckout( int torrentId,
|
||||
const char * folder,
|
||||
const char * torrentFile,
|
||||
tr_bool doWrite,
|
||||
tr_preallocation_mode preallocationMode,
|
||||
|
@ -390,6 +392,7 @@ tr_fdFileCheckout( const char * folder,
|
|||
struct tr_openfile * o;
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
|
||||
assert( torrentId > 0 );
|
||||
assert( folder && *folder );
|
||||
assert( torrentFile && *torrentFile );
|
||||
assert( doWrite == 0 || doWrite == 1 );
|
||||
|
@ -399,14 +402,15 @@ tr_fdFileCheckout( const char * folder,
|
|||
|
||||
tr_lockLock( gFd->lock );
|
||||
|
||||
/* Is it already open? */
|
||||
/* is it already open? */
|
||||
for( i=0; i<gFd->openFileLimit; ++i )
|
||||
{
|
||||
o = &gFd->openFiles[i];
|
||||
|
||||
if( !fileIsOpen( o ) )
|
||||
continue;
|
||||
|
||||
if( torrentId != o->torrentId )
|
||||
continue;
|
||||
if( strcmp( filename, o->filename ) )
|
||||
continue;
|
||||
|
||||
|
@ -422,8 +426,7 @@ tr_fdFileCheckout( const char * folder,
|
|||
|
||||
if( doWrite && !o->isWritable )
|
||||
{
|
||||
dbgmsg(
|
||||
"found it! it's open and available, but isn't writable. closing..." );
|
||||
dbgmsg( "found it! it's open and available, but isn't writable. closing..." );
|
||||
TrCloseFile( i );
|
||||
break;
|
||||
}
|
||||
|
@ -433,8 +436,7 @@ tr_fdFileCheckout( const char * folder,
|
|||
break;
|
||||
}
|
||||
|
||||
dbgmsg(
|
||||
"it's not already open. looking for an open slot or an old file." );
|
||||
dbgmsg( "it's not already open. looking for an open slot or an old file." );
|
||||
while( winner < 0 )
|
||||
{
|
||||
uint64_t date = tr_date( ) + 1;
|
||||
|
@ -495,6 +497,7 @@ tr_fdFileCheckout( const char * folder,
|
|||
}
|
||||
|
||||
dbgmsg( "checking out '%s' in slot %d", filename, winner );
|
||||
o->torrentId = torrentId;
|
||||
o->isCheckedOut = 1;
|
||||
o->closeWhenDone = 0;
|
||||
o->date = tr_date( );
|
||||
|
@ -530,7 +533,6 @@ void
|
|||
tr_fdFileClose( const char * filename )
|
||||
{
|
||||
int i;
|
||||
|
||||
tr_lockLock( gFd->lock );
|
||||
|
||||
for( i=0; i<gFd->openFileLimit; ++i )
|
||||
|
@ -541,23 +543,34 @@ tr_fdFileClose( const char * filename )
|
|||
|
||||
dbgmsg( "tr_fdFileClose closing '%s'", filename );
|
||||
|
||||
if( !o->isCheckedOut )
|
||||
{
|
||||
dbgmsg( "not checked out, so closing it now... '%s'", filename );
|
||||
assert( !o->isCheckedOut && "this is a test assertion... I *think* this is always true now" );
|
||||
|
||||
TrCloseFile( i );
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgmsg(
|
||||
"flagging file '%s', slot #%d to be closed when checked in",
|
||||
gFd->openFiles[i].filename, i );
|
||||
o->closeWhenDone = 1;
|
||||
}
|
||||
}
|
||||
|
||||
tr_lockUnlock( gFd->lock );
|
||||
}
|
||||
|
||||
void
|
||||
tr_fdTorrentClose( int torrentId )
|
||||
{
|
||||
int i;
|
||||
tr_lockLock( gFd->lock );
|
||||
|
||||
for( i=0; i<gFd->openFileLimit; ++i )
|
||||
{
|
||||
struct tr_openfile * o = &gFd->openFiles[i];
|
||||
|
||||
assert( !o->isCheckedOut && "this is a test assertion... I *think* this is always true now" );
|
||||
|
||||
if( fileIsOpen( o ) && o->torrentId == torrentId )
|
||||
TrCloseFile( i );
|
||||
}
|
||||
|
||||
tr_lockUnlock( gFd->lock );
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
****
|
||||
**** Sockets
|
||||
|
@ -736,4 +749,3 @@ tr_fdGetPeerLimit( void )
|
|||
{
|
||||
return gFd ? gFd->socketLimit : -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ int64_t tr_lseek( int fd, int64_t offset, int whence );
|
|||
* @see tr_fdFileReturn
|
||||
* @see tr_fdFileClose
|
||||
*/
|
||||
int tr_fdFileCheckout( const char * folder,
|
||||
int tr_fdFileCheckout( int torrentId,
|
||||
const char * folder,
|
||||
const char * torrentFile,
|
||||
tr_bool doWrite,
|
||||
tr_preallocation_mode preallocationMode,
|
||||
|
@ -93,6 +94,12 @@ void tr_fdFileReturn( int file );
|
|||
void tr_fdFileClose( const char * filename );
|
||||
|
||||
|
||||
/**
|
||||
* Closes all the files associated with a given torrent id
|
||||
*/
|
||||
void tr_fdTorrentClose( int torrentId );
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Sockets
|
||||
**********************************************************************/
|
||||
|
|
|
@ -101,7 +101,7 @@ readOrWriteBytes( const tr_torrent * tor,
|
|||
|
||||
if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */
|
||||
err = errno;
|
||||
else if( ( fd = tr_fdFileCheckout ( tor->downloadDir, file->name, ioMode == TR_IO_WRITE, preallocationMode, file->length ) ) < 0 )
|
||||
else if( ( fd = tr_fdFileCheckout ( tor->uniqueId, tor->downloadDir, file->name, ioMode == TR_IO_WRITE, preallocationMode, file->length ) ) < 0 )
|
||||
err = errno;
|
||||
else if( tr_lseek( fd, (int64_t)fileOffset, SEEK_SET ) == -1 )
|
||||
err = errno;
|
||||
|
|
|
@ -1329,30 +1329,6 @@ tr_torrentVerify( tr_torrent * tor )
|
|||
tr_globalUnlock( tor->session );
|
||||
}
|
||||
|
||||
static void
|
||||
tr_torrentCloseLocalFiles( const tr_torrent * tor )
|
||||
{
|
||||
tr_file_index_t i;
|
||||
struct evbuffer * buf = evbuffer_new( );
|
||||
|
||||
assert( tr_isTorrent( tor ) );
|
||||
|
||||
/* FIXME(libevent2) we're just using the evbuffer to build a key here anyway.
|
||||
so we do (tor->info.fileCount * fd.openFileLimit) strcmps for these keys. :/
|
||||
it would be more efficient to remove this code altogether and
|
||||
add "int torrentId;" to "struct tr_openfile", and a new function
|
||||
tr_fdCloseTorrentFiles( tr_session*, int torrentId ) */
|
||||
for( i=0; i<tor->info.fileCount; ++i )
|
||||
{
|
||||
const tr_file * file = &tor->info.files[i];
|
||||
evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) );
|
||||
evbuffer_add_printf( buf, "%s%s%s", tor->downloadDir, TR_PATH_DELIMITER_STR, file->name );
|
||||
tr_fdFileClose( (const char*) EVBUFFER_DATA( buf ) );
|
||||
}
|
||||
|
||||
evbuffer_free( buf );
|
||||
}
|
||||
|
||||
static void
|
||||
stopTorrent( void * vtor )
|
||||
{
|
||||
|
@ -1364,7 +1340,7 @@ stopTorrent( void * vtor )
|
|||
tr_peerMgrStopTorrent( tor );
|
||||
tr_trackerStop( tor->tracker );
|
||||
|
||||
tr_torrentCloseLocalFiles( tor );
|
||||
tr_fdTorrentClose( tor->uniqueId );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1529,7 +1505,7 @@ tr_torrentRecheckCompleteness( tr_torrent * tor )
|
|||
|
||||
tor->completeness = completeness;
|
||||
tor->needsSeedRatioCheck = TRUE;
|
||||
tr_torrentCloseLocalFiles( tor );
|
||||
tr_fdTorrentClose( tor->uniqueId );
|
||||
fireCompletenessChange( tor, completeness );
|
||||
|
||||
if( recentChange && ( completeness == TR_SEED ) )
|
||||
|
@ -2218,7 +2194,7 @@ tr_torrentDeleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
|
|||
fileFunc = remove;
|
||||
|
||||
/* close all the files because we're about to delete them */
|
||||
tr_torrentCloseLocalFiles( tor );
|
||||
tr_fdTorrentClose( tor->uniqueId );
|
||||
|
||||
if( tor->info.fileCount > 1 )
|
||||
deleteLocalData( tor, fileFunc );
|
||||
|
|
Loading…
Reference in New Issue