Ticket #2551: prefetch-base.patch

File prefetch-base.patch, 6.0 KB (added by jch, 11 years ago)
  • libtransmission/fdlimit.c

    diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c
    index dc43102..c5e5b5b 100644
    a b tr_preallocate_file( const char * filename, uint64_t length ) 
    208208    return preallocateFileFull( filename, length );
    209209}
    210210
     211/* Like pread and pwrite, except that the position is undefined afterwards.
     212   And of course they are not thread-safe. */
     213
     214#define HAVE_PREAD_PWRITE
     215
     216ssize_t
     217tr_pread(int fd, void *buf, size_t count, off_t offset)
     218{
     219#ifdef HAVE_PREAD_PWRITE
     220    return pread(fd, buf, count, offset);
     221#else
     222    off_t lrc;
     223    lrc = lseek(fd, offset, SEEK_SET);
     224    if(lrc < 0)
     225        return -1;
     226    return read(fd, buf, count);
     227#endif
     228}
     229
     230ssize_t
     231tr_pwrite(int fd, void *buf, size_t count, off_t offset)
     232{
     233#ifdef HAVE_PREAD_PWRITE
     234    return pwrite(fd, buf, count, offset);
     235#else
     236    off_t lrc;
     237    lrc = lseek(fd, offset, SEEK_SET);
     238    if(lrc < 0)
     239        return -1;
     240    return write(fd, buf, count);
     241#endif
     242}
     243
     244int
     245tr_prefetch(int fd, off_t offset, size_t count)
     246{
     247#ifdef HAVE_POSIX_FADVISE
     248    return posix_fadvise(fd, offset, count, POSIX_FADV_WILLNEED);
     249#else
     250    /* On old BSD systems, we might call fcntl(F_RDADVISE).  This should
     251       not be necessary, posix_fadvise has been around since POSIX.2001. */
     252    return 0;
     253#endif
     254}
     255
    211256int
    212257tr_open_file_for_writing( const char * filename )
    213258{
  • libtransmission/fdlimit.h

    diff --git a/libtransmission/fdlimit.h b/libtransmission/fdlimit.h
    index c5a35b3..fbe788b 100644
    a b void tr_close_file( int fd ); 
    5353tr_bool tr_preallocate_file( const char * filename, uint64_t length );
    5454
    5555int64_t tr_lseek( int fd, int64_t offset, int whence );
     56ssize_t tr_pread(int fd, void *buf, size_t count, off_t offset);
     57ssize_t tr_pwrite(int fd, void *buf, size_t count, off_t offset);
     58int tr_prefetch(int fd, off_t offset, size_t count);
    5659
    5760
    5861/**
  • libtransmission/inout.c

    diff --git a/libtransmission/inout.c b/libtransmission/inout.c
    index fce9c3f..e790996 100644
    a b  
    5050 #define write _write
    5151#endif
    5252
    53 enum { TR_IO_READ, TR_IO_WRITE };
     53enum { TR_IO_READ, TR_IO_PREFETCH,
     54       /* Any operations that require write access must follow TR_IO_WRITE. */
     55       TR_IO_WRITE
     56};
    5457
    5558int64_t
    5659tr_lseek( int fd, int64_t offset, int whence )
    readOrWriteBytes( tr_session * session, 
    7780    const tr_info * info = &tor->info;
    7881    const tr_file * file = &info->files[fileIndex];
    7982
    80     typedef size_t ( *iofunc )( int, void *, size_t );
    81     iofunc          func = ioMode == TR_IO_READ ? (iofunc)read : (iofunc)write;
    8283    int             fd = -1;
    8384    int             err = 0;
    84     const tr_bool doWrite = ioMode == TR_IO_WRITE;
     85    const tr_bool doWrite = ioMode >= TR_IO_WRITE;
    8586
    8687    assert( fileIndex < info->fileCount );
    8788    assert( !file->length || ( fileOffset < file->length ) );
    readOrWriteBytes( tr_session * session, 
    113114                subpath = tr_strdup( file->name );
    114115        }
    115116
    116         if( ( file->dnd ) || ( ioMode != TR_IO_WRITE ) )
     117        if( ( file->dnd ) || ( ioMode < TR_IO_WRITE ) )
    117118            preallocationMode = TR_PREALLOCATE_NONE;
    118119        else
    119120            preallocationMode = tor->session->preallocationMode;
    120121
    121         if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */
     122        if( ( ioMode < TR_IO_WRITE ) && !fileExists ) /* does file exist? */
    122123        {
    123124            err = ENOENT;
    124125        }
    readOrWriteBytes( tr_session * session, 
    144145
    145146    if( !err )
    146147    {
    147         if( tr_lseek( fd, (int64_t)fileOffset, SEEK_SET ) == -1 )
    148         {
    149             err = errno;
    150             tr_torerr( tor, "tr_lseek failed for \"%s\": %s", file->name, tr_strerror( err ) );
    151         }
    152         else if( func( fd, buf, buflen ) != buflen )
    153         {
    154             err = errno;
    155             tr_torerr( tor, "read/write failed for \"%s\": %s", file->name, tr_strerror( err ) );
    156         }
     148        if( ioMode == TR_IO_READ ) {
     149            int rc = tr_pread(fd, buf, buflen, fileOffset);
     150            if(rc < 0) {
     151                err = errno;
     152                tr_torerr( tor, "read failed for \"%s\": %s",
     153                           file->name, tr_strerror( err ) );
     154            }
     155        } else if( ioMode == TR_IO_PREFETCH ) {
     156            int rc = tr_prefetch(fd, fileOffset, buflen);
     157            if(rc < 0) {
     158                err = errno;
     159                tr_torerr( tor, "write failed for \"%s\": %s",
     160                           file->name, tr_strerror( err ) );
     161            }
     162        } else if( ioMode == TR_IO_WRITE ) {
     163            int rc = tr_pwrite(fd, buf, buflen, fileOffset);
     164            if(rc < 0) {
     165                err = errno;
     166                tr_torerr( tor, "write failed for \"%s\": %s",
     167                           file->name, tr_strerror( err ) );
     168            }
     169        } else
     170            abort();
    157171    }
    158172
    159173    return err;
    tr_ioRead( tr_torrent * tor, 
    247261}
    248262
    249263int
     264tr_ioPrefetch( tr_torrent       * tor,
     265               tr_piece_index_t   pieceIndex,
     266               uint32_t           begin,
     267               uint32_t           len)
     268{
     269    return readOrWritePiece( tor, TR_IO_PREFETCH, pieceIndex, begin,
     270                             NULL, len );
     271}
     272
     273int
    250274tr_ioWrite( tr_torrent       * tor,
    251275            tr_piece_index_t   pieceIndex,
    252276            uint32_t           begin,
  • libtransmission/inout.h

    diff --git a/libtransmission/inout.h b/libtransmission/inout.h
    index 78ebf2d..cf4c00b 100644
    a b int tr_ioRead( struct tr_torrent * tor, 
    3434               uint32_t              len,
    3535               uint8_t             * setme );
    3636
     37int
     38tr_ioPrefetch( tr_torrent       * tor,
     39               tr_piece_index_t   pieceIndex,
     40               uint32_t           begin,
     41               uint32_t           len);
     42
    3743/**
    3844 * Writes the block specified by the piece index, offset, and length.
    3945 * @return 0 on success, or an errno value on failure.