mirror of
https://github.com/transmission/transmission
synced 2024-12-25 01:03:01 +00:00
fix ticket #451 (Files remain in use after removal)
This commit is contained in:
parent
a7671a3afc
commit
260033847f
4 changed files with 91 additions and 30 deletions
|
@ -97,6 +97,7 @@ struct tr_openfile
|
|||
{
|
||||
unsigned int isCheckedOut : 1;
|
||||
unsigned int isWritable : 1;
|
||||
unsigned int closeWhenDone : 1;
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
int fd;
|
||||
uint64_t date;
|
||||
|
@ -189,7 +190,7 @@ fileIsCheckedOut( const struct tr_openfile * o )
|
|||
}
|
||||
|
||||
int
|
||||
tr_fdFileOpen( const char * filename, int write )
|
||||
tr_fdFileCheckout( const char * filename, int write )
|
||||
{
|
||||
int i, winner;
|
||||
struct tr_openfile * o;
|
||||
|
@ -282,24 +283,55 @@ done:
|
|||
|
||||
dbgmsg( "checking out '%s' in slot %d", filename, winner );
|
||||
o->isCheckedOut = 1;
|
||||
o->closeWhenDone = 0;
|
||||
o->date = tr_date( );
|
||||
tr_lockUnlock( gFd->lock );
|
||||
return o->fd;
|
||||
}
|
||||
|
||||
void
|
||||
tr_fdFileRelease( int file )
|
||||
tr_fdFileReturn( int fd )
|
||||
{
|
||||
int i;
|
||||
tr_lockLock( gFd->lock );
|
||||
|
||||
for( i=0; i<TR_MAX_OPEN_FILES; ++i ) {
|
||||
for( i=0; i<TR_MAX_OPEN_FILES; ++i )
|
||||
{
|
||||
struct tr_openfile * o = &gFd->open[i];
|
||||
if( o->fd == file ) {
|
||||
dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
|
||||
/* fsync( o->fd ); */
|
||||
o->isCheckedOut = 0;
|
||||
break;
|
||||
if( o->fd != fd )
|
||||
continue;
|
||||
|
||||
dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
|
||||
o->isCheckedOut = 0;
|
||||
if( o->closeWhenDone )
|
||||
TrCloseFile( i );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
tr_condSignal( gFd->cond );
|
||||
tr_lockUnlock( gFd->lock );
|
||||
}
|
||||
|
||||
void
|
||||
tr_fdFileClose( const char * filename )
|
||||
{
|
||||
int i;
|
||||
tr_lockLock( gFd->lock );
|
||||
dbgmsg( "tr_fdFileClose closing '%s'", filename );
|
||||
|
||||
for( i=0; i<TR_MAX_OPEN_FILES; ++i )
|
||||
{
|
||||
struct tr_openfile * o = &gFd->open[i];
|
||||
if( !fileIsOpen(o) || strcmp(filename,o->filename) )
|
||||
continue;
|
||||
|
||||
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->open[i].filename, i );
|
||||
o->closeWhenDone = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,25 +33,43 @@ void tr_fdInit( void );
|
|||
|
||||
void tr_fdClose( void );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_fdFileOpen
|
||||
***********************************************************************
|
||||
* If it isn't open already, tries to open the file 'name' in the
|
||||
* directory 'folder'. If 'name' itself contains '/'s, required
|
||||
* subfolders are created. The file is open read-write if 'write' is 1
|
||||
* (created if necessary), read-only if 0.
|
||||
* Returns the file descriptor if successful, otherwise returns
|
||||
* one of the TR_ERROR_IO_*.
|
||||
**********************************************************************/
|
||||
int tr_fdFileOpen( const char * filename, int write );
|
||||
/**
|
||||
* Returns an fd to the specified filename.
|
||||
*
|
||||
* A small repository of open files is kept to avoid the overhead of continually
|
||||
* opening and closing the same files when writing piece data during download.
|
||||
* It's also used to ensure that only one client uses the file at a time.
|
||||
* Clients must check out a file to use it, then return it, like a library, when done.
|
||||
*
|
||||
* if write is nonzero and dirname(filename) doesn't exist, dirname is created.
|
||||
* if write is nonzero and filename doesn't exist, filename is created.
|
||||
* returns the fd if successful; otherwise, one of TR_ERROR_IO_*
|
||||
*
|
||||
* @see tr_fdFileReturn
|
||||
* @see tr_fdFileClose
|
||||
*/
|
||||
int tr_fdFileCheckout( const char * filename, int write );
|
||||
|
||||
/**
|
||||
* Returns an fd from tr_fdFileCheckout() so that other clients may borrow it.
|
||||
*
|
||||
* @see tr_fdFileCheckout
|
||||
* @see tr_fdFileClose
|
||||
*/
|
||||
void tr_fdFileReturn( int file );
|
||||
|
||||
/**
|
||||
* Closes a file that's being held by our file repository.
|
||||
*
|
||||
* If the file isn't checked out, it's closed immediately.
|
||||
* If the file is currently checked out, it will be closed upon its return.
|
||||
*
|
||||
* @see tr_fdFileCheckout
|
||||
* @see tr_fdFileReturn
|
||||
*/
|
||||
void tr_fdFileClose( const char * filename );
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* tr_fdFileRelease
|
||||
***********************************************************************
|
||||
* Indicates that the file whose descriptor is 'file' is unused at the
|
||||
* moment and can safely be closed.
|
||||
**********************************************************************/
|
||||
void tr_fdFileRelease( int file );
|
||||
|
||||
/***********************************************************************
|
||||
* Sockets
|
||||
|
|
|
@ -66,7 +66,7 @@ readOrWriteBytes( const tr_torrent * tor,
|
|||
return 0;
|
||||
else if ((ioMode==TR_IO_READ) && stat( path, &sb ) ) /* does file exist? */
|
||||
ret = tr_ioErrorFromErrno ();
|
||||
else if ((fd = tr_fdFileOpen ( path, ioMode==TR_IO_WRITE )) < 0)
|
||||
else if ((fd = tr_fdFileCheckout ( path, ioMode==TR_IO_WRITE )) < 0)
|
||||
ret = fd;
|
||||
else if( lseek( fd, (off_t)fileOffset, SEEK_SET ) == ((off_t)-1) )
|
||||
ret = TR_ERROR_IO_OTHER;
|
||||
|
@ -76,7 +76,7 @@ readOrWriteBytes( const tr_torrent * tor,
|
|||
ret = TR_OK;
|
||||
|
||||
if( fd >= 0 )
|
||||
tr_fdFileRelease( fd );
|
||||
tr_fdFileReturn( fd );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ ensureMinimumFileSize( const tr_torrent * tor,
|
|||
|
||||
tr_buildPath( path, sizeof(path), tor->destination, file->name, NULL );
|
||||
|
||||
fd = tr_fdFileOpen( path, TRUE );
|
||||
fd = tr_fdFileCheckout( path, TRUE );
|
||||
if( fd < 0 ) /* bad fd */
|
||||
ret = fd;
|
||||
else if (fstat (fd, &sb) ) /* how big is the file? */
|
||||
|
@ -138,7 +138,7 @@ ensureMinimumFileSize( const tr_torrent * tor,
|
|||
ret = tr_ioErrorFromErrno ();
|
||||
|
||||
if( fd >= 0 )
|
||||
tr_fdFileRelease( fd );
|
||||
tr_fdFileReturn( fd );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "completion.h"
|
||||
#include "crypto.h" /* for tr_sha1 */
|
||||
#include "fastresume.h"
|
||||
#include "fdlimit.h" /* tr_fdFileClose */
|
||||
#include "handshake.h"
|
||||
#include "inout.h"
|
||||
#include "metainfo.h"
|
||||
|
@ -1077,10 +1078,20 @@ tr_torrentRecheck( tr_torrent * tor )
|
|||
static void
|
||||
stopTorrent( void * vtor )
|
||||
{
|
||||
int i;
|
||||
|
||||
tr_torrent * tor = vtor;
|
||||
tr_ioRecheckRemove( tor );
|
||||
tr_peerMgrStopTorrent( tor->handle->peerMgr, tor->info.hash );
|
||||
tr_trackerStop( tor->tracker );
|
||||
|
||||
for( i=0; i<tor->info.fileCount; ++i )
|
||||
{
|
||||
char path[MAX_PATH_LENGTH];
|
||||
const tr_file * file = &tor->info.files[i];
|
||||
tr_buildPath( path, sizeof(path), tor->destination, file->name, NULL );
|
||||
tr_fdFileClose( path );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue