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 ); |