Changeset 6922


Ignore:
Timestamp:
Oct 18, 2008, 12:20:37 AM (13 years ago)
Author:
charles
Message:

<bullwinkle>this time for sure!</bullwinkle>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/web.c

    r6921 r6922  
    2323#include "web.h"
    2424
    25 #define MAX_CONCURRENT_TASKS 16
    26 
    27 #if LIBCURL_VERSION_NUM < 0x071003
    28 #define curl_multi_socket_action(m,fd,mask,i) curl_multi_socket((m),(fd),(i))
    29 #endif
    30 
    31 #define DEFAULT_TIMER_MSEC 2000
     25#define MAX_CONCURRENT_TASKS 24
     26
     27#define DEFAULT_TIMER_MSEC 2500
    3228
    3329#define dbgmsg( ... )  tr_deepLog( __FILE__, __LINE__, "web", __VA_ARGS__ )
     
    3632struct tr_web
    3733{
    38     unsigned int dying : 1;
     34    unsigned int closing : 1;
    3935    int prev_running;
    4036    int still_running;
     
    5955    tr_web_done_func * done_func;
    6056    void * done_func_user_data;
    61     long timer_ms;
    6257};
    6358
     
    119114        curl_easy_setopt( easy, CURLOPT_SSL_VERIFYHOST, 0 );
    120115        curl_easy_setopt( easy, CURLOPT_SSL_VERIFYPEER, 0 );
    121         //curl_easy_setopt( easy, CURLOPT_FORBID_REUSE, 1 );
    122116        curl_easy_setopt( easy, CURLOPT_NOSIGNAL, 1 );
    123117        curl_easy_setopt( easy, CURLOPT_FOLLOWLOCATION, 1 );
     
    172166
    173167static void
    174 webDestroy( tr_web * web )
    175 {
    176     timeout_del( &web->timer_event );
    177     curl_multi_cleanup( web->multi );
    178     tr_free( web );
    179 }
    180 
    181 /* note: this function can free the tr_web if it's been flagged for deletion
    182    and there are no more tasks remaining.  so, callers need to make sure to
    183    not reference their g pointer after calling this function */
    184 static void
    185 check_run_count( tr_web * g )
    186 {
    187     int added_from_queue = FALSE;
    188 
    189     dbgmsg( "check_run_count: prev_running %d, still_running %d",
    190             g->prev_running, g->still_running );
    191 
    192     if( 1 )
     168remove_finished_tasks( tr_web * g )
     169{
     170
     171    if( g->prev_running != g->still_running )
    193172    {
    194         CURLMsg * msg;
    195         int msgs_left;
    196173        CURL * easy;
    197         CURLcode res;
    198 
    199         do{
     174
     175        do
     176        {
     177            CURLMsg * msg;
     178            int msgs_left;
     179            CURLcode res;
     180
    200181            easy = NULL;
    201182            while(( msg = curl_multi_info_read( g->multi, &msgs_left ))) {
     
    206187                }
    207188            }
     189
    208190            if( easy ) {
    209191                long code;
     
    215197                finish_task( task, code );
    216198            }
    217         } while ( easy );
    218     }
    219 
    220     g->prev_running = g->still_running;
    221 
    222 dbgmsg( "--> still running: %d ... max: %d ... queue size: %d", g->still_running, MAX_CONCURRENT_TASKS, tr_list_size( g->easy_queue ) );
    223 
     199        }
     200        while ( easy );
     201
     202        g->prev_running = g->still_running;
     203    }
     204}
     205
     206static void
     207stop_timer( tr_web* g )
     208{
     209    if( evtimer_pending( &g->timer_event, NULL ) )
     210    {
     211        dbgmsg( "deleting the pending global timer" );
     212        evtimer_del( &g->timer_event );
     213    }
     214}
     215
     216static void
     217restart_timer( tr_web * g )
     218{
     219    struct timeval timeout;
     220    stop_timer( g );
     221    dbgmsg( "adding a timeout for %ld seconds from now", g->timer_ms/1000l );
     222    tr_timevalMsec( g->timer_ms, &timeout );
     223    timeout_add( &g->timer_event, &timeout );
     224}
     225
     226static void
     227add_tasks_from_queue( tr_web * g )
     228{
    224229    while( ( g->still_running < MAX_CONCURRENT_TASKS )
    225230        && ( tr_list_size( g->easy_queue ) > 0 ) )
     
    229234        {
    230235            const CURLMcode rc = curl_multi_add_handle( g->multi, easy );
    231             if( rc != CURLM_OK ) {
     236            if( rc != CURLM_OK )
    232237                tr_err( "%s", curl_multi_strerror( rc ) );
    233             } else {
     238            else {
    234239                dbgmsg( "pumped a task out of the curl queue... %d remain", tr_list_size( g->easy_queue ) );
    235                 added_from_queue = TRUE;
    236240                ++g->still_running;
    237241            }
    238242        }
    239243    }
    240 
    241     if( !added_from_queue )
    242     {
    243         if( g->still_running <= 0 ) {
    244             if( evtimer_pending( &g->timer_event, NULL ) ) {
    245                 dbgmsg( "deleting the pending global timer" );
    246                 evtimer_del( &g->timer_event );
    247             }
     244}
     245
     246static void
     247webDestroy( tr_web * web )
     248{
     249    stop_timer( web );
     250    curl_multi_cleanup( web->multi );
     251    tr_free( web );
     252}
     253
     254/* note: this function can free the tr_web if it's been flagged for deletion
     255   and there are no more tasks remaining.  so, callers need to make sure to
     256   not reference their g pointer after calling this function */
     257static void
     258tr_multi_socket_action( tr_web * g, int fd, int mask )
     259{
     260    int closed = FALSE;
     261    CURLMcode rc;
     262
     263    dbgmsg( "check_run_count: prev_running %d, still_running %d",
     264            g->prev_running, g->still_running );
     265
     266    /* invoke libcurl's processing */
     267    do {
     268        dbgmsg( "event_cb calling socket_action fd %d, mask %d", fd, mask );
     269        rc = curl_multi_socket_action( g->multi, fd, mask, &g->still_running );
     270        dbgmsg( "event_cb(): still_running is %d", g->still_running );
     271    } while( rc == CURLM_CALL_MULTI_PERFORM );
     272    if( rc != CURLM_OK )
     273        tr_err( "%s", curl_multi_strerror( rc ) );
     274
     275    remove_finished_tasks( g );
     276
     277    add_tasks_from_queue( g );
     278
     279    if( !g->still_running ) {
     280        stop_timer( g );
     281        if( g->closing ) {
     282            webDestroy( g );
     283            closed = TRUE;
    248284        }
    249 
    250         if( g->dying && ( g->still_running < 1 ) ) {
    251             dbgmsg( "destroying the web global now that all the tasks are done" );
    252             webDestroy( g );
    253         }
    254     }
    255 }
    256 
    257 
    258 static void
    259 reset_timer( tr_web * g )
    260 {
    261     struct timeval timeout;
    262 
    263     if( evtimer_pending( &g->timer_event, NULL ) )
    264         evtimer_del( &g->timer_event );
    265 
    266     dbgmsg( "adding a timeout for %ld seconds from now", g->timer_ms/1000l );
    267     tr_timevalMsec( g->timer_ms, &timeout );
    268     timeout_add( &g->timer_event, &timeout );
     285    }
     286
     287    if( !closed )
     288        restart_timer( g );
    269289}
    270290
    271291/* libevent says that sock is ready to be processed, so wake up libcurl */
    272292static void
    273 event_cb( int fd, short kind, void * vg )
    274 {
    275     tr_web * g = vg;
    276     CURLMcode rc;
    277     int error = 0;
     293event_cb( int fd, short kind, void * g )
     294{
     295    int error;
    278296    int mask;
    279     socklen_t errsz = sizeof( error );
    280 
     297    socklen_t errsz;
     298
     299    error = 0;
     300    errsz = sizeof( error );
    281301    getsockopt( fd, SOL_SOCKET, SO_ERROR, &error, &errsz );
    282302    if( error )
     
    288308    }
    289309
    290     do {
    291         dbgmsg( "event_cb calling socket_action fd %d, mask %d", fd, mask );
    292         rc = curl_multi_socket_action( g->multi, fd, mask, &g->still_running );
    293         dbgmsg( "event_cb(): still_running is %d", g->still_running );
    294     } while( rc == CURLM_CALL_MULTI_PERFORM );
    295     if( rc != CURLM_OK )
    296         tr_err( "%s", curl_multi_strerror( rc ) );
    297 
    298     reset_timer( g );
    299     check_run_count( g );
     310    tr_multi_socket_action( g, fd, mask );
    300311}
    301312
    302313/* libevent says that timer_ms have passed, so wake up libcurl */
    303314static void
    304 timer_cb( int socket UNUSED, short action UNUSED, void * vg )
    305 {
    306     tr_web * g = vg;
    307     CURLMcode rc;
     315timer_cb( int socket UNUSED, short action UNUSED, void * g )
     316{
    308317    dbgmsg( "libevent timer is done" );
    309 
    310     do {
    311         dbgmsg( "timer_cb calling CURL_SOCKET_TIMEOUT" );
    312         rc = curl_multi_socket_action( g->multi, CURL_SOCKET_TIMEOUT, 0,
    313                                        &g->still_running );
    314         dbgmsg( "timer_cb(): still_running is %d", g->still_running );
    315     } while( rc == CURLM_CALL_MULTI_PERFORM );
    316 
    317     if( rc != CURLM_OK )
    318         tr_err( "%s", curl_multi_strerror( rc ) );
    319 
    320     reset_timer( g );
    321     check_run_count( g );
     318    tr_multi_socket_action( g, CURL_SOCKET_TIMEOUT, 0 );
    322319}
    323320
     
    340337{
    341338    const int kind = EV_PERSIST
    342                    | (action & CURL_POLL_IN ? EV_READ : 0)
    343                    | (action & CURL_POLL_OUT ? EV_WRITE : 0);
     339                   | (( action & CURL_POLL_IN ) ? EV_READ : 0 )
     340                   | (( action & CURL_POLL_OUT ) ? EV_WRITE : 0 );
    344341    dbgmsg( "setsock: fd is %d, curl action is %d, libevent action is %d", sockfd, action, kind );
    345342    if( f->evset )
     
    384381
    385382
    386 /* from libcurl documentation: "The timeout value returned in the long timeout
    387    points to, is in number of milliseconds at this very moment. If 0, it means
    388    you should proceed immediately without waiting for anything. If it
    389    returns -1, there's no timeout at all set.  Note: if libcurl returns a -1
    390    timeout here, it just means that libcurl currently has no stored timeout
    391    value. You must not wait too long (more than a few seconds perhaps) before
    392    you call curl_multi_perform() again."  */
     383/* from libcurl documentation: "If 0, it means you should proceed immediately
     384 * without waiting for anything. If it returns -1, there's no timeout at all
     385 * set ... (but) you must not wait too long (more than a few seconds perhaps)
     386 * before you call curl_multi_perform() again."  */
    393387static void
    394388multi_timer_cb( CURLM *multi UNUSED, long timer_ms, void * g )
     
    399393        timer_ms = DEFAULT_TIMER_MSEC;
    400394    }
    401     reset_timer( g );
     395    restart_timer( g );
    402396}
    403397
     
    449443    web->multi = curl_multi_init( );
    450444    web->session = session;
    451     web->timer_ms = DEFAULT_TIMER_MSEC; /* default value to overwrite in multi_timer_cb() */
     445    web->timer_ms = DEFAULT_TIMER_MSEC; /* overwritten by multi_timer_cb() */
    452446
    453447    timeout_set( &web->timer_event, timer_cb, web );
     
    468462        webDestroy( web );
    469463    else
    470         web->dying = 1;
     464        web->closing = 1;
    471465}
    472466
Note: See TracChangeset for help on using the changeset viewer.