diff options
Diffstat (limited to 'ot_stats.c')
| -rw-r--r-- | ot_stats.c | 341 |
1 files changed, 180 insertions, 161 deletions
| @@ -1,7 +1,7 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> |
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. | 2 | It is considered beerware. Prost. Skol. Cheers or whatever. |
| 3 | 3 | ||
| 4 | $id$ */ | 4 | $id$ */ |
| 5 | 5 | ||
| 6 | /* System */ | 6 | /* System */ |
| 7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
| @@ -50,12 +50,13 @@ static unsigned long long ot_full_scrape_size = 0; | |||
| 50 | static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; | 50 | static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; |
| 51 | static unsigned long long ot_renewed[OT_PEER_TIMEOUT]; | 51 | static unsigned long long ot_renewed[OT_PEER_TIMEOUT]; |
| 52 | static unsigned long long ot_overall_sync_count; | 52 | static unsigned long long ot_overall_sync_count; |
| 53 | static unsigned long long ot_overall_stall_count; | ||
| 53 | 54 | ||
| 54 | static time_t ot_start_time; | 55 | static time_t ot_start_time; |
| 55 | 56 | ||
| 56 | #ifdef WANT_LOG_NETWORKS | 57 | #ifdef WANT_LOG_NETWORKS |
| 57 | #define STATS_NETWORK_NODE_BITWIDTH 8 | 58 | #define STATS_NETWORK_NODE_BITWIDTH 8 |
| 58 | #define STATS_NETWORK_NODE_MAXDEPTH 3 | 59 | #define STATS_NETWORK_NODE_MAXDEPTH 16 |
| 59 | 60 | ||
| 60 | #define STATS_NETWORK_NODE_BITMASK ((1<<STATS_NETWORK_NODE_BITWIDTH)-1) | 61 | #define STATS_NETWORK_NODE_BITMASK ((1<<STATS_NETWORK_NODE_BITWIDTH)-1) |
| 61 | #define STATS_NETWORK_NODE_COUNT (1<<STATS_NETWORK_NODE_BITWIDTH) | 62 | #define STATS_NETWORK_NODE_COUNT (1<<STATS_NETWORK_NODE_BITWIDTH) |
| @@ -68,19 +69,20 @@ union stats_network_node { | |||
| 68 | 69 | ||
| 69 | static stats_network_node *stats_network_counters_root = NULL; | 70 | static stats_network_node *stats_network_counters_root = NULL; |
| 70 | 71 | ||
| 71 | static int stat_increase_network_count( stats_network_node **node, int depth, uint32_t ip ) { | 72 | static int stat_increase_network_count( stats_network_node **node, int depth, uintptr_t ip ) { |
| 72 | int foo = ( ip >> ( 32 - STATS_NETWORK_NODE_BITWIDTH * ( ++depth ) ) ) & STATS_NETWORK_NODE_BITMASK; | 73 | ot_ip6 *_ip = (ot_ip6*)ip; |
| 73 | 74 | int foo = (*_ip)[depth]; | |
| 75 | |||
| 74 | if( !*node ) { | 76 | if( !*node ) { |
| 75 | *node = malloc( sizeof( stats_network_node ) ); | 77 | *node = malloc( sizeof( stats_network_node ) ); |
| 76 | if( !*node ) | 78 | if( !*node ) |
| 77 | return -1; | 79 | return -1; |
| 78 | memset( *node, 0, sizeof( stats_network_node ) ); | 80 | memset( *node, 0, sizeof( stats_network_node ) ); |
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) | 83 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) |
| 82 | return stat_increase_network_count( &(*node)->children[ foo ], depth, ip ); | 84 | return stat_increase_network_count( &(*node)->children[ foo ], depth, ip ); |
| 83 | 85 | ||
| 84 | (*node)->counters[ foo ]++; | 86 | (*node)->counters[ foo ]++; |
| 85 | return 0; | 87 | return 0; |
| 86 | } | 88 | } |
| @@ -88,40 +90,40 @@ static int stat_increase_network_count( stats_network_node **node, int depth, ui | |||
| 88 | static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) { | 90 | static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) { |
| 89 | int i, rest = 0; | 91 | int i, rest = 0; |
| 90 | if( !*node ) return 0; | 92 | if( !*node ) return 0; |
| 91 | 93 | ||
| 92 | if( ++depth == STATS_NETWORK_NODE_MAXDEPTH ) | 94 | if( ++depth == STATS_NETWORK_NODE_MAXDEPTH ) |
| 93 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | 95 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { |
| 94 | rest += ((*node)->counters[i]>>=shift); | 96 | rest += ((*node)->counters[i]>>=shift); |
| 95 | return rest; | 97 | return rest; |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | 100 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { |
| 99 | stats_network_node **childnode = &(*node)->children[i]; | 101 | stats_network_node **childnode = &(*node)->children[i]; |
| 100 | int rest_val; | 102 | int rest_val; |
| 101 | 103 | ||
| 102 | if( !*childnode ) continue; | 104 | if( !*childnode ) continue; |
| 103 | 105 | ||
| 104 | rest += rest_val = stats_shift_down_network_count( childnode, depth, shift ); | 106 | rest += rest_val = stats_shift_down_network_count( childnode, depth, shift ); |
| 105 | 107 | ||
| 106 | if( rest_val ) continue; | 108 | if( rest_val ) continue; |
| 107 | 109 | ||
| 108 | free( (*node)->children[i] ); | 110 | free( (*node)->children[i] ); |
| 109 | (*node)->children[i] = NULL; | 111 | (*node)->children[i] = NULL; |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | return rest; | 114 | return rest; |
| 113 | } | 115 | } |
| 114 | 116 | ||
| 115 | static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) { | 117 | static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) { |
| 116 | int i; | 118 | int i; |
| 117 | 119 | ||
| 118 | if( !node ) return; | 120 | if( !node ) return; |
| 119 | 121 | ||
| 120 | if( !depth++ ) { | 122 | if( !depth++ ) { |
| 121 | memset( scores, 0, sizeof( *scores ) * network_count ); | 123 | memset( scores, 0, sizeof( *scores ) * network_count ); |
| 122 | memset( networks, 0, sizeof( *networks ) * network_count ); | 124 | memset( networks, 0, sizeof( *networks ) * network_count ); |
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) { | 127 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) { |
| 126 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) | 128 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) |
| 127 | if( node->children[i] ) | 129 | if( node->children[i] ) |
| @@ -130,15 +132,15 @@ static void stats_get_highscore_networks( stats_network_node *node, int depth, u | |||
| 130 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | 132 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { |
| 131 | int j=1; | 133 | int j=1; |
| 132 | if( node->counters[i] <= scores[0] ) continue; | 134 | if( node->counters[i] <= scores[0] ) continue; |
| 133 | 135 | ||
| 134 | while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j; | 136 | while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j; |
| 135 | --j; | 137 | --j; |
| 136 | 138 | ||
| 137 | memcpy( scores, scores + 1, j * sizeof( *scores ) ); | 139 | memcpy( scores, scores + 1, j * sizeof( *scores ) ); |
| 138 | memcpy( networks, networks + 1, j * sizeof( *networks ) ); | 140 | memcpy( networks, networks + 1, j * sizeof( *networks ) ); |
| 139 | scores[ j ] = node->counters[ i ]; | 141 | scores[ j ] = node->counters[ i ]; |
| 140 | networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); | 142 | networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); |
| 141 | } | 143 | } |
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | static size_t stats_return_busy_networks( char * reply ) { | 146 | static size_t stats_return_busy_networks( char * reply ) { |
| @@ -146,17 +148,31 @@ static size_t stats_return_busy_networks( char * reply ) { | |||
| 146 | int scores[16]; | 148 | int scores[16]; |
| 147 | int i; | 149 | int i; |
| 148 | char * r = reply; | 150 | char * r = reply; |
| 149 | 151 | ||
| 150 | stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 ); | 152 | stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 ); |
| 151 | 153 | ||
| 152 | for( i=15; i>=0; --i) | 154 | for( i=15; i>=0; --i) |
| 153 | r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff ); | 155 | r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff ); |
| 154 | 156 | ||
| 155 | return r - reply; | 157 | return r - reply; |
| 156 | } | 158 | } |
| 157 | 159 | ||
| 158 | #endif | 160 | #endif |
| 159 | 161 | ||
| 162 | typedef struct { | ||
| 163 | unsigned long long torrent_count; | ||
| 164 | unsigned long long peer_count; | ||
| 165 | unsigned long long seed_count; | ||
| 166 | } torrent_stats; | ||
| 167 | |||
| 168 | static int torrent_statter( ot_torrent *torrent, uintptr_t data ) { | ||
| 169 | torrent_stats *stats = (torrent_stats*)data; | ||
| 170 | stats->torrent_count++; | ||
| 171 | stats->peer_count += torrent->peer_list->peer_count; | ||
| 172 | stats->seed_count += torrent->peer_list->seed_count; | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 160 | /* Converter function from memory to human readable hex strings */ | 176 | /* Converter function from memory to human readable hex strings */ |
| 161 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} | 177 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} |
| 162 | 178 | ||
| @@ -168,10 +184,10 @@ size_t stats_top10_txt( char * reply ) { | |||
| 168 | ot_record top10s[10], top10c[10]; | 184 | ot_record top10s[10], top10c[10]; |
| 169 | char *r = reply, hex_out[42]; | 185 | char *r = reply, hex_out[42]; |
| 170 | int idx, bucket; | 186 | int idx, bucket; |
| 171 | 187 | ||
| 172 | byte_zero( top10s, sizeof( top10s ) ); | 188 | byte_zero( top10s, sizeof( top10s ) ); |
| 173 | byte_zero( top10c, sizeof( top10c ) ); | 189 | byte_zero( top10c, sizeof( top10c ) ); |
| 174 | 190 | ||
| 175 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 191 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { |
| 176 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 192 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); |
| 177 | for( j=0; j<torrents_list->size; ++j ) { | 193 | for( j=0; j<torrents_list->size; ++j ) { |
| @@ -193,7 +209,7 @@ size_t stats_top10_txt( char * reply ) { | |||
| 193 | if( !g_opentracker_running ) | 209 | if( !g_opentracker_running ) |
| 194 | return 0; | 210 | return 0; |
| 195 | } | 211 | } |
| 196 | 212 | ||
| 197 | r += sprintf( r, "Top 10 torrents by peers:\n" ); | 213 | r += sprintf( r, "Top 10 torrents by peers:\n" ); |
| 198 | for( idx=0; idx<10; ++idx ) | 214 | for( idx=0; idx<10; ++idx ) |
| 199 | if( top10c[idx].torrent ) | 215 | if( top10c[idx].torrent ) |
| @@ -202,31 +218,31 @@ size_t stats_top10_txt( char * reply ) { | |||
| 202 | for( idx=0; idx<10; ++idx ) | 218 | for( idx=0; idx<10; ++idx ) |
| 203 | if( top10s[idx].torrent ) | 219 | if( top10s[idx].torrent ) |
| 204 | r += sprintf( r, "\t%zd\t%s\n", top10s[idx].val, to_hex( hex_out, top10s[idx].torrent->hash) ); | 220 | r += sprintf( r, "\t%zd\t%s\n", top10s[idx].val, to_hex( hex_out, top10s[idx].torrent->hash) ); |
| 205 | 221 | ||
| 206 | return r - reply; | 222 | return r - reply; |
| 207 | } | 223 | } |
| 208 | 224 | ||
| 209 | /* This function collects 4096 /24s in 4096 possible | 225 | /* This function collects 4096 /24s in 4096 possible |
| 210 | malloc blocks | 226 | malloc blocks |
| 211 | */ | 227 | */ |
| 212 | static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh ) { | 228 | static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh ) { |
| 213 | 229 | ||
| 214 | #define NUM_TOPBITS 12 | 230 | #define NUM_TOPBITS 12 |
| 215 | #define NUM_LOWBITS (24-NUM_TOPBITS) | 231 | #define NUM_LOWBITS (24-NUM_TOPBITS) |
| 216 | #define NUM_BUFS (1<<NUM_TOPBITS) | 232 | #define NUM_BUFS (1<<NUM_TOPBITS) |
| 217 | #define NUM_S24S (1<<NUM_LOWBITS) | 233 | #define NUM_S24S (1<<NUM_LOWBITS) |
| 218 | #define MSK_S24S (NUM_S24S-1) | 234 | #define MSK_S24S (NUM_S24S-1) |
| 219 | 235 | ||
| 220 | uint32_t *counts[ NUM_BUFS ]; | 236 | uint32_t *counts[ NUM_BUFS ]; |
| 221 | uint32_t slash24s[amount*2]; /* first dword amount, second dword subnet */ | 237 | uint32_t slash24s[amount*2]; /* first dword amount, second dword subnet */ |
| 222 | size_t i, j, k, l; | 238 | size_t i, j, k, l; |
| 223 | char *r = reply; | 239 | char *r = reply; |
| 224 | 240 | ||
| 225 | byte_zero( counts, sizeof( counts ) ); | 241 | byte_zero( counts, sizeof( counts ) ); |
| 226 | byte_zero( slash24s, amount * 2 * sizeof(uint32_t) ); | 242 | byte_zero( slash24s, amount * 2 * sizeof(uint32_t) ); |
| 227 | 243 | ||
| 228 | r += sprintf( r, "Stats for all /24s with more than %u announced torrents:\n\n", thresh ); | 244 | r += sprintf( r, "Stats for all /24s with more than %u announced torrents:\n\n", thresh ); |
| 229 | 245 | ||
| 230 | #if 0 | 246 | #if 0 |
| 231 | /* XXX: TOOD: Doesn't work yet with new peer storage model */ | 247 | /* XXX: TOOD: Doesn't work yet with new peer storage model */ |
| 232 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 248 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { |
| @@ -257,7 +273,7 @@ static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh ) | |||
| 257 | goto bailout_cleanup; | 273 | goto bailout_cleanup; |
| 258 | } | 274 | } |
| 259 | #endif | 275 | #endif |
| 260 | 276 | ||
| 261 | k = l = 0; /* Debug: count allocated bufs */ | 277 | k = l = 0; /* Debug: count allocated bufs */ |
| 262 | for( i=0; i < NUM_BUFS; ++i ) { | 278 | for( i=0; i < NUM_BUFS; ++i ) { |
| 263 | uint32_t *count = counts[i]; | 279 | uint32_t *count = counts[i]; |
| @@ -281,28 +297,28 @@ static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh ) | |||
| 281 | } | 297 | } |
| 282 | free( count ); | 298 | free( count ); |
| 283 | } | 299 | } |
| 284 | 300 | ||
| 285 | r += sprintf( r, "Allocated bufs: %zd, used s24s: %zd\n", k, l ); | 301 | r += sprintf( r, "Allocated bufs: %zd, used s24s: %zd\n", k, l ); |
| 286 | 302 | ||
| 287 | for( i=0; i < amount; ++i ) | 303 | for( i=0; i < amount; ++i ) |
| 288 | if( slash24s[ 2*i ] >= thresh ) { | 304 | if( slash24s[ 2*i ] >= thresh ) { |
| 289 | uint32_t ip = slash24s[ 2*i +1 ]; | 305 | uint32_t ip = slash24s[ 2*i +1 ]; |
| 290 | r += sprintf( r, "% 10ld %d.%d.%d.0/24\n", (long)slash24s[ 2*i ], (int)(ip >> 16), (int)(255 & ( ip >> 8 )), (int)(ip & 255) ); | 306 | r += sprintf( r, "% 10ld %d.%d.%d.0/24\n", (long)slash24s[ 2*i ], (int)(ip >> 16), (int)(255 & ( ip >> 8 )), (int)(ip & 255) ); |
| 291 | } | 307 | } |
| 292 | 308 | ||
| 293 | return r - reply; | 309 | return r - reply; |
| 294 | 310 | ||
| 295 | for( i=0; i < NUM_BUFS; ++i ) | 311 | for( i=0; i < NUM_BUFS; ++i ) |
| 296 | free( counts[i] ); | 312 | free( counts[i] ); |
| 297 | 313 | ||
| 298 | return 0; | 314 | return 0; |
| 299 | } | 315 | } |
| 300 | 316 | ||
| 301 | /* | 317 | /* |
| 302 | struct { | 318 | struct { |
| 303 | size_t size | 319 | size_t size |
| 304 | size_t space | 320 | size_t space |
| 305 | size_t count | 321 | size_t count |
| 306 | } | 322 | } |
| 307 | */ | 323 | */ |
| 308 | 324 | ||
| @@ -313,105 +329,95 @@ static unsigned long events_per_time( unsigned long long events, time_t t ) { | |||
| 313 | static size_t stats_connections_mrtg( char * reply ) { | 329 | static size_t stats_connections_mrtg( char * reply ) { |
| 314 | ot_time t = time( NULL ) - ot_start_time; | 330 | ot_time t = time( NULL ) - ot_start_time; |
| 315 | return sprintf( reply, | 331 | return sprintf( reply, |
| 316 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", | 332 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", |
| 317 | ot_overall_tcp_connections+ot_overall_udp_connections, | 333 | ot_overall_tcp_connections+ot_overall_udp_connections, |
| 318 | ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, | 334 | ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, |
| 319 | (int)t, | 335 | (int)t, |
| 320 | (int)(t / 3600), | 336 | (int)(t / 3600), |
| 321 | events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), | 337 | events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), |
| 322 | events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) | 338 | events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) |
| 323 | ); | 339 | ); |
| 324 | } | 340 | } |
| 325 | 341 | ||
| 326 | static size_t stats_udpconnections_mrtg( char * reply ) { | 342 | static size_t stats_udpconnections_mrtg( char * reply ) { |
| 327 | ot_time t = time( NULL ) - ot_start_time; | 343 | ot_time t = time( NULL ) - ot_start_time; |
| 328 | return sprintf( reply, | 344 | return sprintf( reply, |
| 329 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", | 345 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", |
| 330 | ot_overall_udp_connections, | 346 | ot_overall_udp_connections, |
| 331 | ot_overall_udp_successfulannounces+ot_overall_udp_connects, | 347 | ot_overall_udp_successfulannounces+ot_overall_udp_connects, |
| 332 | (int)t, | 348 | (int)t, |
| 333 | (int)(t / 3600), | 349 | (int)(t / 3600), |
| 334 | events_per_time( ot_overall_udp_connections, t ), | 350 | events_per_time( ot_overall_udp_connections, t ), |
| 335 | events_per_time( ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) | 351 | events_per_time( ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) |
| 336 | ); | 352 | ); |
| 337 | } | 353 | } |
| 338 | 354 | ||
| 339 | static size_t stats_tcpconnections_mrtg( char * reply ) { | 355 | static size_t stats_tcpconnections_mrtg( char * reply ) { |
| 340 | time_t t = time( NULL ) - ot_start_time; | 356 | time_t t = time( NULL ) - ot_start_time; |
| 341 | return sprintf( reply, | 357 | return sprintf( reply, |
| 342 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", | 358 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", |
| 343 | ot_overall_tcp_connections, | 359 | ot_overall_tcp_connections, |
| 344 | ot_overall_tcp_successfulannounces, | 360 | ot_overall_tcp_successfulannounces, |
| 345 | (int)t, | 361 | (int)t, |
| 346 | (int)(t / 3600), | 362 | (int)(t / 3600), |
| 347 | events_per_time( ot_overall_tcp_connections, t ), | 363 | events_per_time( ot_overall_tcp_connections, t ), |
| 348 | events_per_time( ot_overall_tcp_successfulannounces, t ) | 364 | events_per_time( ot_overall_tcp_successfulannounces, t ) |
| 349 | ); | 365 | ); |
| 350 | } | 366 | } |
| 351 | 367 | ||
| 352 | static size_t stats_scrape_mrtg( char * reply ) { | 368 | static size_t stats_scrape_mrtg( char * reply ) { |
| 353 | time_t t = time( NULL ) - ot_start_time; | 369 | time_t t = time( NULL ) - ot_start_time; |
| 354 | return sprintf( reply, | 370 | return sprintf( reply, |
| 355 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", | 371 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", |
| 356 | ot_overall_tcp_successfulscrapes, | 372 | ot_overall_tcp_successfulscrapes, |
| 357 | ot_overall_udp_successfulscrapes, | 373 | ot_overall_udp_successfulscrapes, |
| 358 | (int)t, | 374 | (int)t, |
| 359 | (int)(t / 3600), | 375 | (int)(t / 3600), |
| 360 | events_per_time( (ot_overall_tcp_successfulscrapes+ot_overall_udp_successfulscrapes), t ) | 376 | events_per_time( (ot_overall_tcp_successfulscrapes+ot_overall_udp_successfulscrapes), t ) |
| 361 | ); | 377 | ); |
| 362 | } | 378 | } |
| 363 | 379 | ||
| 364 | static size_t stats_fullscrapes_mrtg( char * reply ) { | 380 | static size_t stats_fullscrapes_mrtg( char * reply ) { |
| 365 | ot_time t = time( NULL ) - ot_start_time; | 381 | ot_time t = time( NULL ) - ot_start_time; |
| 366 | return sprintf( reply, | 382 | return sprintf( reply, |
| 367 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", | 383 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", |
| 368 | ot_full_scrape_count * 1000, | 384 | ot_full_scrape_count * 1000, |
| 369 | ot_full_scrape_size, | 385 | ot_full_scrape_size, |
| 370 | (int)t, | 386 | (int)t, |
| 371 | (int)(t / 3600), | 387 | (int)(t / 3600), |
| 372 | events_per_time( ot_full_scrape_count, t ), | 388 | events_per_time( ot_full_scrape_count, t ), |
| 373 | events_per_time( ot_full_scrape_size, t ) | 389 | events_per_time( ot_full_scrape_size, t ) |
| 374 | ); | 390 | ); |
| 375 | } | 391 | } |
| 376 | 392 | ||
| 377 | static size_t stats_peers_mrtg( char * reply ) { | 393 | static size_t stats_peers_mrtg( char * reply ) { |
| 378 | size_t torrent_count = 0, peer_count = 0, seed_count = 0, j; | 394 | torrent_stats stats = {0,0,0}; |
| 379 | int bucket; | 395 | |
| 380 | 396 | iterate_all_torrents( torrent_statter, (uintptr_t)&stats ); | |
| 381 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 397 | |
| 382 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 398 | return sprintf( reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", |
| 383 | torrent_count += torrents_list->size; | 399 | stats.peer_count, |
| 384 | for( j=0; j<torrents_list->size; ++j ) { | 400 | stats.seed_count, |
| 385 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 401 | stats.torrent_count |
| 386 | peer_count += peer_list->peer_count; seed_count += peer_list->seed_count; | 402 | ); |
| 387 | } | ||
| 388 | mutex_bucket_unlock( bucket, 0 ); | ||
| 389 | if( !g_opentracker_running ) | ||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", | ||
| 393 | peer_count, | ||
| 394 | seed_count, | ||
| 395 | torrent_count | ||
| 396 | ); | ||
| 397 | } | 403 | } |
| 398 | 404 | ||
| 399 | static size_t stats_startstop_mrtg( char * reply ) | 405 | static size_t stats_startstop_mrtg( char * reply ) |
| 400 | { | 406 | { |
| 401 | size_t torrent_count = mutex_get_torrent_count(); | 407 | size_t torrent_count = mutex_get_torrent_count(); |
| 402 | 408 | ||
| 403 | return sprintf( reply, "%zd\n%zd\nopentracker handling %zd torrents\nopentracker", | 409 | return sprintf( reply, "%zd\n%zd\nopentracker handling %zd torrents\nopentracker", |
| 404 | (size_t)0, | 410 | (size_t)0, |
| 405 | (size_t)0, | 411 | (size_t)0, |
| 406 | torrent_count | 412 | torrent_count |
| 407 | ); | 413 | ); |
| 408 | } | 414 | } |
| 409 | 415 | ||
| 410 | static size_t stats_toraddrem_mrtg( char * reply ) | 416 | static size_t stats_toraddrem_mrtg( char * reply ) |
| 411 | { | 417 | { |
| 412 | size_t peer_count = 0, j; | 418 | size_t peer_count = 0, j; |
| 413 | int bucket; | 419 | int bucket; |
| 414 | 420 | ||
| 415 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) | 421 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) |
| 416 | { | 422 | { |
| 417 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 423 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); |
| @@ -424,53 +430,63 @@ static size_t stats_toraddrem_mrtg( char * reply ) | |||
| 424 | if( !g_opentracker_running ) | 430 | if( !g_opentracker_running ) |
| 425 | return 0; | 431 | return 0; |
| 426 | } | 432 | } |
| 427 | 433 | ||
| 428 | return sprintf( reply, "%zd\n%zd\nopentracker handling %zd peers\nopentracker", | 434 | return sprintf( reply, "%zd\n%zd\nopentracker handling %zd peers\nopentracker", |
| 429 | (size_t)0, | 435 | (size_t)0, |
| 430 | (size_t)0, | 436 | (size_t)0, |
| 431 | peer_count | 437 | peer_count |
| 432 | ); | 438 | ); |
| 433 | } | 439 | } |
| 434 | 440 | ||
| 435 | static size_t stats_torrents_mrtg( char * reply ) | 441 | static size_t stats_torrents_mrtg( char * reply ) |
| 436 | { | 442 | { |
| 437 | size_t torrent_count = mutex_get_torrent_count(); | 443 | size_t torrent_count = mutex_get_torrent_count(); |
| 438 | 444 | ||
| 439 | return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", | 445 | return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", |
| 440 | torrent_count, | 446 | torrent_count, |
| 441 | (size_t)0, | 447 | (size_t)0, |
| 442 | torrent_count | 448 | torrent_count |
| 443 | ); | 449 | ); |
| 444 | } | 450 | } |
| 445 | 451 | ||
| 446 | static size_t stats_httperrors_txt ( char * reply ) { | 452 | static size_t stats_httperrors_txt ( char * reply ) { |
| 447 | return sprintf( reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", | 453 | return sprintf( reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", |
| 448 | ot_failed_request_counts[0], ot_failed_request_counts[1], ot_failed_request_counts[2], | 454 | ot_failed_request_counts[0], ot_failed_request_counts[1], ot_failed_request_counts[2], |
| 449 | ot_failed_request_counts[3], ot_failed_request_counts[4], ot_failed_request_counts[5], | 455 | ot_failed_request_counts[3], ot_failed_request_counts[4], ot_failed_request_counts[5], |
| 450 | ot_failed_request_counts[6] ); | 456 | ot_failed_request_counts[6] ); |
| 451 | } | 457 | } |
| 452 | 458 | ||
| 453 | static size_t stats_return_renew_bucket( char * reply ) { | 459 | static size_t stats_return_renew_bucket( char * reply ) { |
| 454 | char *r = reply; | 460 | char *r = reply; |
| 455 | int i; | 461 | int i; |
| 456 | 462 | ||
| 457 | for( i=0; i<OT_PEER_TIMEOUT; ++i ) | 463 | for( i=0; i<OT_PEER_TIMEOUT; ++i ) |
| 458 | r+=sprintf(r,"%02i %llu\n", i, ot_renewed[i] ); | 464 | r+=sprintf(r,"%02i %llu\n", i, ot_renewed[i] ); |
| 459 | return r - reply; | 465 | return r - reply; |
| 460 | } | 466 | } |
| 461 | 467 | ||
| 462 | static size_t stats_return_sync_mrtg( char * reply ) | 468 | static size_t stats_return_sync_mrtg( char * reply ) { |
| 463 | { | ||
| 464 | ot_time t = time( NULL ) - ot_start_time; | 469 | ot_time t = time( NULL ) - ot_start_time; |
| 465 | return sprintf( reply, | 470 | return sprintf( reply, |
| 466 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", | 471 | "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", |
| 467 | ot_overall_sync_count, | 472 | ot_overall_sync_count, |
| 468 | 0LL, | 473 | 0LL, |
| 469 | (int)t, | 474 | (int)t, |
| 470 | (int)(t / 3600), | 475 | (int)(t / 3600), |
| 471 | events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), | 476 | events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), |
| 472 | events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) | 477 | events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) |
| 473 | ); | 478 | ); |
| 479 | } | ||
| 480 | |||
| 481 | static size_t stats_return_everything( char * reply ) { | ||
| 482 | char * r = reply; | ||
| 483 | r += sprintf( r, "<stats>\n" ); | ||
| 484 | r += sprintf( r, " <uptime>%llu</uptime>\n", (unsigned long long)(time( NULL ) - ot_start_time) ); | ||
| 485 | r += sprintf( r, " <torrents>%zd</torrents>\n", mutex_get_torrent_count() ); | ||
| 486 | /* r += sprintf( r, " <peers>%llu</peers>\n", ); */ | ||
| 487 | |||
| 488 | r += sprintf( reply, "</stats>" ); | ||
| 489 | return r - reply; | ||
| 474 | } | 490 | } |
| 475 | 491 | ||
| 476 | extern const char | 492 | extern const char |
| @@ -480,9 +496,9 @@ extern const char | |||
| 480 | 496 | ||
| 481 | size_t stats_return_tracker_version( char *reply ) { | 497 | size_t stats_return_tracker_version( char *reply ) { |
| 482 | return sprintf( reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s", | 498 | return sprintf( reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s", |
| 483 | g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, | 499 | g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, |
| 484 | g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, | 500 | g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, |
| 485 | g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c ); | 501 | g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c ); |
| 486 | } | 502 | } |
| 487 | 503 | ||
| 488 | size_t return_stats_for_tracker( char *reply, int mode, int format ) { | 504 | size_t return_stats_for_tracker( char *reply, int mode, int format ) { |
| @@ -509,7 +525,7 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { | |||
| 509 | case TASK_STATS_RENEW: | 525 | case TASK_STATS_RENEW: |
| 510 | return stats_return_renew_bucket( reply ); | 526 | return stats_return_renew_bucket( reply ); |
| 511 | case TASK_STATS_SYNCS: | 527 | case TASK_STATS_SYNCS: |
| 512 | return stats_return_sync_mrtg( reply ); | 528 | return stats_return_sync_mrtg( reply ); |
| 513 | #ifdef WANT_LOG_NETWORKS | 529 | #ifdef WANT_LOG_NETWORKS |
| 514 | case TASK_STATS_BUSY_NETWORKS: | 530 | case TASK_STATS_BUSY_NETWORKS: |
| 515 | return stats_return_busy_networks( reply ); | 531 | return stats_return_busy_networks( reply ); |
| @@ -521,12 +537,12 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { | |||
| 521 | 537 | ||
| 522 | static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) { | 538 | static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) { |
| 523 | char *r; | 539 | char *r; |
| 524 | 540 | ||
| 525 | *iovec_entries = 0; | 541 | *iovec_entries = 0; |
| 526 | *iovector = NULL; | 542 | *iovector = NULL; |
| 527 | if( !( r = iovec_increase( iovec_entries, iovector, OT_STATS_TMPSIZE ) ) ) | 543 | if( !( r = iovec_increase( iovec_entries, iovector, OT_STATS_TMPSIZE ) ) ) |
| 528 | return; | 544 | return; |
| 529 | 545 | ||
| 530 | switch( mode & TASK_TASK_MASK ) { | 546 | switch( mode & TASK_TASK_MASK ) { |
| 531 | case TASK_STATS_TORRENTS: r += stats_torrents_mrtg( r ); break; | 547 | case TASK_STATS_TORRENTS: r += stats_torrents_mrtg( r ); break; |
| 532 | case TASK_STATS_PEERS: r += stats_peers_mrtg( r ); break; | 548 | case TASK_STATS_PEERS: r += stats_peers_mrtg( r ); break; |
| @@ -560,26 +576,26 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event | |||
| 560 | ot_full_scrape_size += event_data; | 576 | ot_full_scrape_size += event_data; |
| 561 | break; | 577 | break; |
| 562 | case EVENT_FULLSCRAPE_REQUEST: | 578 | case EVENT_FULLSCRAPE_REQUEST: |
| 563 | { | 579 | { |
| 564 | ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ | 580 | ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ |
| 565 | char _debug[512]; | 581 | char _debug[512]; |
| 566 | int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); | 582 | int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); |
| 567 | off += fmt_ip6( _debug+off, *ip ); | 583 | off += fmt_ip6( _debug+off, *ip ); |
| 568 | off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); | 584 | off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); |
| 569 | write( 2, _debug, off ); | 585 | write( 2, _debug, off ); |
| 570 | ot_full_scrape_request_count++; | 586 | ot_full_scrape_request_count++; |
| 571 | } | 587 | } |
| 572 | break; | 588 | break; |
| 573 | case EVENT_FULLSCRAPE_REQUEST_GZIP: | 589 | case EVENT_FULLSCRAPE_REQUEST_GZIP: |
| 574 | { | 590 | { |
| 575 | ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ | 591 | ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ |
| 576 | char _debug[512]; | 592 | char _debug[512]; |
| 577 | int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); | 593 | int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); |
| 578 | off += fmt_ip6(_debug+off, *ip ); | 594 | off += fmt_ip6(_debug+off, *ip ); |
| 579 | off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); | 595 | off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); |
| 580 | write( 2, _debug, off ); | 596 | write( 2, _debug, off ); |
| 581 | ot_full_scrape_request_count++; | 597 | ot_full_scrape_request_count++; |
| 582 | } | 598 | } |
| 583 | break; | 599 | break; |
| 584 | case EVENT_FAILED: | 600 | case EVENT_FAILED: |
| 585 | ot_failed_request_counts[event_data]++; | 601 | ot_failed_request_counts[event_data]++; |
| @@ -590,6 +606,9 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event | |||
| 590 | case EVENT_SYNC: | 606 | case EVENT_SYNC: |
| 591 | ot_overall_sync_count+=event_data; | 607 | ot_overall_sync_count+=event_data; |
| 592 | break; | 608 | break; |
| 609 | case EVENT_BUCKET_LOCKED: | ||
| 610 | ot_overall_stall_count++; | ||
| 611 | break; | ||
| 593 | default: | 612 | default: |
| 594 | break; | 613 | break; |
| 595 | } | 614 | } |
| @@ -598,9 +617,9 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event | |||
| 598 | static void * stats_worker( void * args ) { | 617 | static void * stats_worker( void * args ) { |
| 599 | int iovec_entries; | 618 | int iovec_entries; |
| 600 | struct iovec *iovector; | 619 | struct iovec *iovector; |
| 601 | 620 | ||
| 602 | args = args; | 621 | args = args; |
| 603 | 622 | ||
| 604 | while( 1 ) { | 623 | while( 1 ) { |
| 605 | ot_tasktype tasktype = TASK_STATS; | 624 | ot_tasktype tasktype = TASK_STATS; |
| 606 | ot_taskid taskid = mutex_workqueue_poptask( &tasktype ); | 625 | ot_taskid taskid = mutex_workqueue_poptask( &tasktype ); |
