mirror of
https://github.com/transmission/transmission
synced 2024-12-25 01:03:01 +00:00
ugly code removal: we were calling stat() three times on each file! (BMW: builder struct changed slightly... this shouldn't affect the mac client but you might want to recompile to confirm)
This commit is contained in:
parent
a4d5dfa328
commit
4eea50e991
2 changed files with 55 additions and 68 deletions
|
@ -14,7 +14,6 @@
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <stdio.h> /* FILE, snprintf, stderr */
|
#include <stdio.h> /* FILE, snprintf, stderr */
|
||||||
#include <stdlib.h> /* malloc, calloc */
|
|
||||||
|
|
||||||
#include "transmission.h"
|
#include "transmission.h"
|
||||||
#include "internal.h" /* for tr_torrent_t */
|
#include "internal.h" /* for tr_torrent_t */
|
||||||
|
@ -31,7 +30,8 @@
|
||||||
struct FileList
|
struct FileList
|
||||||
{
|
{
|
||||||
struct FileList * next;
|
struct FileList * next;
|
||||||
char filename[MAX_PATH_LENGTH];
|
uint64_t size;
|
||||||
|
char * filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct FileList*
|
static struct FileList*
|
||||||
|
@ -62,8 +62,9 @@ getFiles( const char * dir,
|
||||||
}
|
}
|
||||||
else if( S_ISREG( sb.st_mode ) )
|
else if( S_ISREG( sb.st_mode ) )
|
||||||
{
|
{
|
||||||
struct FileList * node = malloc( sizeof( struct FileList ) );
|
struct FileList * node = tr_malloc( sizeof( struct FileList ) );
|
||||||
snprintf( node->filename, sizeof( node->filename ), "%s", buf );
|
node->size = sb.st_size;
|
||||||
|
node->filename = tr_strdup( buf );
|
||||||
node->next = list;
|
node->next = list;
|
||||||
list = node;
|
list = node;
|
||||||
}
|
}
|
||||||
|
@ -71,26 +72,6 @@ getFiles( const char * dir,
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
freeFileList( struct FileList * list )
|
|
||||||
{
|
|
||||||
while( list ) {
|
|
||||||
struct FileList * tmp = list->next;
|
|
||||||
free( list );
|
|
||||||
list = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static off_t
|
|
||||||
getFileSize ( const char * filename )
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
sb.st_size = 0;
|
|
||||||
stat( filename, &sb );
|
|
||||||
return sb.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bestPieceSize( uint64_t totalSize )
|
bestPieceSize( uint64_t totalSize )
|
||||||
{
|
{
|
||||||
|
@ -110,15 +91,12 @@ bestPieceSize( uint64_t totalSize )
|
||||||
return MiB / 4;
|
return MiB / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
static int
|
||||||
*****
|
builderFileCompare ( const void * va, const void * vb)
|
||||||
****/
|
|
||||||
|
|
||||||
static int pstrcmp( const void * va, const void * vb)
|
|
||||||
{
|
{
|
||||||
const char * a = *(const char**) va;
|
const tr_metainfo_builder_file_t * a = (const tr_metainfo_builder_file_t*) va;
|
||||||
const char * b = *(const char**) vb;
|
const tr_metainfo_builder_file_t * b = (const tr_metainfo_builder_file_t*) vb;
|
||||||
return strcmp( a, b );
|
return strcmp( a->filename, b->filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_metainfo_builder_t*
|
tr_metainfo_builder_t*
|
||||||
|
@ -126,11 +104,10 @@ tr_metaInfoBuilderCreate( tr_handle_t * handle, const char * topFile )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct FileList * files;
|
struct FileList * files;
|
||||||
const struct FileList * walk;
|
struct FileList * walk;
|
||||||
tr_metainfo_builder_t * ret = calloc( 1, sizeof(tr_metainfo_builder_t) );
|
tr_metainfo_builder_t * ret = tr_calloc( 1, sizeof(tr_metainfo_builder_t) );
|
||||||
ret->top = tr_strdup( topFile );
|
ret->top = tr_strdup( topFile );
|
||||||
ret->handle = handle;
|
ret->handle = handle;
|
||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
stat( topFile, &sb );
|
stat( topFile, &sb );
|
||||||
|
@ -152,20 +129,25 @@ tr_metaInfoBuilderCreate( tr_handle_t * handle, const char * topFile )
|
||||||
|
|
||||||
for( walk=files; walk!=NULL; walk=walk->next )
|
for( walk=files; walk!=NULL; walk=walk->next )
|
||||||
++ret->fileCount;
|
++ret->fileCount;
|
||||||
ret->files = calloc( ret->fileCount, sizeof(char*) );
|
|
||||||
ret->fileLengths = calloc( ret->fileCount, sizeof(uint64_t) );
|
|
||||||
|
|
||||||
for( i=0, walk=files; walk!=NULL; walk=walk->next, ++i )
|
ret->files = tr_calloc( ret->fileCount, sizeof(tr_metainfo_builder_file_t) );
|
||||||
ret->files[i] = tr_strdup( walk->filename );
|
|
||||||
|
|
||||||
qsort( ret->files, ret->fileCount, sizeof(char*), pstrcmp );
|
for( i=0, walk=files; walk!=NULL; ++i )
|
||||||
for( i=0; i<ret->fileCount; ++i ) {
|
{
|
||||||
ret->fileLengths[i] = getFileSize( ret->files[i] );
|
struct FileList * tmp = walk;
|
||||||
ret->totalSize += ret->fileLengths[i];
|
tr_metainfo_builder_file_t * file = &ret->files[i];
|
||||||
|
walk = walk->next;
|
||||||
|
file->filename = tmp->filename;
|
||||||
|
file->size = tmp->size;
|
||||||
|
ret->totalSize += tmp->size;
|
||||||
|
tr_free( tmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
freeFileList( files );
|
qsort( ret->files,
|
||||||
|
ret->fileCount,
|
||||||
|
sizeof(tr_metainfo_builder_file_t),
|
||||||
|
builderFileCompare );
|
||||||
|
|
||||||
ret->pieceSize = bestPieceSize( ret->totalSize );
|
ret->pieceSize = bestPieceSize( ret->totalSize );
|
||||||
ret->pieceCount = (int)( ret->totalSize / ret->pieceSize);
|
ret->pieceCount = (int)( ret->totalSize / ret->pieceSize);
|
||||||
if( ret->totalSize % ret->pieceSize )
|
if( ret->totalSize % ret->pieceSize )
|
||||||
|
@ -181,9 +163,8 @@ tr_metaInfoBuilderFree( tr_metainfo_builder_t * builder )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for( i=0; i<builder->fileCount; ++i )
|
for( i=0; i<builder->fileCount; ++i )
|
||||||
tr_free( builder->files[i] );
|
tr_free( builder->files[i].filename );
|
||||||
tr_free( builder->files );
|
tr_free( builder->files );
|
||||||
tr_free( builder->fileLengths );
|
|
||||||
tr_free( builder->top );
|
tr_free( builder->top );
|
||||||
tr_free( builder->comment );
|
tr_free( builder->comment );
|
||||||
tr_free( builder->announce );
|
tr_free( builder->announce );
|
||||||
|
@ -200,16 +181,16 @@ static uint8_t*
|
||||||
getHashInfo ( tr_metainfo_builder_t * b )
|
getHashInfo ( tr_metainfo_builder_t * b )
|
||||||
{
|
{
|
||||||
int fileIndex = 0;
|
int fileIndex = 0;
|
||||||
uint8_t *ret = (uint8_t*) malloc ( SHA_DIGEST_LENGTH * b->pieceCount );
|
uint8_t *ret = (uint8_t*) tr_malloc ( SHA_DIGEST_LENGTH * b->pieceCount );
|
||||||
uint8_t *walk = ret;
|
uint8_t *walk = ret;
|
||||||
uint8_t *buf = malloc( b->pieceSize );
|
uint8_t *buf = tr_malloc( b->pieceSize );
|
||||||
uint64_t totalRemain;
|
uint64_t totalRemain;
|
||||||
uint64_t off = 0;
|
uint64_t off = 0;
|
||||||
FILE * fp;
|
FILE * fp;
|
||||||
|
|
||||||
b->pieceIndex = 0;
|
b->pieceIndex = 0;
|
||||||
totalRemain = b->totalSize;
|
totalRemain = b->totalSize;
|
||||||
fp = fopen( b->files[fileIndex], "rb" );
|
fp = fopen( b->files[fileIndex].filename, "rb" );
|
||||||
while ( totalRemain )
|
while ( totalRemain )
|
||||||
{
|
{
|
||||||
uint8_t *bufptr = buf;
|
uint8_t *bufptr = buf;
|
||||||
|
@ -220,17 +201,17 @@ getHashInfo ( tr_metainfo_builder_t * b )
|
||||||
|
|
||||||
while( pieceRemain )
|
while( pieceRemain )
|
||||||
{
|
{
|
||||||
const uint64_t n_this_pass = MIN( (b->fileLengths[fileIndex] - off), pieceRemain );
|
const uint64_t n_this_pass = MIN( (b->files[fileIndex].size - off), pieceRemain );
|
||||||
fread( bufptr, 1, n_this_pass, fp );
|
fread( bufptr, 1, n_this_pass, fp );
|
||||||
bufptr += n_this_pass;
|
bufptr += n_this_pass;
|
||||||
off += n_this_pass;
|
off += n_this_pass;
|
||||||
pieceRemain -= n_this_pass;
|
pieceRemain -= n_this_pass;
|
||||||
if( off == b->fileLengths[fileIndex] ) {
|
if( off == b->files[fileIndex].size ) {
|
||||||
off = 0;
|
off = 0;
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
if( ++fileIndex < b->fileCount ) {
|
if( ++fileIndex < b->fileCount ) {
|
||||||
fp = fopen( b->files[fileIndex], "rb" );
|
fp = fopen( b->files[fileIndex].filename, "rb" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,15 +236,15 @@ getHashInfo ( tr_metainfo_builder_t * b )
|
||||||
if( fp != NULL )
|
if( fp != NULL )
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
|
|
||||||
free( buf );
|
tr_free( buf );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
getFileInfo( const char * topFile,
|
getFileInfo( const char * topFile,
|
||||||
const char * filename,
|
const tr_metainfo_builder_file_t * file,
|
||||||
benc_val_t * uninitialized_length,
|
benc_val_t * uninitialized_length,
|
||||||
benc_val_t * uninitialized_path )
|
benc_val_t * uninitialized_path )
|
||||||
{
|
{
|
||||||
benc_val_t *sub;
|
benc_val_t *sub;
|
||||||
const char *pch, *prev;
|
const char *pch, *prev;
|
||||||
|
@ -271,16 +252,16 @@ getFileInfo( const char * topFile,
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* get the file size */
|
/* get the file size */
|
||||||
tr_bencInitInt( uninitialized_length, getFileSize(filename) );
|
tr_bencInitInt( uninitialized_length, file->size );
|
||||||
|
|
||||||
/* the path list */
|
/* the path list */
|
||||||
n = 1;
|
n = 1;
|
||||||
for( pch=filename+topLen; *pch; ++pch )
|
for( pch=file->filename+topLen; *pch; ++pch )
|
||||||
if (*pch == TR_PATH_DELIMITER)
|
if (*pch == TR_PATH_DELIMITER)
|
||||||
++n;
|
++n;
|
||||||
tr_bencInit( uninitialized_path, TYPE_LIST );
|
tr_bencInit( uninitialized_path, TYPE_LIST );
|
||||||
tr_bencListReserve( uninitialized_path, n );
|
tr_bencListReserve( uninitialized_path, n );
|
||||||
for( prev=pch=filename+topLen; ; ++pch )
|
for( prev=pch=file->filename+topLen; ; ++pch )
|
||||||
{
|
{
|
||||||
char buf[MAX_PATH_LENGTH];
|
char buf[MAX_PATH_LENGTH];
|
||||||
|
|
||||||
|
@ -316,7 +297,7 @@ makeFilesList( benc_val_t * list,
|
||||||
tr_bencDictReserve( dict, 2 );
|
tr_bencDictReserve( dict, 2 );
|
||||||
length = tr_bencDictAdd( dict, "length" );
|
length = tr_bencDictAdd( dict, "length" );
|
||||||
pathVal = tr_bencDictAdd( dict, "path" );
|
pathVal = tr_bencDictAdd( dict, "path" );
|
||||||
getFileInfo( builder->top, builder->files[i], length, pathVal );
|
getFileInfo( builder->top, &builder->files[i], length, pathVal );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +325,7 @@ makeInfoDict ( benc_val_t * dict,
|
||||||
if ( builder->isSingleFile )
|
if ( builder->isSingleFile )
|
||||||
{
|
{
|
||||||
val = tr_bencDictAdd( dict, "length" );
|
val = tr_bencDictAdd( dict, "length" );
|
||||||
tr_bencInitInt( val, builder->fileLengths[0] );
|
tr_bencInitInt( val, builder->files[0].size );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -398,7 +379,7 @@ static void tr_realMakeMetaInfo ( tr_metainfo_builder_t * builder )
|
||||||
builder->failed = 1;
|
builder->failed = 1;
|
||||||
else if( fwrite( pch, 1, nmemb, fp ) != nmemb )
|
else if( fwrite( pch, 1, nmemb, fp ) != nmemb )
|
||||||
builder->failed = 1;
|
builder->failed = 1;
|
||||||
free( pch );
|
tr_free( pch );
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +408,7 @@ static tr_lock_t* getQueueLock( tr_handle_t * h )
|
||||||
tr_sharedLock( h->shared );
|
tr_sharedLock( h->shared );
|
||||||
if( lock == NULL )
|
if( lock == NULL )
|
||||||
{
|
{
|
||||||
lock = calloc( 1, sizeof( tr_lock_t ) );
|
lock = tr_calloc( 1, sizeof( tr_lock_t ) );
|
||||||
tr_lockInit( lock );
|
tr_lockInit( lock );
|
||||||
}
|
}
|
||||||
tr_sharedUnlock( h->shared );
|
tr_sharedUnlock( h->shared );
|
||||||
|
|
|
@ -11,6 +11,13 @@
|
||||||
#ifndef TR_MAKEMETA_H
|
#ifndef TR_MAKEMETA_H
|
||||||
#define TR_MAKEMETA_H 1
|
#define TR_MAKEMETA_H 1
|
||||||
|
|
||||||
|
typedef struct tr_metainfo_builder_file_s
|
||||||
|
{
|
||||||
|
char * filename;
|
||||||
|
uint64_t size;
|
||||||
|
}
|
||||||
|
tr_metainfo_builder_file_t;
|
||||||
|
|
||||||
typedef struct tr_metainfo_builder_s
|
typedef struct tr_metainfo_builder_s
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +26,7 @@ typedef struct tr_metainfo_builder_s
|
||||||
**/
|
**/
|
||||||
|
|
||||||
char * top;
|
char * top;
|
||||||
char ** files;
|
tr_metainfo_builder_file_t * files;
|
||||||
uint64_t * fileLengths;
|
|
||||||
uint64_t totalSize;
|
uint64_t totalSize;
|
||||||
int fileCount;
|
int fileCount;
|
||||||
int pieceSize;
|
int pieceSize;
|
||||||
|
|
Loading…
Reference in a new issue