(trunk libT) #2551 "better buffer cache management": apply jch's prefetch-base.patch
This commit is contained in:
parent
b906c125ac
commit
3759c98d76
|
@ -208,6 +208,56 @@ tr_preallocate_file( const char * filename, uint64_t length )
|
|||
return preallocateFileFull( filename, length );
|
||||
}
|
||||
|
||||
/* Like pread and pwrite, except that the position is undefined afterwards.
|
||||
And of course they are not thread-safe. */
|
||||
|
||||
#ifdef SYS_DARWIN
|
||||
#define HAVE_PREAD
|
||||
#define HAVE_PWRITE
|
||||
#endif
|
||||
|
||||
ssize_t
|
||||
tr_pread( int fd, void *buf, size_t count, off_t offset )
|
||||
{
|
||||
#ifdef HAVE_PREAD
|
||||
return pread( fd, buf, count, offset );
|
||||
#else
|
||||
const off_t lrc = lseek( fd, offset, SEEK_SET );
|
||||
if( lrc < 0 )
|
||||
return -1;
|
||||
return read( fd, buf, count );
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t
|
||||
tr_pwrite( int fd, void *buf, size_t count, off_t offset )
|
||||
{
|
||||
#ifdef HAVE_PWRITE
|
||||
return pwrite( fd, buf, count, offset );
|
||||
#else
|
||||
const off_t lrc = lseek( fd, offset, SEEK_SET );
|
||||
if( lrc < 0 )
|
||||
return -1;
|
||||
return write( fd, buf, count );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
tr_prefetch( int fd, off_t offset, size_t count )
|
||||
{
|
||||
#ifdef HAVE_POSIX_FADVISE
|
||||
return posix_fadvise( fd, offset, count, POSIX_FADV_WILLNEED );
|
||||
#elif defined(SYS_DARWIN)
|
||||
int val;
|
||||
struct radvisory radv;
|
||||
radv.ra_offset = offset;
|
||||
radv.ra_count = count;
|
||||
return fcntl( fd, F_RDADVISE, &radv );
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
tr_open_file_for_writing( const char * filename )
|
||||
{
|
||||
|
|
|
@ -53,6 +53,9 @@ void tr_close_file( int fd );
|
|||
tr_bool tr_preallocate_file( const char * filename, uint64_t length );
|
||||
|
||||
int64_t tr_lseek( int fd, int64_t offset, int whence );
|
||||
ssize_t tr_pread(int fd, void *buf, size_t count, off_t offset);
|
||||
ssize_t tr_pwrite(int fd, void *buf, size_t count, off_t offset);
|
||||
int tr_prefetch(int fd, off_t offset, size_t count);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,7 +50,10 @@
|
|||
#define write _write
|
||||
#endif
|
||||
|
||||
enum { TR_IO_READ, TR_IO_WRITE };
|
||||
enum { TR_IO_READ, TR_IO_PREFETCH,
|
||||
/* Any operations that require write access must follow TR_IO_WRITE. */
|
||||
TR_IO_WRITE
|
||||
};
|
||||
|
||||
int64_t
|
||||
tr_lseek( int fd, int64_t offset, int whence )
|
||||
|
@ -77,11 +80,9 @@ readOrWriteBytes( tr_session * session,
|
|||
const tr_info * info = &tor->info;
|
||||
const tr_file * file = &info->files[fileIndex];
|
||||
|
||||
typedef size_t ( *iofunc )( int, void *, size_t );
|
||||
iofunc func = ioMode == TR_IO_READ ? (iofunc)read : (iofunc)write;
|
||||
int fd = -1;
|
||||
int err = 0;
|
||||
const tr_bool doWrite = ioMode == TR_IO_WRITE;
|
||||
const tr_bool doWrite = ioMode >= TR_IO_WRITE;
|
||||
|
||||
assert( fileIndex < info->fileCount );
|
||||
assert( !file->length || ( fileOffset < file->length ) );
|
||||
|
@ -113,12 +114,12 @@ readOrWriteBytes( tr_session * session,
|
|||
subpath = tr_strdup( file->name );
|
||||
}
|
||||
|
||||
if( ( file->dnd ) || ( ioMode != TR_IO_WRITE ) )
|
||||
if( ( file->dnd ) || ( ioMode < TR_IO_WRITE ) )
|
||||
preallocationMode = TR_PREALLOCATE_NONE;
|
||||
else
|
||||
preallocationMode = tor->session->preallocationMode;
|
||||
|
||||
if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */
|
||||
if( ( ioMode < TR_IO_WRITE ) && !fileExists ) /* does file exist? */
|
||||
{
|
||||
err = ENOENT;
|
||||
}
|
||||
|
@ -144,16 +145,29 @@ readOrWriteBytes( tr_session * session,
|
|||
|
||||
if( !err )
|
||||
{
|
||||
if( tr_lseek( fd, (int64_t)fileOffset, SEEK_SET ) == -1 )
|
||||
{
|
||||
err = errno;
|
||||
tr_torerr( tor, "tr_lseek failed for \"%s\": %s", file->name, tr_strerror( err ) );
|
||||
}
|
||||
else if( func( fd, buf, buflen ) != buflen )
|
||||
{
|
||||
err = errno;
|
||||
tr_torerr( tor, "read/write failed for \"%s\": %s", file->name, tr_strerror( err ) );
|
||||
}
|
||||
if( ioMode == TR_IO_READ ) {
|
||||
int rc = tr_pread(fd, buf, buflen, fileOffset);
|
||||
if(rc < 0) {
|
||||
err = errno;
|
||||
tr_torerr( tor, "read failed for \"%s\": %s",
|
||||
file->name, tr_strerror( err ) );
|
||||
}
|
||||
} else if( ioMode == TR_IO_PREFETCH ) {
|
||||
int rc = tr_prefetch(fd, fileOffset, buflen);
|
||||
if(rc < 0) {
|
||||
err = errno;
|
||||
tr_torerr( tor, "prefetch failed for \"%s\": %s",
|
||||
file->name, tr_strerror( err ) );
|
||||
}
|
||||
} else if( ioMode == TR_IO_WRITE ) {
|
||||
int rc = tr_pwrite(fd, buf, buflen, fileOffset);
|
||||
if(rc < 0) {
|
||||
err = errno;
|
||||
tr_torerr( tor, "write failed for \"%s\": %s",
|
||||
file->name, tr_strerror( err ) );
|
||||
}
|
||||
} else
|
||||
abort();
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -246,6 +260,16 @@ tr_ioRead( tr_torrent * tor,
|
|||
return readOrWritePiece( tor, TR_IO_READ, pieceIndex, begin, buf, len );
|
||||
}
|
||||
|
||||
int
|
||||
tr_ioPrefetch( tr_torrent * tor,
|
||||
tr_piece_index_t pieceIndex,
|
||||
uint32_t begin,
|
||||
uint32_t len)
|
||||
{
|
||||
return readOrWritePiece( tor, TR_IO_PREFETCH, pieceIndex, begin,
|
||||
NULL, len );
|
||||
}
|
||||
|
||||
int
|
||||
tr_ioWrite( tr_torrent * tor,
|
||||
tr_piece_index_t pieceIndex,
|
||||
|
|
|
@ -34,6 +34,12 @@ int tr_ioRead( struct tr_torrent * tor,
|
|||
uint32_t len,
|
||||
uint8_t * setme );
|
||||
|
||||
int
|
||||
tr_ioPrefetch( tr_torrent * tor,
|
||||
tr_piece_index_t pieceIndex,
|
||||
uint32_t begin,
|
||||
uint32_t len );
|
||||
|
||||
/**
|
||||
* Writes the block specified by the piece index, offset, and length.
|
||||
* @return 0 on success, or an errno value on failure.
|
||||
|
|
Loading…
Reference in New Issue