Changeset 237 for trunk/libtransmission


Ignore:
Timestamp:
Apr 22, 2006, 9:39:17 PM (16 years ago)
Author:
titer
Message:

Clean up, perform all DNS resolutions in a common thread. This should
fix the remaining issues with many open torrents

Location:
trunk/libtransmission
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/net.c

    r236 r237  
    2323#include "transmission.h"
    2424
     25/***********************************************************************
     26 * DNS resolution
     27 **********************************************************************/
     28
     29/***********************************************************************
     30 * tr_netResolve
     31 ***********************************************************************
     32 * Synchronous "resolution": only works with character strings
     33 * representing numbers expressed in the Internet standard `.' notation.
     34 * Returns a non-zero value if an error occurs.
     35 **********************************************************************/
     36int tr_netResolve( char * address, struct in_addr * addr )
     37{
     38    addr->s_addr = inet_addr( address );
     39    return ( addr->s_addr == 0xFFFFFFFF );
     40}
     41
     42/* TODO: Make this code reentrant */
     43static tr_thread_t  resolveThread;
     44static tr_lock_t    resolveLock;
     45static volatile int resolveDie;
     46static tr_resolve_t * resolveQueue;
     47
     48static void resolveRelease ( tr_resolve_t * );
     49static void resolveFunc    ( void * );
     50
     51struct tr_resolve_s
     52{
     53    int            status;
     54    char           * address;
     55    struct in_addr addr;
     56
     57    int            refcount;
     58    tr_resolve_t   * next;
     59};
     60
     61/***********************************************************************
     62 * tr_netResolveThreadInit
     63 ***********************************************************************
     64 * Initializes the static variables used for resolution and launch the
     65 * gethostbyname thread.
     66 **********************************************************************/
     67void tr_netResolveThreadInit()
     68{
     69    resolveDie   = 0;
     70    resolveQueue = NULL;
     71    tr_lockInit( &resolveLock );
     72    tr_threadCreate( &resolveThread, resolveFunc, NULL );
     73}
     74
     75/***********************************************************************
     76 * tr_netResolveThreadClose
     77 ***********************************************************************
     78 * Notices the gethostbyname thread that is should terminate. Doesn't
     79 * wait until it does, in case it is stuck in a resolution: we let it
     80 * die and clean itself up.
     81 **********************************************************************/
     82void tr_netResolveThreadClose()
     83{
     84    tr_lockLock( &resolveLock );
     85    resolveDie = 1;
     86    tr_lockUnlock( &resolveLock );
     87    tr_wait( 200 );
     88}
     89
     90/***********************************************************************
     91 * tr_netResolveInit
     92 ***********************************************************************
     93 * Adds an address to the resolution queue.
     94 **********************************************************************/
     95tr_resolve_t * tr_netResolveInit( char * address )
     96{
     97    tr_resolve_t * r;
     98
     99    r           = malloc( sizeof( tr_resolve_t ) );
     100    r->status   = TR_RESOLVE_WAIT;
     101    r->address  = strdup( address );
     102    r->refcount = 2;
     103    r->next     = NULL;
     104
     105    tr_lockLock( &resolveLock );
     106    if( !resolveQueue )
     107    {
     108        resolveQueue = r;
     109    }
     110    else
     111    {
     112        tr_resolve_t * iter;
     113        for( iter = resolveQueue; iter->next; iter = iter->next );
     114        iter->next = r;
     115    }
     116    tr_lockUnlock( &resolveLock );
     117
     118    return r;
     119}
     120
     121/***********************************************************************
     122 * tr_netResolvePulse
     123 ***********************************************************************
     124 * Checks the current status of a resolution.
     125 **********************************************************************/
     126int tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
     127{
     128    int ret;
     129
     130    tr_lockLock( &resolveLock );
     131    ret = r->status;
     132    if( ret == TR_RESOLVE_OK )
     133    {
     134        *addr = r->addr;
     135    }
     136    tr_lockUnlock( &resolveLock );
     137
     138    return ret;
     139}
     140
     141/***********************************************************************
     142 * tr_netResolveClose
     143 ***********************************************************************
     144 *
     145 **********************************************************************/
     146void tr_netResolveClose( tr_resolve_t * r )
     147{
     148    resolveRelease( r );
     149}
     150
     151/***********************************************************************
     152 * resolveRelease
     153 ***********************************************************************
     154 * The allocated tr_resolve_t structures should be freed when
     155 * tr_netResolveClose was called *and* it was removed from the queue.
     156 * This can happen in any order, so we use a refcount to know we can
     157 * take it out.
     158 **********************************************************************/
     159static void resolveRelease( tr_resolve_t * r )
     160{
     161    if( --r->refcount < 1 )
     162    {
     163        free( r->address );
     164        free( r );
     165    }
     166}
     167
     168/***********************************************************************
     169 * resolveFunc
     170 ***********************************************************************
     171 * Keeps waiting for addresses to resolve, and removes them from the
     172 * queue once resolution is done.
     173 **********************************************************************/
     174static void resolveFunc( void * unused )
     175{
     176    tr_resolve_t * r;
     177    struct hostent * host;
     178
     179    tr_dbg( "Resolve thread started" );
     180
     181    tr_lockLock( &resolveLock );
     182
     183    while( !resolveDie )
     184    {
     185        if( !( r = resolveQueue ) )
     186        {
     187            /* TODO: Use a condition wait */
     188            tr_lockUnlock( &resolveLock );
     189            tr_wait( 50 );
     190            tr_lockLock( &resolveLock );
     191            continue;
     192        }
     193
     194        /* Blocking resolution */
     195        tr_lockUnlock( &resolveLock );
     196        host = gethostbyname( r->address );
     197        tr_lockLock( &resolveLock );
     198
     199        if( host )
     200        {
     201            memcpy( &r->addr, host->h_addr, host->h_length );
     202            r->status = TR_RESOLVE_OK;
     203        }
     204        else
     205        {
     206            r->status = TR_RESOLVE_ERROR;
     207        }
     208       
     209        resolveQueue = r->next;
     210        resolveRelease( r );
     211    }
     212
     213    /* Clean up  */
     214    tr_lockUnlock( &resolveLock );
     215    tr_lockClose( &resolveLock );
     216    while( ( r = resolveQueue ) )
     217    {
     218        resolveQueue = r->next;
     219        resolveRelease( r );
     220    }
     221
     222    tr_dbg( "Resolve thread exited" );
     223}
     224
     225
     226/***********************************************************************
     227 * TCP sockets
     228 **********************************************************************/
     229
    25230static int makeSocketNonBlocking( int s )
    26231{
     
    59264}
    60265
    61 struct tr_resolve_s
    62 {
    63     int            status;
    64     char           * address;
    65     struct in_addr addr;
    66 
    67     tr_lock_t      lock;
    68     tr_thread_t    thread;
    69     int            orphan;
    70 };
    71 
    72 /* Hem, global variable. Initialized from tr_init(). */
    73 tr_lock_t gethostbynameLock;
    74 
    75 static void resolveFunc( void * _r )
    76 {
    77     tr_resolve_t * r = _r;
    78     struct hostent * host;
    79 
    80     tr_lockLock( &r->lock );
    81 
    82     r->addr.s_addr = inet_addr( r->address );
    83     if( r->addr.s_addr != 0xFFFFFFFF )
    84     {
    85         /* This was an IP address, no resolving required */
    86         r->status = TR_RESOLVE_OK;
    87         goto resolveDone;
    88     }
    89 
    90     tr_lockLock( &gethostbynameLock );
    91     tr_lockUnlock( &r->lock );
    92     host = gethostbyname( r->address );
    93     tr_lockLock( &r->lock );
    94     if( host )
    95     {
    96         memcpy( &r->addr, host->h_addr, host->h_length );
    97         r->status = TR_RESOLVE_OK;
    98     }
    99     else
    100     {
    101         r->status = TR_RESOLVE_ERROR;
    102     }
    103     tr_lockUnlock( &gethostbynameLock );
    104 
    105 resolveDone:
    106     if( r->orphan )
    107     {
    108         /* tr_netResolveClose was closed already. Free memory */
    109         tr_lockUnlock( &r->lock );
    110         tr_lockClose( &r->lock );
    111         free( r );
    112     }
    113     else
    114     {
    115         tr_lockUnlock( &r->lock );
    116     }
    117 }
    118 
    119 tr_resolve_t * tr_netResolveInit( char * address )
    120 {
    121     tr_resolve_t * r = malloc( sizeof( tr_resolve_t ) );
    122 
    123     r->status  = TR_RESOLVE_WAIT;
    124     r->address = address;
    125 
    126     tr_lockInit( &r->lock );
    127     tr_threadCreate( &r->thread, resolveFunc, r );
    128     r->orphan = 0;
    129 
    130     return r;
    131 }
    132 
    133 int tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
    134 {
    135     int ret;
    136 
    137     tr_lockLock( &r->lock );
    138     ret = r->status;
    139     if( ret == TR_RESOLVE_OK )
    140     {
    141         *addr = r->addr;
    142     }
    143     tr_lockUnlock( &r->lock );
    144 
    145     return ret;
    146 }
    147 
    148 void tr_netResolveClose( tr_resolve_t * r )
    149 {
    150     tr_lockLock( &r->lock );
    151     if( r->status == TR_RESOLVE_WAIT )
    152     {
    153         /* Let the thread die */
    154         r->orphan = 1;
    155         tr_lockUnlock( &r->lock );
    156         return;
    157     }
    158     tr_lockUnlock( &r->lock );
    159 
    160     /* Clean up */
    161     tr_threadJoin( &r->thread );
    162     tr_lockClose( &r->lock );
    163     free( r );
    164 }
    165 
    166 /* Blocking version */
    167 int tr_netResolve( char * address, struct in_addr * addr )
    168 {
    169     addr->s_addr = inet_addr( address );
    170     return ( addr->s_addr == 0xFFFFFFFF );
    171 }
    172 
    173266int tr_netOpen( struct in_addr addr, in_port_t port )
    174267{
  • trunk/libtransmission/net.h

    r236 r237  
    2121 *****************************************************************************/
    2222
     23
    2324/***********************************************************************
    2425 * DNS resolution
    2526 **********************************************************************/
    26 
    27 /* Synchronous version: only works with character strings representing
    28    numbers expressed in the Internet standard `.' notation */
    2927int tr_netResolve( char *, struct in_addr * );
    3028
    31 /* Asynchronous version */
    3229#define TR_RESOLVE_WAIT  0
    3330#define TR_RESOLVE_ERROR 1
    3431#define TR_RESOLVE_OK    2
    3532typedef struct tr_resolve_s tr_resolve_t;
     33void           tr_netResolveThreadInit();
     34void           tr_netResolveThreadClose();
    3635tr_resolve_t * tr_netResolveInit( char * );
    3736int            tr_netResolvePulse( tr_resolve_t *, struct in_addr * );
  • trunk/libtransmission/transmission.c

    r219 r237  
    3131static void acceptStop( tr_handle_t * h );
    3232
    33 /* Used in tr_netResolve */
    34 extern tr_lock_t gethostbynameLock;
    35 
    3633/***********************************************************************
    3734 * tr_init
     
    4441    int           i, r;
    4542
    46     tr_lockInit( &gethostbynameLock );
     43    tr_netResolveThreadInit();
    4744
    4845    h = calloc( sizeof( tr_handle_t ), 1 );
     
    541538    free( h );
    542539
    543     tr_lockClose( &gethostbynameLock );
     540    tr_netResolveThreadClose();
    544541}
    545542
Note: See TracChangeset for help on using the changeset viewer.