(trunk libT) #2551 "better buffer cache management": apply jch's prefetch-base.patch

This commit is contained in:
Charles Kerr 2009-11-08 23:43:38 +00:00
parent b906c125ac
commit 3759c98d76
4 changed files with 99 additions and 16 deletions

View File

@ -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 )
{

View File

@ -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);
/**

View File

@ -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,

View File

@ -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.