Changeset 2107


Ignore:
Timestamp:
Jun 16, 2007, 11:58:03 PM (15 years ago)
Author:
charles
Message:

let libT handle all the makemeta worker thread stuff. (and make BMW have to change his backend calls all over again, muhaha)

Location:
branches/file_selection
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • branches/file_selection/cli/transmissioncli.c

    r2105 r2107  
    9393#define LINEWIDTH 80
    9494
    95 static void
    96 progress_func( const meta_info_builder_t * builder,
    97                size_t                      pieceIndex,
    98                int                       * abortFlag   UNUSED,
    99                void                      * userData    UNUSED )
    100 {
    101     double percent = (double)pieceIndex / builder->pieceCount;
    102     printf( "%d%% done (on block %lu of %lu)\n",
    103             (int)(100.0*percent + 0.5),
    104             pieceIndex, builder->pieceCount );
    105 }
    106 
    107 
    10895int main( int argc, char ** argv )
    10996{
     
    155142    if( sourceFile && *sourceFile ) /* creating a torrent */
    156143    {
    157         meta_info_builder_t* builder = tr_metaInfoBuilderCreate( sourceFile );
    158         int ret = tr_makeMetaInfo( builder,
    159                                    progress_func, NULL,
    160                                    NULL, announce, comment, isPrivate );
     144        int ret;
     145        tr_metainfo_builder_t* builder = tr_metaInfoBuilderCreate( h, sourceFile );
     146        tr_makeMetaInfo( builder, NULL, announce, comment, isPrivate );
     147        while( !builder->isDone ) {
     148            usleep( 1 );
     149            printf( "." );
     150        }
     151        ret = !builder->failed;
    161152        tr_metaInfoBuilderFree( builder );
    162153        return ret;
  • branches/file_selection/gtk/main.c

    r2097 r2107  
    347347gtksetup( int * argc, char *** argv, struct cbdata * callback_data )
    348348{
    349     gtk_init( argc, argv );
    350349
    351350    bindtextdomain( "transmission-gtk", LOCALEDIR );
     
    353352    textdomain( "transmission-gtk" );
    354353
     354    g_thread_init (0);
    355355    g_set_application_name( _("Transmission") );
     356    gtk_init( argc, argv );
    356357
    357358    /* connect up the actions */
     
    995996    else if (!strcmp (action_name, "create-torrent"))
    996997    {
    997         GtkWidget * w = make_meta_ui( GTK_WINDOW( data->wind ) );
     998        GtkWidget * w = make_meta_ui( GTK_WINDOW( data->wind ), tr_core_handle( data->core ) );
    998999        gtk_widget_show_all( w );
    9991000    }
  • branches/file_selection/gtk/make-meta-ui.c

    r2104 r2107  
    2828#include <gtk/gtk.h>
    2929
     30#include "transmission.h"
    3031#include "makemeta.h"
    3132
     
    4041    GtkWidget * comment_entry;
    4142    GtkWidget * private_check;
    42     meta_info_builder_t * builder;
     43    tr_metainfo_builder_t * builder;
     44    tr_handle_t * handle;
    4345}
    4446MakeMetaUI;
    4547
    4648static void
    47 cancel_cb( GtkDialog *d UNUSED, int response UNUSED, gpointer cancel_flag )
    48 {
    49     *(int*)cancel_flag = TRUE;
    50 }
    51 
    52 static void
    53 progress_cb( const meta_info_builder_t  * builder    UNUSED,
    54              size_t                       pieceIndex,
    55              int                        * abortFlag,
    56              void                       * user_data  UNUSED)
    57 {
    58     g_message ("%lu of %lu", pieceIndex, builder->pieceCount);
    59 
    60     *abortFlag = *(gboolean*)user_data;
     49cancel_cb( GtkDialog *d UNUSED, int response UNUSED, gpointer user_data )
     50{
     51    MakeMetaUI * ui = (MakeMetaUI *) user_data;
     52    ui->builder->abortFlag = TRUE;
     53}
     54
     55static gboolean
     56refresh_cb ( gpointer user_data )
     57{
     58    MakeMetaUI * ui = (MakeMetaUI *) user_data;
     59
     60    g_message ("refresh");
     61
     62    return !ui->builder->isDone;
    6163}
    6264
     
    6466response_cb( GtkDialog* d, int response, gpointer user_data )
    6567{
    66     int ret;
    67     gboolean cancelFlag = FALSE;
    6868    MakeMetaUI * ui = (MakeMetaUI*) user_data;
    6969    GtkWidget *w, *l, *p;
     
    8181                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    8282                                     NULL );
    83     g_signal_connect( w, "response", G_CALLBACK(cancel_cb), &cancelFlag );
     83    g_signal_connect( w, "response", G_CALLBACK(cancel_cb), ui );
    8484
    8585    tmp = g_path_get_basename (ui->builder->top);
     
    8888    gtk_box_pack_start_defaults ( GTK_BOX(GTK_DIALOG(w)->vbox), l );
    8989    p = gtk_progress_bar_new ();
    90     gtk_box_pack_start_defaults ( GTK_BOX(GTK_DIALOG(w)->vbox), l );
     90    gtk_box_pack_start_defaults ( GTK_BOX(GTK_DIALOG(w)->vbox), p );
    9191    gtk_widget_show_all ( w );
    9292    g_free( name );
    9393    g_free( tmp );
    9494
    95     ret = tr_makeMetaInfo( ui->builder,
    96                            progress_cb, &cancelFlag,
    97                            NULL,
    98                            gtk_entry_get_text( GTK_ENTRY( ui->announce_entry ) ),
    99                            gtk_entry_get_text( GTK_ENTRY( ui->comment_entry ) ),
    100                            gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ui->private_check ) ) );
    101     if( !ret )
    102       gtk_widget_destroy( GTK_WIDGET( d ) );
     95    tr_makeMetaInfo( ui->builder,
     96                     NULL,
     97                     gtk_entry_get_text( GTK_ENTRY( ui->announce_entry ) ),
     98                     gtk_entry_get_text( GTK_ENTRY( ui->comment_entry ) ),
     99                     gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ui->private_check ) ) );
     100
     101    g_timeout_add ( 1000, refresh_cb, ui );
    103102}
    104103
     
    141140
    142141    filename = gtk_file_chooser_get_filename( chooser );
    143     ui->builder = tr_metaInfoBuilderCreate( filename );
     142    ui->builder = tr_metaInfoBuilderCreate( ui->handle, filename );
    144143    g_free( filename );
    145144
     
    153152
    154153GtkWidget*
    155 make_meta_ui( GtkWindow * parent )
     154make_meta_ui( GtkWindow * parent, tr_handle_t * handle )
    156155{
    157156    int row = 0;
    158157    GtkWidget *d, *t, *w, *h, *rb_file, *rb_dir;
    159158    char name[256];
    160     MakeMetaUI * ui = g_new0 ( MakeMetaUI, 1 ) ;
     159    MakeMetaUI * ui = g_new0 ( MakeMetaUI, 1 );
     160    ui->handle = handle;
    161161
    162162    d = gtk_dialog_new_with_buttons( _("Make a New Torrent"),
  • branches/file_selection/gtk/make-meta-ui.h

    r2097 r2107  
    2727
    2828#include <gtk/gtk.h>
     29#include "transmission.h"
    2930
    30 GtkWidget* make_meta_ui( GtkWindow * parent );
     31GtkWidget* make_meta_ui( GtkWindow * parent, tr_handle_t * handle );
    3132
    3233#endif
  • branches/file_selection/libtransmission/choking.c

    r2005 r2107  
    3030#endif
    3131
    32 /* We may try to allocate and free tables of size 0. Quick and dirty
    33    way to handle it... */
    34 void * tr_malloc( size_t size )
    35 {
    36     if( !size )
    37         return NULL;
    38     return malloc( size );
    39 }
    40 void tr_free( void * p )
    41 {
    42     if( p )
    43         free( p );
    44 }
     32/* We may try to allocate and free tables of size 0.
     33   Quick and dirty way to handle it... */
    4534#define malloc tr_malloc
    4635#define free   tr_free
  • branches/file_selection/libtransmission/makemeta.c

    r2104 r2107  
    3535#include "bencode.h"
    3636#include "makemeta.h"
     37#include "platform.h" /* threads, locks */
     38#include "shared.h" /* shared lock */
    3739#include "version.h"
    3840
     
    133135}
    134136
    135 meta_info_builder_t*
    136 tr_metaInfoBuilderCreate( const char * topFile )
     137tr_metainfo_builder_t*
     138tr_metaInfoBuilderCreate( tr_handle_t * handle, const char * topFile )
    137139{
    138140    size_t i;
    139141    struct FileList * files;
    140142    const struct FileList * walk;
    141     meta_info_builder_t * ret = calloc( 1, sizeof(meta_info_builder_t) );
     143    tr_metainfo_builder_t * ret = calloc( 1, sizeof(tr_metainfo_builder_t) );
    142144    ret->top = tr_strdup( topFile );
     145    ret->handle = handle;
    143146
    144147    if (1) {
     
    186189
    187190void
    188 tr_metaInfoBuilderFree( meta_info_builder_t * builder )
     191tr_metaInfoBuilderFree( tr_metainfo_builder_t * builder )
    189192{
    190193    size_t i;
    191194
    192195    for( i=0; i<builder->fileCount; ++i )
    193         free( builder->files[i] );
    194     free( builder->top );
    195     free( builder );
     196        tr_free( builder->files[i] );
     197    tr_free( builder->top );
     198    tr_free( builder->comment );
     199    tr_free( builder->announce );
     200    tr_free( builder->outputFile );
     201    tr_free( builder );
    196202}
    197203
     
    201207
    202208static uint8_t*
    203 getHashInfo ( const meta_info_builder_t  * builder,
    204               makemeta_progress_func       progress_func,
    205               void                       * progress_func_user_data,
     209getHashInfo ( const tr_metainfo_builder_t  * builder,
    206210              int                        * setmeCount )
    207211{
    208212    size_t i;
    209     int abort = 0;;
    210213    tr_torrent_t t;
    211214    uint8_t *ret, *walk;
     
    231234    walk = ret;
    232235
    233     /* FIXME: call the periodically while getting the SHA1 sums.
    234        this will take a little tweaking to ioRecalculateHash,
    235        probably will get done Sunday or Monday */
    236     (progress_func)( builder, 0, &abort, progress_func_user_data );
    237 
     236    /* FIXME: check the abort flag */
    238237    for( i=0; i<(size_t)t.info.pieceCount; ++i ) {
    239238        tr_ioRecalculateHash( &t, i, walk );
     
    292291static void
    293292makeFilesList( benc_val_t                 * list,
    294                const meta_info_builder_t  * builder )
     293               const tr_metainfo_builder_t  * builder )
    295294{
    296295    size_t i = 0;
     
    313312static void
    314313makeInfoDict ( benc_val_t                 * dict,
    315                const meta_info_builder_t  * builder,
    316                makemeta_progress_func       progress_func,
    317                void                       * progress_func_user_data,
    318                int                          isPrivate )
     314               const tr_metainfo_builder_t  * builder )
    319315{
    320316    uint8_t * pch;
     
    332328    tr_bencInitInt( val, builder->pieceSize );
    333329
    334     pch = getHashInfo( builder,
    335                        progress_func,
    336                        progress_func_user_data,
    337                        &pieceCount );
     330    pch = getHashInfo( builder, &pieceCount );
    338331    val = tr_bencDictAdd( dict, "pieces" );
    339332    tr_bencInitStr( val, pch, SHA_DIGEST_LENGTH * pieceCount, 0 );
     
    352345
    353346    val = tr_bencDictAdd( dict, "private" );
    354     tr_bencInitInt( val, isPrivate ? 1 : 0 );
    355 }
    356 
    357 /* if outputFile is NULL, builder->top + ".torrent" is used */
    358 int
    359 tr_makeMetaInfo( const meta_info_builder_t  * builder,
    360                  makemeta_progress_func       progress_func,
    361                  void                       * progress_func_user_data,
    362                  const char                 * outputFile,
    363                  const char                 * announce,
    364                  const char                 * comment,
    365                  int                          isPrivate )
     347    tr_bencInitInt( val, builder->isPrivate ? 1 : 0 );
     348}
     349
     350static void tr_realMakeMetaInfo ( tr_metainfo_builder_t * builder )
    366351{
    367352    int n = 5;
     
    369354
    370355    tr_bencInit ( &top, TYPE_DICT );
    371     if ( comment && *comment ) ++n;
     356    if ( builder->comment && *builder->comment ) ++n;
    372357    tr_bencDictReserve( &top, n );
    373358
    374359        val = tr_bencDictAdd( &top, "announce" );
    375         tr_bencInitStrDup( val, announce );
     360        tr_bencInitStrDup( val, builder->announce );
    376361
    377362        val = tr_bencDictAdd( &top, "created by" );
     
    384369        tr_bencInitStrDup( val, "UTF-8" );
    385370
    386         if( comment && *comment ) {
     371        if( builder->comment && *builder->comment ) {
    387372            val = tr_bencDictAdd( &top, "comment" );
    388             tr_bencInitStrDup( val, comment );
     373            tr_bencInitStrDup( val, builder->comment );
    389374        }
    390375
     
    392377        tr_bencInit( val, TYPE_DICT );
    393378        tr_bencDictReserve( val, 666 );
    394         makeInfoDict( val, builder,
    395                       progress_func, progress_func_user_data,
    396                       isPrivate );
     379        makeInfoDict( val, builder );
    397380
    398381    /* debugging... */
     
    401384    /* save the file */
    402385    if (1) {
    403         char out[MAX_PATH_LENGTH];
    404         FILE * fp;
    405         char * pch;
    406         if ( !outputFile || !*outputFile ) {
    407             snprintf( out, sizeof(out), "%s.torrent", builder->top);
    408             outputFile = out;
    409         }
    410         fp = fopen( outputFile, "wb+" );
    411         pch = tr_bencSaveMalloc( &top, &n );
     386        FILE * fp = fopen( builder->outputFile, "wb+" );
     387        char * pch = tr_bencSaveMalloc( &top, &n );
    412388        fwrite( pch, n, 1, fp );
    413389        free( pch );
     
    417393    /* cleanup */
    418394    tr_bencFree( & top );
    419     return 0;
    420 }
     395    builder->isDone = 1;
     396    builder->failed = builder->abortFlag; /* FIXME: doesn't catch all failures */
     397}
     398
     399/***
     400****
     401****  A threaded builder queue
     402****
     403***/
     404
     405static tr_metainfo_builder_t * queue = NULL;
     406
     407static int workerIsRunning = 0;
     408
     409static tr_thread_t workerThread;
     410
     411static tr_lock_t* getQueueLock( tr_handle_t * h )
     412{
     413    static tr_lock_t * lock = NULL;
     414
     415    tr_sharedLock( h->shared );
     416    if( lock == NULL )
     417    {
     418        lock = calloc( 1, sizeof( tr_lock_t ) );
     419        tr_lockInit( lock );
     420    }
     421    tr_sharedUnlock( h->shared );
     422
     423    return lock;
     424}
     425
     426static void workerFunc( void * user_data )
     427{
     428    tr_handle_t * handle = (tr_handle_t *) user_data;
     429
     430    for (;;)
     431    {
     432        tr_metainfo_builder_t * builder = NULL;
     433
     434        /* find the next builder to process */
     435        tr_lock_t * lock = getQueueLock ( handle );
     436        tr_lockLock( lock );
     437        if( queue != NULL ) {
     438            builder = queue;
     439            queue = queue->nextBuilder;
     440        }
     441        tr_lockUnlock( lock );
     442
     443        /* if no builders, this worker thread is done */
     444        if( builder == NULL )
     445          break;
     446
     447        tr_realMakeMetaInfo ( builder );
     448    }
     449
     450    workerIsRunning = 0;
     451}
     452
     453void
     454tr_makeMetaInfo( tr_metainfo_builder_t  * builder,
     455                 const char             * outputFile,
     456                 const char             * announce,
     457                 const char             * comment,
     458                 int                      isPrivate )
     459{
     460    tr_lock_t * lock;
     461    builder->announce = tr_strdup( announce );
     462    builder->comment = tr_strdup( comment );
     463    builder->isPrivate = isPrivate;
     464    if( outputFile && *outputFile )
     465        builder->outputFile = tr_strdup( outputFile );
     466    else {
     467        char out[MAX_PATH_LENGTH];
     468        snprintf( out, sizeof(out), "%s.torrent", builder->top);
     469        builder->outputFile = tr_strdup( out );
     470    }
     471
     472    /* enqueue the builder */
     473    lock = getQueueLock ( builder->handle );
     474    tr_lockLock( lock );
     475    builder->nextBuilder = queue;
     476    queue = builder;
     477    if( !workerIsRunning ) {
     478        workerIsRunning = 1;
     479        tr_threadCreate( &workerThread, workerFunc, builder->handle, "makeMeta" );
     480    }
     481    tr_lockUnlock( lock );
     482}
     483
  • branches/file_selection/libtransmission/makemeta.h

    r2104 r2107  
    2626#define TR_MAKEMETA_H 1
    2727
    28 typedef struct
     28typedef struct tr_metainfo_builder_s
    2929{
     30    /**
     31    ***  These are set by tr_makeMetaInfo()
     32    ***  and cleaned up by tr_metaInfoBuilderFree()
     33    **/
     34
    3035    char * top;
    3136    char ** files;
     
    3641    size_t pieceCount;
    3742    int isSingleFile;
     43    tr_handle_t * handle;
     44
     45    /**
     46    ***  These are set inside tr_makeMetaInfo()
     47    ***  by copying the arguments passed to it,
     48    ***  and cleaned up by tr_metaInfoBuilderFree()
     49    **/
     50
     51    char * announce;
     52    char * comment;
     53    char * outputFile;
     54    int isPrivate;
     55
     56    /**
     57    ***  These are set inside tr_makeMetaInfo() so the client
     58    ***  can poll periodically to see what the status is.
     59    ***  The client can also set abortFlag to nonzero to
     60    ***  tell tr_makeMetaInfo() to abort and clean up after itself.
     61    **/
     62
     63    size_t pieceIndex;
     64    int abortFlag;
     65    int isDone;
     66    int failed; /* only meaningful if isDone is set */
     67
     68    /**
     69    ***  This is an implementation detail.
     70    ***  The client should never use these fields.
     71    **/
     72
     73    struct tr_metainfo_builder_s * nextBuilder;
    3874}
    39 meta_info_builder_t;
     75tr_metainfo_builder_t;
    4076
    41 meta_info_builder_t*
    42 tr_metaInfoBuilderCreate( const char * topFile );
    4377
    44 /**
    45  * Called periodically during the checksum generation.
    46  *
    47  * 'builder' is the builder passed into tr_makeMetaInfo
    48  * 'pieceIndex' is the current piece having a checksum generated
    49  * 'abortFlag' is an int pointer to set if the user wants to abort
    50  * 'userData' is the data passed into tr_makeMetaInfo
    51  */
    52 typedef
    53 void (*makemeta_progress_func)(const meta_info_builder_t * builder,
    54                                size_t                      pieceIndex,
    55                                int                       * abortFlag,
    56                                void                      * userData );
     78
     79
     80tr_metainfo_builder_t*
     81tr_metaInfoBuilderCreate( tr_handle_t  * handle,
     82                          const char   * topFile );
     83
     84void
     85tr_metaInfoBuilderFree( tr_metainfo_builder_t* );
    5786
    5887/**
    59  * Builds a .torrent metainfo file.
     88 * 'outputFile' if NULL, builder->top + ".torrent" will be used.
    6089 *
    61  * 'outputFile' if NULL, builder->top + ".torrent" will be used.
    62  * 'progress_func' a client-implemented callback function (see above)
    63  * 'progress_func_user_data' is passed back to the user in the progress func.
    64  *     It can be used to pass a resource or handle from tr_makeMetaInfo's
    65  *     caller to progress_func, or anything else.  Pass NULL if not needed.
     90 * This is actually done in a worker thread, not the main thread!
     91 * Otherwise the client's interface would lock up while this runs.
     92 *
     93 * It is the caller's responsibility to poll builder->isDone
     94 * from time to time!  When the worker thread sets that flag,
     95 * the caller must pass the builder to tr_metaInfoBuilderFree().
    6696 */
    67 int
    68 tr_makeMetaInfo( const meta_info_builder_t  * builder,
    69                  makemeta_progress_func       progress_func,
    70                  void                       * progress_func_user_data,
    71                  const char                 * outputFile,
    72                  const char                 * announce,
    73                  const char                 * comment,
    74                  int                          isPrivate );
     97void
     98tr_makeMetaInfo( tr_metainfo_builder_t  * builder,
     99                 const char             * outputFile,
     100                 const char             * announce,
     101                 const char             * comment,
     102                 int                      isPrivate );
    75103
    76104
    77 void
    78 tr_metaInfoBuilderFree( meta_info_builder_t* );
    79 
    80105#endif
  • branches/file_selection/libtransmission/utils.c

    r2093 r2107  
    390390}
    391391
     392void*
     393tr_malloc( size_t size )
     394{
     395    return size ? malloc( size ) : NULL;
     396}
     397
     398void tr_free( void * p )
     399{
     400    if( p )
     401        free( p );
     402}
     403
    392404/****
    393405*****
  • branches/file_selection/libtransmission/utils.h

    r2093 r2107  
    174174}
    175175
     176/***
     177****
     178***/
    176179
    177180char* tr_strdup( const char * pch );
     181
     182void* tr_malloc( size_t );
     183
     184void  tr_free( void* );
    178185
    179186/***
Note: See TracChangeset for help on using the changeset viewer.