Пример #1
0
void
tr_fdFileClose( const char * filename )
{
    int i;

    tr_lockLock( gFd->lock );

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
    {
        struct tr_openfile * o = &gFd->open[i];
        if( !fileIsOpen( o ) || strcmp( filename, o->filename ) )
            continue;

        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->open[i].filename, i );
            o->closeWhenDone = 1;
        }
    }

    tr_lockUnlock( gFd->lock );
}
Пример #2
0
void
tr_fdSetFileLimit( tr_session * session, int limit )
{
    struct tr_fdInfo * gFd;

    ensureSessionFdInfoExists( session );

    gFd = session->fdInfo;

    if( gFd->openFileLimit != limit )
    {
        int i;
        struct tr_openfile * o;
        const struct tr_openfile * end;

        /* close any files we've got open  */
        for( o=gFd->openFiles, end=o+gFd->openFileLimit; o!=end; ++o )
            if( fileIsOpen( o ) )
                TrCloseFile( o );

        /* rebuild the openFiles array */
        tr_free( gFd->openFiles );
        gFd->openFiles = tr_new0( struct tr_openfile, limit );
        gFd->openFileLimit = limit;
        for( i=0; i<gFd->openFileLimit; ++i )
            gFd->openFiles[i].fd = -1;
    }
Пример #3
0
void
tr_fdFileClose( tr_session        * session,
                const tr_torrent  * tor,
                tr_file_index_t     fileNum )
{
    struct tr_openfile * o;
    struct tr_fdInfo * gFd;
    const struct tr_openfile * end;
    const int torrentId = tr_torrentId( tor );

    assert( tr_isSession( session ) );
    assert( session->fdInfo != NULL );
    assert( tr_isTorrent( tor ) );
    assert( fileNum < tor->info.fileCount );

    gFd = session->fdInfo;

    for( o=gFd->openFiles, end=o+gFd->openFileLimit; o!=end; ++o )
    {
        if( torrentId != o->torrentId )
            continue;
        if( fileNum != o->fileNum )
            continue;
        if( !fileIsOpen( o ) )
            continue;

        dbgmsg( "tr_fdFileClose closing \"%s\"", o->filename );
        TrCloseFile( o );
    }
}
Пример #4
0
void
tr_fdClose( void )
{
    int i = 0;

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
        if( fileIsOpen( &gFd->open[i] ) )
            TrCloseFile( i );

    tr_lockFree( gFd->lock );

    tr_free( gFd );
    gFd = NULL;
}
Пример #5
0
void
tr_fdTorrentClose( tr_session * session, int torrentId )
{
    assert( tr_isSession( session ) );

    if( session->fdInfo != NULL )
    {
        struct tr_openfile * o;
        const struct tr_openfile * end;
        struct tr_fdInfo * gFd = session->fdInfo;

        for( o=gFd->openFiles, end=o+gFd->openFileLimit; o!=end; ++o )
            if( fileIsOpen( o ) && ( o->torrentId == torrentId ) )
                TrCloseFile( o );
    }
}
Пример #6
0
void
tr_fdClose( tr_session * session )
{
    struct tr_fdInfo * gFd;
    struct tr_openfile * o;
    const struct tr_openfile * end;

    assert( tr_isSession( session ) );
    assert( session->fdInfo != NULL );

    gFd = session->fdInfo;

    for( o=gFd->openFiles, end=o+gFd->openFileLimit; o!=end; ++o )
        if( fileIsOpen( o ) )
            TrCloseFile( o );

    tr_free( gFd->openFiles );
    tr_free( gFd );
    session->fdInfo = NULL;
}
Пример #7
0
void
tr_fdFileReturn( int fd )
{
    int i;

    tr_lockLock( gFd->lock );

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
    {
        struct tr_openfile * o = &gFd->open[i];
        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_lockUnlock( gFd->lock );
}
Пример #8
0
/* returns an fd on success, or a -1 on failure and sets errno */
int
tr_fdFileCheckout( const char * folder,
                   const char * torrentFile,
                   int          doWrite,
                   int          doPreallocate,
                   uint64_t     desiredFileSize )
{
    int                  i, winner = -1;
    struct tr_openfile * o;
    char               * filename;

    assert( folder && *folder );
    assert( torrentFile && *torrentFile );
    assert( doWrite == 0 || doWrite == 1 );

    filename = tr_buildPath( folder, torrentFile, NULL );
    dbgmsg( "looking for file '%s', writable %c", filename,
            doWrite ? 'y' : 'n' );

    tr_lockLock( gFd->lock );

    /* Is it already open? */
    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
    {
        o = &gFd->open[i];

        if( !fileIsOpen( o ) )
            continue;

        if( strcmp( filename, o->filename ) )
            continue;

        if( fileIsCheckedOut( o ) )
        {
            dbgmsg( "found it!  it's open, but checked out.  waiting..." );
            tr_lockUnlock( gFd->lock );
            tr_wait( 200 );
            tr_lockLock( gFd->lock );
            i = -1; /* reloop */
            continue;
        }

        if( doWrite && !o->isWritable )
        {
            dbgmsg(
                "found it!  it's open and available, but isn't writable. closing..." );
            TrCloseFile( i );
            break;
        }

        dbgmsg( "found it!  it's ready for use!" );
        winner = i;
        break;
    }

    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 < TR_MAX_OPEN_FILES; ++i )
        {
            o = &gFd->open[i];

            if( !fileIsOpen( o ) )
            {
                winner = i;
                dbgmsg( "found an empty slot in %d", winner );
                break;
            }

            if( date > o->date )
            {
                date = o->date;
                winner = i;
            }
        }

        if( winner >= 0 )
        {
            if( fileIsOpen( &gFd->open[winner] ) )
            {
                dbgmsg( "closing file '%s', slot #%d",
                        gFd->open[winner].filename,
                        winner );
                TrCloseFile( winner );
            }
        }
        else
        {
            dbgmsg(
                "everything's full!  waiting for someone else to finish something" );
            tr_lockUnlock( gFd->lock );
            tr_wait( 200 );
            tr_lockLock( gFd->lock );
        }
    }

    assert( winner >= 0 );
    o = &gFd->open[winner];
    if( !fileIsOpen( o ) )
    {
        const int err = TrOpenFile( winner, folder, torrentFile, doWrite, doPreallocate, desiredFileSize );
        if( err ) {
            tr_lockUnlock( gFd->lock );
            tr_free( filename );
            errno = err;
            return -1;
        }

        dbgmsg( "opened '%s' in slot %d, doWrite %c", filename, winner,
                doWrite ? 'y' : 'n' );
        tr_strlcpy( o->filename, filename, sizeof( o->filename ) );
        o->isWritable = doWrite;
    }

    dbgmsg( "checking out '%s' in slot %d", filename, winner );
    o->isCheckedOut = 1;
    o->closeWhenDone = 0;
    o->date = tr_date( );
    tr_free( filename );
    tr_lockUnlock( gFd->lock );
    return o->fd;
}
Пример #9
0
/* returns an fd on success, or a -1 on failure and sets errno */
int
tr_fdFileCheckout( tr_session             * session,
                   int                      torrentId,
                   tr_file_index_t          fileNum,
                   const char             * filename,
                   tr_bool                  doWrite,
                   tr_preallocation_mode    preallocationMode,
                   uint64_t                 desiredFileSize )
{
    int i, winner = -1;
    struct tr_fdInfo * gFd;
    struct tr_openfile * o;

    assert( tr_isSession( session ) );
    assert( session->fdInfo != NULL );
    assert( torrentId > 0 );
    assert( filename && *filename );
    assert( tr_isBool( doWrite ) );

    gFd = session->fdInfo;

    dbgmsg( "looking for file '%s', writable %c", filename, doWrite ? 'y' : 'n' );

    /* is it already open? */
    for( i=0; i<gFd->openFileLimit; ++i )
    {
        o = &gFd->openFiles[i];

        if( torrentId != o->torrentId )
            continue;
        if( fileNum != o->fileNum )
            continue;
        if( !fileIsOpen( o ) )
            continue;

        if( doWrite && !o->isWritable )
        {
            dbgmsg( "found it!  it's open and available, but isn't writable. closing..." );
            TrCloseFile( o );
            break;
        }

        dbgmsg( "found it!  it's ready for use!" );
        winner = i;
        break;
    }

    dbgmsg( "it's not already open.  looking for an open slot or an old file." );
    while( winner < 0 )
    {
        time_t date = tr_time( ) + 1;

        /* look for the file that's been open longest */
        for( i=0; i<gFd->openFileLimit; ++i )
        {
            o = &gFd->openFiles[i];

            if( !fileIsOpen( o ) )
            {
                winner = i;
                dbgmsg( "found an empty slot in %d", winner );
                break;
            }

            if( date > o->date )
            {
                date = o->date;
                winner = i;
            }
        }

        assert( winner >= 0 );

        if( fileIsOpen( &gFd->openFiles[winner] ) )
        {
            dbgmsg( "closing file \"%s\"", gFd->openFiles[winner].filename );
            TrCloseFile( &gFd->openFiles[winner] );
        }
    }

    assert( winner >= 0 );
    o = &gFd->openFiles[winner];
    if( !fileIsOpen( o ) )
    {
        const int err = TrOpenFile( session, winner, filename, doWrite,
                                    preallocationMode, desiredFileSize );
        if( err ) {
            errno = err;
            return -1;
        }

        dbgmsg( "opened '%s' in slot %d, doWrite %c", filename, winner,
                doWrite ? 'y' : 'n' );
        tr_strlcpy( o->filename, filename, sizeof( o->filename ) );
        o->isWritable = doWrite;
    }

    dbgmsg( "checking out '%s' in slot %d", filename, winner );
    o->torrentId = torrentId;
    o->fileNum = fileNum;
    o->date = tr_time( );
    return o->fd;
}