Changeset 7051


Ignore:
Timestamp:
Nov 5, 2008, 5:56:06 AM (10 years ago)
Author:
charles
Message:

(libT) #849: preallocate files when possible to prevent disk fragmentation

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/configure.ac

    r7036 r7051  
    5050AC_HEADER_STDC
    5151AC_HEADER_TIME
    52 AC_CHECK_FUNCS([lrintf strlcpy daemon dirname basename daemon strcasecmp localtime_r])
     52AC_CHECK_FUNCS([lrintf strlcpy daemon dirname basename daemon strcasecmp localtime_r fallocate posix_fallocate])
    5353AC_PROG_INSTALL
    5454AC_PROG_MAKE_SET
  • trunk/libtransmission/fdlimit.c

    r6961 r7051  
    3333#include <stdlib.h>
    3434#include <string.h>
     35#ifdef SYS_DARWIN
     36#include <fcntl.h>
     37#endif
    3538
    3639#include <sys/types.h>
     
    9699****
    97100***/
     101
     102static int
     103preallocateFile( int fd UNUSED, uint64_t length UNUSED )
     104{
     105#ifdef HAVE_FALLOCATE
     106
     107    return fallocate( fd, 0, offset, length );
     108
     109#elif defined(HAVE_POSIX_FALLOCATE)
     110
     111    return posix_fallocate( fd, 0, length );
     112
     113#elif defined(SYS_DARWIN)
     114
     115    fstore_t fst;
     116    fst.fst_flags = F_ALLOCATECONTIG;
     117    fst.fst_posmode = F_PEOFPOSMODE;
     118    fst.fst_offset = 0;
     119    fst.fst_length = length;
     120    fst.fst_bytesalloc = 0;
     121    return fcntl( fd, F_PREALLOCATE, &fst );
     122
     123#else
     124
     125    #warning no known method to preallocate files on this platform
     126    return -1;
     127
     128#endif
     129}
    98130
    99131/**
     
    106138            const char * folder,
    107139            const char * torrentFile,
    108             int          write )
     140            int          doWrite,
     141            int          doPreallocate,
     142            uint64_t     desiredFileSize )
    109143{
    110144    struct tr_openfile * file = &gFd->open[i];
     
    112146    char               * filename;
    113147    struct stat          sb;
     148    int                  alreadyExisted;
    114149
    115150    /* confirm the parent folder exists */
     
    119154    /* create subfolders, if any */
    120155    filename = tr_buildPath( folder, torrentFile, NULL );
    121     if( write )
     156    if( doWrite )
    122157    {
    123158        char * tmp = tr_dirname( filename );
     
    130165    }
    131166
     167    alreadyExisted = !stat( filename, &sb ) && S_ISREG( sb.st_mode );
     168   
    132169    /* open the file */
    133     flags = write ? ( O_RDWR | O_CREAT ) : O_RDONLY;
     170    flags = doWrite ? ( O_RDWR | O_CREAT ) : O_RDONLY;
    134171#ifdef O_LARGEFILE
    135172    flags |= O_LARGEFILE;
     
    148185    }
    149186
     187    if( ( file->fd >= 0 ) && !alreadyExisted && doPreallocate )
     188        if( !preallocateFile( file->fd, desiredFileSize ) )
     189            tr_inf( _( "Preallocated file \"%s\"" ), filename );
     190       
    150191    tr_free( filename );
    151192    return 0;
     
    182223tr_fdFileCheckout( const char * folder,
    183224                   const char * torrentFile,
    184                    int          write )
     225                   int          doWrite,
     226                   int          doPreallocate,
     227                   uint64_t     desiredFileSize )
    185228{
    186229    int                  i, winner = -1;
     
    190233    assert( folder && *folder );
    191234    assert( torrentFile && *torrentFile );
    192     assert( write == 0 || write == 1 );
     235    assert( doWrite == 0 || doWrite == 1 );
    193236
    194237    filename = tr_buildPath( folder, torrentFile, NULL );
    195238    dbgmsg( "looking for file '%s', writable %c", filename,
    196             write ? 'y' : 'n' );
     239            doWrite ? 'y' : 'n' );
    197240
    198241    tr_lockLock( gFd->lock );
     
    219262        }
    220263
    221         if( write && !o->isWritable )
     264        if( doWrite && !o->isWritable )
    222265        {
    223266            dbgmsg(
     
    281324    if( !fileIsOpen( o ) )
    282325    {
    283         const int err = TrOpenFile( winner, folder, torrentFile, write );
     326        const int err = TrOpenFile( winner, folder, torrentFile, doWrite, doPreallocate, desiredFileSize );
    284327        if( err ) {
    285328            tr_lockUnlock( gFd->lock );
     
    289332        }
    290333
    291         dbgmsg( "opened '%s' in slot %d, write %c", filename, winner,
    292                 write ? 'y' : 'n' );
     334        dbgmsg( "opened '%s' in slot %d, doWrite %c", filename, winner,
     335                doWrite ? 'y' : 'n' );
    293336        tr_strlcpy( o->filename, filename, sizeof( o->filename ) );
    294         o->isWritable = write;
     337        o->isWritable = doWrite;
    295338    }
    296339
  • trunk/libtransmission/fdlimit.h

    r6906 r7051  
    5555int  tr_fdFileCheckout( const char * folder,
    5656                        const char * torrentFile,
    57                         int          doWrite );
     57                        int          doWrite,
     58                        int          doPreallocate,
     59                        uint64_t     desiredFileSize );
    5860
    5961/**
  • trunk/libtransmission/inout.c

    r7046 r7051  
    8484    if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */
    8585        err = errno;
    86     else if( ( fd = tr_fdFileCheckout ( tor->downloadDir,
    87                                         file->name,
    88                                         ioMode == TR_IO_WRITE ) ) < 0 )
     86    else if( ( fd = tr_fdFileCheckout ( tor->downloadDir, file->name, ioMode == TR_IO_WRITE, !file->dnd, file->length ) ) < 0 )
    8987        err = errno;
    9088    else if( lseek( fd, (off_t)fileOffset, SEEK_SET ) == ( (off_t)-1 ) )
     
    154152    assert( minBytes <= file->length );
    155153
    156     fd = tr_fdFileCheckout( tor->downloadDir, file->name, TRUE );
     154    fd = tr_fdFileCheckout( tor->downloadDir,
     155                            file->name,
     156                            TRUE,
     157                            tor->session->doPreallocateFiles && !file->dnd,
     158                            file->length );
     159
    157160    if( fd < 0 ) /* bad fd */
    158161        err = errno;
  • trunk/libtransmission/torrent.c

    r7027 r7051  
    17691769}
    17701770
     1771/**
     1772***
     1773**/
     1774
     1775uint64_t
     1776tr_torrentGetBytesLeftToAllocate( const tr_torrent * tor )
     1777{
     1778    const tr_file * it;
     1779    const tr_file * end;
     1780    struct stat sb;
     1781    uint64_t bytesLeft = 0;
     1782
     1783    for( it=tor->info.files, end=it+tor->info.fileCount; it!=end; ++it )
     1784    {
     1785        if( !it->dnd )
     1786        {
     1787            char * path = tr_buildPath( tor->downloadDir, it->name, NULL );
     1788
     1789            bytesLeft += it->length;
     1790
     1791            if( !stat( path, &sb )
     1792                    && S_ISREG( sb.st_mode )
     1793                    && ( sb.st_size <= it->length ) )
     1794                bytesLeft -= sb.st_size;
     1795
     1796            tr_free( path );
     1797        }
     1798    }
     1799
     1800    return bytesLeft;
     1801}
  • trunk/libtransmission/transmission.h

    r7021 r7051  
    835835                            tr_torrent  * current );
    836836
     837
     838uint64_t tr_torrentGetBytesLeftToAllocate( const tr_torrent * torrent );
     839
    837840/**
    838841 * @brief Returns this torrent's unique ID.
Note: See TracChangeset for help on using the changeset viewer.