/* Clean up all peers in current bucket, remove timedout pools and torrents */ static void * clean_worker( void * args ) { (void) args; while( 1 ) { int bucket = OT_BUCKET_COUNT; while( bucket-- ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); size_t toffs; int delta_torrentcount = 0; for( toffs=0; toffs<torrents_list->size; ++toffs ) { ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; if( clean_single_torrent( torrent ) ) { vector_remove_torrent( torrents_list, torrent ); --delta_torrentcount; --toffs; } } mutex_bucket_unlock( bucket, delta_torrentcount ); if( !g_opentracker_running ) return NULL; usleep( OT_CLEAN_SLEEP ); } stats_cleanup(); } return NULL; }
/* Clean up all peers in current bucket, remove timedout pools and torrents */ static void * clean_worker( void * args ) { #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: start"); #endif (void) args; while( 1 ) { int bucket = OT_BUCKET_COUNT; while( bucket-- ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); size_t toffs; int delta_torrentcount = 0; for( toffs=0; toffs<torrents_list->size; ++toffs ) { ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; if( clean_single_torrent( torrent ) ) { /* terasaur -- begin mod */ /* torrent->peer_list->peer_count = 0; torrent->peer_list->seed_count = 0; #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: calling ts_update_torrent_stats"); #endif ts_update_torrent_stats(torrent, 0); #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: after ts_update_torrent_stats"); #endif */ /* terasaur -- end mod */ vector_remove_torrent( torrents_list, torrent ); #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: after vector_remove_torrent"); #endif --delta_torrentcount; --toffs; } #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: after if clean_single_torrent block"); #endif } mutex_bucket_unlock( bucket, delta_torrentcount ); if( !g_opentracker_running ) return NULL; usleep( OT_CLEAN_SLEEP ); } #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: calling stats_cleanup"); #endif stats_cleanup(); } #ifdef _DEBUG ts_log_debug("ot_clean::clean_worker: returning"); #endif return NULL; }
static void * streamsync_worker( void * args ) { (void)args; while( 1 ) { int bucket; /* For each bucket... */ for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { /* Get exclusive access to that bucket */ ot_vector *torrents_list = mutex_bucket_lock( bucket ); size_t tor_offset, count_def = 0, count_one = 0, count_two = 0, count_peers = 0; size_t mem, mem_a = 0, mem_b = 0; uint8_t *ptr = 0, *ptr_a, *ptr_b, *ptr_c; if( !torrents_list->size ) goto unlock_continue; /* For each torrent in this bucket.. */ for( tor_offset=0; tor_offset<torrents_list->size; ++tor_offset ) { /* Address torrents members */ ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[tor_offset] ).peer_list; switch( peer_list->peer_count ) { case 2: count_two++; break; case 1: count_one++; break; case 0: break; default: count_def++; count_peers += peer_list->peer_count; } } /* Maximal memory requirement: max 3 blocks, max torrents * 20 + max peers * 7 */ mem = 3 * ( 1 + 1 + 2 ) + ( count_one + count_two ) * ( 19 + 1 ) + count_def * ( 19 + 8 ) + ( count_one + 2 * count_two + count_peers ) * 7; fprintf( stderr, "Mem: %zd\n", mem ); ptr = ptr_a = ptr_b = ptr_c = malloc( mem ); if( !ptr ) goto unlock_continue; if( count_one > 4 || !count_def ) { mem_a = 1 + 1 + 2 + count_one * ( 19 + 7 ); ptr_b += mem_a; ptr_c += mem_a; ptr_a[0] = 1; /* Offset 0: packet type 1 */ ptr_a[1] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 1: the shared prefix */ ptr_a[2] = count_one >> 8; ptr_a[3] = count_one & 255; ptr_a += 4; } else count_def += count_one; if( count_two > 4 || !count_def ) { mem_b = 1 + 1 + 2 + count_two * ( 19 + 14 ); ptr_c += mem_b; ptr_b[0] = 2; /* Offset 0: packet type 2 */ ptr_b[1] = (bucket << 8) >> OT_BUCKET_COUNT_BITS; /* Offset 1: the shared prefix */ ptr_b[2] = count_two >> 8; ptr_b[3] = count_two & 255; ptr_b += 4; } else
static size_t stats_slash24s_txt( char *reply, size_t amount ) { stats_network_node *slash24s_network_counters_root = NULL; char *r=reply; int bucket; size_t i; for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); for( i=0; i<torrents_list->size; ++i ) { ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[i] ).peer_list; ot_vector *bucket_list = &peer_list->peers; int num_buckets = 1; if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { num_buckets = bucket_list->size; bucket_list = (ot_vector *)bucket_list->data; } while( num_buckets-- ) { ot_peer *peers = (ot_peer*)bucket_list->data; size_t numpeers = bucket_list->size; while( numpeers-- ) if( stat_increase_network_count( &slash24s_network_counters_root, 0, (uintptr_t)(peers++) ) ) goto bailout_unlock; ++bucket_list; } } mutex_bucket_unlock( bucket, 0 ); if( !g_opentracker_running ) goto bailout_error; } /* The tree is built. Now analyze */ r += stats_return_busy_networks( r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_MAXDEPTH ); r += stats_return_busy_networks( r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_LIMIT ); goto success; bailout_unlock: mutex_bucket_unlock( bucket, 0 ); bailout_error: r = reply; success: stats_shift_down_network_count( &slash24s_network_counters_root, 0, sizeof(int)*8-1 ); return r-reply; }
static void clean_make() { int bucket; for( bucket = OT_BUCKET_COUNT - 1; bucket >= 0; --bucket ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); size_t toffs; for( toffs=0; toffs<torrents_list->size; ++toffs ) { ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + toffs; if( clean_single_torrent( torrent ) ) { vector_remove_torrent( torrents_list, torrent ); --toffs; continue; } } mutex_bucket_unlock( bucket ); } }
/* Fetches stats from tracker */ size_t stats_top_txt( char * reply, int amount ) { size_t j; ot_record top100s[100], top100c[100]; char *r = reply, hex_out[42]; int idx, bucket; if( amount > 100 ) amount = 100; byte_zero( top100s, sizeof( top100s ) ); byte_zero( top100c, sizeof( top100c ) ); for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); for( j=0; j<torrents_list->size; ++j ) { ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; int idx = amount - 1; while( (idx >= 0) && ( peer_list->peer_count > top100c[idx].val ) ) --idx; if ( idx++ != amount - 1 ) { memmove( top100c + idx + 1, top100c + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); top100c[idx].val = peer_list->peer_count; top100c[idx].torrent = (ot_torrent*)(torrents_list->data) + j; } idx = amount - 1; while( (idx >= 0) && ( peer_list->seed_count > top100s[idx].val ) ) --idx; if ( idx++ != amount - 1 ) { memmove( top100s + idx + 1, top100s + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); top100s[idx].val = peer_list->seed_count; top100s[idx].torrent = (ot_torrent*)(torrents_list->data) + j; } } mutex_bucket_unlock( bucket, 0 ); if( !g_opentracker_running ) return 0; } r += sprintf( r, "Top %d torrents by peers:\n", amount ); for( idx=0; idx<amount; ++idx ) if( top100c[idx].torrent ) r += sprintf( r, "\t%zd\t%s\n", top100c[idx].val, to_hex( hex_out, top100c[idx].torrent->hash) ); r += sprintf( r, "Top %d torrents by seeds:\n", amount ); for( idx=0; idx<amount; ++idx ) if( top100s[idx].torrent ) r += sprintf( r, "\t%zd\t%s\n", top100s[idx].val, to_hex( hex_out, top100s[idx].torrent->hash) ); return r - reply; }
static int persist_dump_make() { int bucket; size_t j; uint8_t c; FILE *fp; char tmpfile[256]; snprintf(tmpfile, 256, "temp-%u.odb", (unsigned int)g_now_seconds); LOG_ERR("Start write odb file:%s\n", tmpfile); fp = fopen(tmpfile, "w"); if (!fp) { LOG_ERR("%s: fopen odb file:%s failed: %s\n", __FUNCTION__, tmpfile, strerror(errno)); return -1; } /* write identifier and version */ if (fwrite(OT_DUMP_IDENTI_VERSION, OT_DUMP_IDENTI_VERSION_LEN, 1, fp) == 0) goto werr; /* Dump torrents and peers */ for(bucket=0; bucket < OT_BUCKET_COUNT; ++bucket ) { ot_vector *torrents_list = mutex_bucket_lock( bucket ); ot_torrent *torrents = (ot_torrent*)(torrents_list->data); for( j=0; j < torrents_list->size; ++j ) if( persist_dump_torrent( torrents + j, fp ) < 0 ) { mutex_bucket_unlock( bucket, 0 ); goto werr; } mutex_bucket_unlock( bucket, 0 ); } /* EOF opcode */ c = OT_DUMP_EOF; if (fwrite(&c, 1, 1, fp) != 1) goto werr; /* Make sure data will not remain on the OS's output buffers. */ fflush(fp); fsync(fileno(fp)); fclose(fp); /* Use RENAME to make sure the dump file is changed atomically * only if the generate dump file is ok. */ if (!g_persistfile) { g_persistfile = strdup("opentracker.odb"); } if (rename(tmpfile, g_persistfile) < 0) { unlink(tmpfile); return -1; } dump_dirty = 0; dump_lastsave = g_now_seconds; return 0; werr: LOG_ERR("%s: persist dump odb file:%s failed: %s\n", __FUNCTION__, tmpfile, strerror(errno)); fclose(fp); unlink(tmpfile); return -1; }