(trunk libT) more efficient closing of a torrent's open files

This commit is contained in:
Charles Kerr 2009-06-21 07:36:51 +00:00
parent a8a4259f3a
commit ef9896e223
4 changed files with 48 additions and 53 deletions

View File

@ -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? */
for( i = 0; i < gFd->openFileLimit; ++i )
/* 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,14 +436,13 @@ 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;
/* look for the file that's been open longest */
for( i = 0; i < gFd->openFileLimit; ++i )
for( i=0; i<gFd->openFileLimit; ++i )
{
o = &gFd->openFiles[i];
@ -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,10 +533,9 @@ void
tr_fdFileClose( const char * filename )
{
int i;
tr_lockLock( gFd->lock );
for( i = 0; i < gFd->openFileLimit; ++i )
for( i=0; i<gFd->openFileLimit; ++i )
{
struct tr_openfile * o = &gFd->openFiles[i];
if( !fileIsOpen( o ) || strcmp( filename, o->filename ) )
@ -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 );
TrCloseFile( i );
}
else
{
dbgmsg(
"flagging file '%s', slot #%d to be closed when checked in",
gFd->openFiles[i].filename, i );
o->closeWhenDone = 1;
}
assert( !o->isCheckedOut && "this is a test assertion... I *think* this is always true now" );
TrCloseFile( i );
}
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;
}

View File

@ -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
**********************************************************************/

View File

@ -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;

View File

@ -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 );