Add a lot of documentation for static functions in trackerlogic.c. Make vector_remove_peer use hysteresis only, if pool is expected to grow again. Remove too old torrents.

dynamic-accesslists
erdgeist 18 years ago
parent 11a1c070ae
commit 70a65f2842

@ -34,6 +34,11 @@ int g_check_blacklist = 1;
static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2; static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2;
#endif #endif
/* Converter function from memory to human readable hex strings
- definitely not thread safe!!!
*/
static char ths[2+2*20]="-";static char*to_hex(ot_byte*s){const char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;}
/* This function gives us a binary search that returns a pointer, even if /* This function gives us a binary search that returns a pointer, even if
no exact match is found. In that case it sets exactmatch 0 and gives no exact match is found. In that case it sets exactmatch 0 and gives
calling functions the chance to insert data calling functions the chance to insert data
@ -58,11 +63,13 @@ static void *binary_search( const void * const key, const void * base, const siz
return (void*)lookat; return (void*)lookat;
} }
/* Converter function from memory to human readable hex strings /* This is the generic insert operation for our vector type.
- definitely not thread safe!!! It tries to locate the object at "key" with size "member_size" by comparing its first "compare_size" bytes with
those of objects in vector. Our special "binary_search" function does that and either returns the match or a
pointer to where the object is to be inserted. vector_find_or_insert makes space for the object and copies it,
if it wasn't found in vector. Caller needs to check the passed "exactmatch" variable to see, whether an insert
took place. If resizing the vector failed, NULL is returned, else the pointer to the object in vector.
*/ */
char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;}
static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ) { static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ) {
ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch ); ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch );
@ -84,8 +91,15 @@ static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_
return match; return match;
} }
static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) { /* This is the non-generic delete from vector-operation specialized for peers in pools.
Set hysteresis == 0 if you expect the vector not to ever grow again.
It returns 0 if no peer was found (and thus not removed)
1 if a non-seeding peer was removed
2 if a seeding peer was removed
*/
static int vector_remove_peer( ot_vector *vector, ot_peer *peer, int hysteresis ) {
int exactmatch; int exactmatch;
size_t shrink_thresh = hysteresis ? OT_VECTOR_SHRINK_THRESH : OT_VECTOR_SHRINK_RATIO;
ot_peer *end = ((ot_peer*)vector->data) + vector->size; ot_peer *end = ((ot_peer*)vector->data) + vector->size;
ot_peer *match; ot_peer *match;
@ -95,7 +109,7 @@ static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
if( !exactmatch ) return 0; if( !exactmatch ) return 0;
exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1; exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1;
memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) ); memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );
if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { if( ( --vector->size * shrink_thresh < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
vector->space /= OT_VECTOR_SHRINK_RATIO; vector->space /= OT_VECTOR_SHRINK_RATIO;
vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) ); vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) );
} }
@ -117,14 +131,18 @@ static void free_peerlist( ot_peerlist *peer_list ) {
free( peer_list ); free( peer_list );
} }
/* This is the non-generic delete from vector-operation specialized for torrents in buckets.
it returns 0 if the hash wasn't found in vector
1 if the torrent was removed from vector
*/
static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) { static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
int exactmatch; int exactmatch;
ot_torrent *end = ((ot_torrent*)vector->data) + vector->size; ot_torrent *end = ((ot_torrent*)vector->data) + vector->size;
ot_torrent *match; ot_torrent *match;
if( !vector->size ) return 0; if( !vector->size ) return 0;
match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
if( !exactmatch ) return 0; if( !exactmatch ) return 0;
/* If this is being called after a unsuccessful malloc() for peer_list /* If this is being called after a unsuccessful malloc() for peer_list
@ -139,8 +157,11 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
return 1; return 1;
} }
/* Returns 1, if torrent is gone, 0 otherwise /* This function deallocates all timedouted pools and shifts all other pools
We expect NOW as a parameter since calling time() may be expensive*/ it Returns 1 if torrent itself has not seen an announce for more than OT_TORRENT_TIMEOUT time units
0 if torrent is not yet timed out
Note: We expect NOW as a parameter since calling time() may be expensive
*/
static int clean_peerlist( time_t time_now, ot_peerlist *peer_list ) { static int clean_peerlist( time_t time_now, ot_peerlist *peer_list ) {
int i, timedout = (int)( time_now - peer_list->base ); int i, timedout = (int)( time_now - peer_list->base );
@ -156,8 +177,11 @@ static int clean_peerlist( time_t time_now, ot_peerlist *peer_list ) {
memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout) ); memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout) );
byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout ); byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout );
peer_list->base = NOW; if( timedout == OT_POOLS_COUNT )
return timedout == OT_POOLS_COUNT; return time_now - peer_list->base > OT_TORRENT_TIMEOUT;
peer_list->base = time_now;
return 0;
} }
ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
@ -187,8 +211,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
/* Create a new torrent entry, then */ /* Create a new torrent entry, then */
memmove( &torrent->hash, hash, sizeof( ot_hash ) ); memmove( &torrent->hash, hash, sizeof( ot_hash ) );
torrent->peer_list = malloc( sizeof (ot_peerlist) ); if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
if( !torrent->peer_list ) {
vector_remove_torrent( torrents_list, hash ); vector_remove_torrent( torrents_list, hash );
return NULL; return NULL;
} }
@ -213,7 +236,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
torrent->peer_list->seed_count[0]++; torrent->peer_list->seed_count[0]++;
for( i=1; i<OT_POOLS_COUNT; ++i ) { for( i=1; i<OT_POOLS_COUNT; ++i ) {
switch( vector_remove_peer( &torrent->peer_list->peers[i], peer ) ) { switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) {
case 0: continue; case 0: continue;
case 2: torrent->peer_list->seed_count[i]--; case 2: torrent->peer_list->seed_count[i]--;
case 1: default: return torrent; case 1: default: return torrent;
@ -231,7 +254,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
} }
/* Compiles a list of random peers for a torrent /* Compiles a list of random peers for a torrent
* reply must have enough space to hold 24+6*amount bytes * reply must have enough space to hold 92+6*amount bytes
* Selector function can be anything, maybe test for seeds, etc. * Selector function can be anything, maybe test for seeds, etc.
* RANDOM may return huge values * RANDOM may return huge values
* does not yet check not to return self * does not yet check not to return self
@ -349,7 +372,7 @@ size_t return_memstat_for_tracker( char **reply ) {
if( !( r = *reply = malloc( 256*32 + (43+OT_POOLS_COUNT*32)*torrent_count ) ) ) return 0; if( !( r = *reply = malloc( 256*32 + (43+OT_POOLS_COUNT*32)*torrent_count ) ) ) return 0;
for( i=0; i<256; ++i ) for( i=0; i<256; ++i )
r += sprintf( r, "%02X: %04X %04X\n", i, (ot_dword)all_torrents[i].size, (ot_dword)all_torrents[i].space ); r += sprintf( r, "%02X: %08X %08X\n", i, (unsigned int)all_torrents[i].size, (unsigned int)all_torrents[i].space );
for( i=0; i<256; ++i ) { for( i=0; i<256; ++i ) {
ot_vector *torrents_list = &all_torrents[i]; ot_vector *torrents_list = &all_torrents[i];
@ -359,7 +382,7 @@ size_t return_memstat_for_tracker( char **reply ) {
r += sprintf( r, "\n%s:\n", to_hex( (ot_byte*)hash ) ); r += sprintf( r, "\n%s:\n", to_hex( (ot_byte*)hash ) );
clean_peerlist( time_now, peer_list ); clean_peerlist( time_now, peer_list );
for( k=0; k<OT_POOLS_COUNT; ++k ) for( k=0; k<OT_POOLS_COUNT; ++k )
r += sprintf( r, "\t%04X %04X\n", peer_list->peers[k].size, peer_list->peers[k].space ); r += sprintf( r, "\t%04X %04X\n", ((unsigned int)peer_list->peers[k].size), (unsigned int)peer_list->peers[k].space );
} }
} }
@ -432,7 +455,13 @@ size_t return_stats_for_tracker( char *reply, int mode ) {
for( j=0; j<torrents_list->size; ++j ) { for( j=0; j<torrents_list->size; ++j ) {
ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
size_t local_peers = 0, local_seeds = 0; size_t local_peers = 0, local_seeds = 0;
clean_peerlist( time_now, peer_list );
if( clean_peerlist( time_now, peer_list ) ) {
ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash;
vector_remove_torrent( torrents_list->data, hash );
--j;
continue;
}
for( k=0; k<OT_POOLS_COUNT; ++k ) { for( k=0; k<OT_POOLS_COUNT; ++k ) {
local_peers += peer_list->peers[k].size; local_peers += peer_list->peers[k].size;
local_seeds += peer_list->seed_count[k]; local_seeds += peer_list->seed_count[k];
@ -480,15 +509,12 @@ void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
/* Maybe this does the job */ /* Maybe this does the job */
if( clean_peerlist( NOW, torrent->peer_list ) ) { if( clean_peerlist( NOW, torrent->peer_list ) ) {
#ifdef WANT_CLOSED_TRACKER
if( !g_closedtracker )
#endif
vector_remove_torrent( torrents_list, hash ); vector_remove_torrent( torrents_list, hash );
return; return;
} }
for( i=0; i<OT_POOLS_COUNT; ++i ) for( i=0; i<OT_POOLS_COUNT; ++i )
switch( vector_remove_peer( &torrent->peer_list->peers[i], peer ) ) { switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, i == 0 ) ) {
case 0: continue; case 0: continue;
case 2: torrent->peer_list->seed_count[i]--; case 2: torrent->peer_list->seed_count[i]--;
case 1: default: return; case 1: default: return;

Loading…
Cancel
Save