1
0
Fork 0
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:
Charles Kerr 2007-06-19 00:08:39 +00:00
parent a4d5dfa328
commit 4eea50e991
2 changed files with 55 additions and 68 deletions

View file

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

View file

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