Changeset 6414


Ignore:
Timestamp:
Jul 29, 2008, 12:51:07 AM (13 years ago)
Author:
charles
Message:

#1122: faster http processing

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/configure.ac

    r6368 r6414  
    1212
    1313OPENSSL_MINIMUM=0.9.4
    14 CURL_MINIMUM=7.15.0
     14CURL_MINIMUM=7.16.3
    1515GIO_MINIMUM=2.15.5
    1616GLIB_MINIMUM=2.6.0
  • trunk/libtransmission/web.c

    r6354 r6414  
    2121#include "utils.h"
    2222#include "web.h"
    23 
    24 #define CURL_CHECK_VERSION(major,minor,micro)    \
    25     (LIBCURL_VERSION_MAJOR > (major) || \
    26      (LIBCURL_VERSION_MAJOR == (major) && LIBCURL_VERSION_MINOR > (minor)) || \
    27      (LIBCURL_VERSION_MAJOR == (major) && LIBCURL_VERSION_MINOR == (minor) && \
    28       LIBCURL_VERSION_PATCH >= (micro)))
    29 
    30 #define PULSE_MSEC 500
    3123
    3224#define dbgmsg(fmt...) tr_deepLog( __FILE__, __LINE__, "web", ##fmt )
     
    9385}
    9486
    95 static void
    96 pump( tr_web * web )
    97 {
    98     int unused;
    99     CURLMcode rc;
    100     do {
    101         rc = curl_multi_perform( web->cm, &unused );
    102     } while( rc == CURLM_CALL_MULTI_PERFORM );
    103     if ( rc == CURLM_OK  )
    104         processCompletedTasks( web );
    105     else
    106         tr_err( "%s", curl_multi_strerror(rc) );
    107 }
    108 
    10987static size_t
    11088writeFunc( void * ptr, size_t size, size_t nmemb, void * task )
     
    11391    evbuffer_add( ((struct tr_web_task*)task)->response, ptr, byteCount );
    11492    return byteCount;
    115 }
    116 
    117 static void
    118 ensureTimerIsRunning( tr_web * web )
    119 {
    120     if( !web->running )
    121     {
    122         struct timeval tv = tr_timevalMsec( PULSE_MSEC );
    123         dbgmsg( "starting web timer" );
    124         web->running = 1;
    125         evtimer_add( &web->timer, &tv );
    126     }
    12793}
    12894
     
    151117        CURL * ch;
    152118
    153         ensureTimerIsRunning( web );
    154 
    155119        ++web->remain;
    156120        dbgmsg( "adding task #%lu [%s] (%d remain)", task->tag, task->url, web->remain );
    157121
    158122        ch = curl_easy_init( );
     123
     124        if( getenv( "TRANSMISSION_LIBCURL_VERBOSE" ) != 0 )
     125            curl_easy_setopt( ch, CURLOPT_VERBOSE, 1 );
    159126
    160127        if( !task->range && session->isProxyEnabled ) {
     
    225192}
    226193
    227 static void
    228 pulse( int socket UNUSED, short action UNUSED, void * vweb )
     194/* libevent says that sock is ready to be processed, so wake up libcurl */
     195static void
     196event_callback( int sock, short action, void * vweb )
    229197{
    230198    tr_web * web = vweb;
    231     assert( web->running );
    232 
    233     pump( web );
    234 
    235     evtimer_del( &web->timer );
    236 
    237     web->running = web->remain > 0;
    238 
    239     if( web->running ) {
    240         struct timeval tv = tr_timevalMsec( PULSE_MSEC );
    241         evtimer_add( &web->timer, &tv );
    242     } else if( web->dying ) {
    243         webDestroy( web );
    244     } else {
    245         dbgmsg( "stopping web timer" );
    246     }
     199    CURLMcode rc;
     200    int mask;
     201
     202#if 0
     203    static const char *strings[] = {
     204        "NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE",
     205        "READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL" };
     206     fprintf( stderr, "%s:%d (%s) event on socket %d (%s)\n",
     207              __FILE__, __LINE__, __FUNCTION__,
     208              sock, strings[action] );
     209#endif
     210
     211    mask = 0;
     212    if( action & EV_READ  ) mask |= CURL_CSELECT_IN;
     213    if( action & EV_WRITE ) mask |= CURL_CSELECT_OUT;
     214
     215    do
     216        rc = curl_multi_socket_action( web->cm, sock, mask, &web->remain );
     217    while( rc == CURLM_CALL_MULTI_PERFORM );
     218
     219    if ( rc != CURLM_OK  )
     220        tr_err( "%s (%d)", curl_multi_strerror(rc), (int)sock );
     221
     222    processCompletedTasks( web );
     223}
     224
     225/* libcurl wants us to tell it when sock is ready to be processed */
     226static int
     227socket_callback( CURL            * easy UNUSED,
     228                 curl_socket_t     sock,
     229                 int               action,
     230                 void            * vweb,
     231                 void            * assigndata )
     232{
     233    tr_web * web = vweb;
     234    int events = EV_PERSIST;
     235    struct event * ev = assigndata;
     236
     237    if( ev )
     238        event_del( ev );
     239    else {
     240        ev = tr_new0( struct event, 1 );
     241        curl_multi_assign( web->cm, sock, ev );
     242    }
     243
     244#if 0
     245    {
     246        static const char *actions[] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"};
     247        fprintf( stderr, "%s:%d (%s) callback on socket %d (%s)\n",
     248                 __FILE__, __LINE__, __FUNCTION__,
     249                 (int)sock, actions[action]);
     250    }
     251#endif
     252
     253    switch (action) {
     254        case CURL_POLL_IN: events |= EV_READ; break;
     255        case CURL_POLL_OUT: events |= EV_WRITE; break;
     256        case CURL_POLL_INOUT: events |= EV_READ|EV_WRITE; break;
     257        case CURL_POLL_REMOVE: tr_free( ev ); /* fallthrough */
     258        case CURL_POLL_NONE: return 0;
     259        default: tr_err( "Unknown socket action %d", action ); return -1;
     260    }
     261
     262    event_set( ev, sock, events, event_callback, web );
     263    event_add( ev, NULL );
     264    return 0;
     265}
     266
     267/* libevent says that timeout_ms have passed, so wake up libcurl */
     268static void
     269timeout_callback( int socket UNUSED, short action UNUSED, void * vweb )
     270{
     271    CURLMcode rc;
     272    tr_web * web = vweb;
     273
     274    do
     275        rc = curl_multi_socket( web->cm, CURL_SOCKET_TIMEOUT, &web->remain );
     276    while( rc == CURLM_CALL_MULTI_PERFORM );
     277
     278    if( rc != CURLM_OK )
     279        tr_err( "%s", curl_multi_strerror( rc ) );
     280
     281    processCompletedTasks( web );
     282}
     283
     284/* libcurl wants us to tell it when timeout_ms have passed */
     285static void
     286timer_callback( CURLM *multi UNUSED, long timeout_ms, void * vweb )
     287{
     288    tr_web * web = vweb;
     289    struct timeval timeout = tr_timevalMsec( timeout_ms );
     290    evtimer_add( &web->timer, &timeout );
    247291}
    248292
     
    266310    web->session = session;
    267311
    268     evtimer_set( &web->timer, pulse, web );
    269 #if CURL_CHECK_VERSION(7,16,3)
    270     curl_multi_setopt( web->cm, CURLMOPT_MAXCONNECTS, 10 );
    271 #endif
    272     pump( web );
     312    evtimer_set( &web->timer, timeout_callback, web );
     313    curl_multi_setopt( web->cm, CURLMOPT_SOCKETDATA, web );
     314    curl_multi_setopt( web->cm, CURLMOPT_SOCKETFUNCTION, socket_callback );
     315    curl_multi_setopt( web->cm, CURLMOPT_TIMERDATA, web );
     316    curl_multi_setopt( web->cm, CURLMOPT_TIMERFUNCTION, timer_callback );
    273317
    274318    return web;
Note: See TracChangeset for help on using the changeset viewer.