diff options
author | erdgeist <> | 2009-03-04 14:35:21 +0000 |
---|---|---|
committer | erdgeist <> | 2009-03-04 14:35:21 +0000 |
commit | 9297967f8523f1ac22bbac1823529b970a07cf56 (patch) | |
tree | 0a6bc2a2d3ac9d38e53079040c7057c779e30f15 | |
parent | 72a1564ca14392cc2e1d044554c6e86a0eda9409 (diff) |
Add a stat option the count bucket stalls
Add an iterator for all torrents. It's slower but for stats it's okay.
Move some stats collection stuff to the new iterator. More to come.
Start a "report all stats" page.
Start fixing the code to identify "busy" networks.
Add the concept of hosts allowed to proxy.
Add a parser for the X-Forwarded-For: HTTP header.
Clean up HTTP Header handling code. (Remove some left overs of now vanished sync code).
-rw-r--r-- | opentracker.c | 11 | ||||
-rw-r--r-- | ot_accesslist.c | 1 | ||||
-rw-r--r-- | ot_accesslist.h | 3 | ||||
-rw-r--r-- | ot_http.c | 43 | ||||
-rw-r--r-- | ot_mutex.c | 5 | ||||
-rw-r--r-- | ot_stats.c | 341 | ||||
-rw-r--r-- | ot_stats.h | 3 | ||||
-rw-r--r-- | trackerlogic.c | 19 | ||||
-rw-r--r-- | trackerlogic.h | 3 |
9 files changed, 252 insertions, 177 deletions
diff --git a/opentracker.c b/opentracker.c index b839efc..c67e331 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -135,12 +135,10 @@ static ssize_t handle_read( const int64 sock, struct ot_workstruct *ws ) { | |||
135 | 135 | ||
136 | array_catb( &cookie->data.request, ws->inbuf, byte_count ); | 136 | array_catb( &cookie->data.request, ws->inbuf, byte_count ); |
137 | 137 | ||
138 | if( array_failed( &cookie->data.request ) ) | 138 | if( array_failed( &cookie->data.request ) || |
139 | array_bytes( &cookie->data.request ) > 8192 ) | ||
139 | return http_issue_error( sock, ws, CODE_HTTPERROR_500 ); | 140 | return http_issue_error( sock, ws, CODE_HTTPERROR_500 ); |
140 | 141 | ||
141 | if( array_bytes( &cookie->data.request ) > 8192 ) | ||
142 | return http_issue_error( sock, ws, CODE_HTTPERROR_500 ); | ||
143 | |||
144 | if( !memchr( array_start( &cookie->data.request ), '\n', array_bytes( &cookie->data.request ) ) ) | 142 | if( !memchr( array_start( &cookie->data.request ), '\n', array_bytes( &cookie->data.request ) ) ) |
145 | return 0; | 143 | return 0; |
146 | 144 | ||
@@ -370,6 +368,11 @@ int parse_configfile( char * config_filename ) { | |||
370 | if( !scan_ip6( p+13, tmpip )) goto parse_error; | 368 | if( !scan_ip6( p+13, tmpip )) goto parse_error; |
371 | accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT ); | 369 | accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT ); |
372 | #endif | 370 | #endif |
371 | #ifdef WANT_IP_FROM_PROXY | ||
372 | } else if(!byte_diff(p, 12, "access.proxy" ) && isspace(p[12])) { | ||
373 | if( !scan_ip6( p+13, tmpip )) goto parse_error; | ||
374 | accesslist_blessip( tmpip, OT_PERMISSION_MAY_PROXY ); | ||
375 | #endif | ||
373 | } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { | 376 | } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { |
374 | set_config_option( &g_redirecturl, p+21 ); | 377 | set_config_option( &g_redirecturl, p+21 ); |
375 | #ifdef WANT_SYNC_LIVE | 378 | #ifdef WANT_SYNC_LIVE |
diff --git a/ot_accesslist.c b/ot_accesslist.c index 304b3f1..631ab88 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
@@ -124,6 +124,7 @@ int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ) { | |||
124 | if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" ); | 124 | if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" ); |
125 | if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" ); | 125 | if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" ); |
126 | if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" ); | 126 | if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" ); |
127 | if( permissions & OT_PERMISSION_MAY_PROXY ) off += snprintf( _debug+off, 512-off, " may_proxy" ); | ||
127 | if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing\n" ); | 128 | if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing\n" ); |
128 | _debug[off++] = '.'; | 129 | _debug[off++] = '.'; |
129 | write( 2, _debug, off ); | 130 | write( 2, _debug, off ); |
diff --git a/ot_accesslist.h b/ot_accesslist.h index 836a233..5954a4a 100644 --- a/ot_accesslist.h +++ b/ot_accesslist.h | |||
@@ -27,7 +27,8 @@ extern char *g_accesslist_filename; | |||
27 | typedef enum { | 27 | typedef enum { |
28 | OT_PERMISSION_MAY_FULLSCRAPE = 0x1, | 28 | OT_PERMISSION_MAY_FULLSCRAPE = 0x1, |
29 | OT_PERMISSION_MAY_STAT = 0x2, | 29 | OT_PERMISSION_MAY_STAT = 0x2, |
30 | OT_PERMISSION_MAY_LIVESYNC = 0x4 | 30 | OT_PERMISSION_MAY_LIVESYNC = 0x4, |
31 | OT_PERMISSION_MAY_PROXY = 0x8 | ||
31 | } ot_permissions; | 32 | } ot_permissions; |
32 | 33 | ||
33 | int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ); | 34 | int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ); |
@@ -306,13 +306,14 @@ static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "even | |||
306 | { NULL, -3 } }; | 306 | { NULL, -3 } }; |
307 | static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; | 307 | static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; |
308 | static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) { | 308 | static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) { |
309 | int numwant, tmp, scanon; | 309 | int numwant, tmp, scanon; |
310 | ot_peer peer; | 310 | ot_peer peer; |
311 | ot_hash *hash = NULL; | 311 | ot_hash *hash = NULL; |
312 | unsigned short port = htons(6881); | 312 | unsigned short port = htons(6881); |
313 | char *write_ptr; | 313 | char *write_ptr; |
314 | ssize_t len; | 314 | ssize_t len; |
315 | 315 | struct http_data *cookie = io_getcookie( sock ); | |
316 | |||
316 | /* This is to hack around stupid clients that send "announce ?info_hash" */ | 317 | /* This is to hack around stupid clients that send "announce ?info_hash" */ |
317 | if( read_ptr[-1] != '?' ) { | 318 | if( read_ptr[-1] != '?' ) { |
318 | while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; | 319 | while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; |
@@ -320,7 +321,33 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, | |||
320 | ++read_ptr; | 321 | ++read_ptr; |
321 | } | 322 | } |
322 | 323 | ||
323 | OT_SETIP( &peer, ((struct http_data*)io_getcookie( sock ) )->ip ); | 324 | #ifdef WANT_IP_FROM_PROXY |
325 | if( accesslist_isblessed( cookie->ip, OT_PERMISSION_MAY_PROXY ) ) { | ||
326 | ot_ip6 proxied_ip; | ||
327 | char *fwd, *fwd_new = ws->request; | ||
328 | |||
329 | /* Zero terminate for string routines. Normally we'd only overwrite bollocks */ | ||
330 | ws->request[ws->request_size-1] = 0; | ||
331 | |||
332 | /* Find last occurence of the forwarded header */ | ||
333 | do { | ||
334 | fwd = fwd_new; | ||
335 | fwd_new = strcasestr( fwd_new, "\nX-Forwarded-For:" ); | ||
336 | } while( fwd_new ); | ||
337 | |||
338 | /* Skip spaces between : and the ip address */ | ||
339 | if( fwd ) { | ||
340 | fwd += 18; /* sizeof( "\nX-Forwarded-For:" ) */ | ||
341 | while( *fwd == ' ' ) ++fwd; | ||
342 | } | ||
343 | |||
344 | if( fwd && scan_ip6( fwd, proxied_ip ) ) | ||
345 | OT_SETIP( &peer, proxied_ip ); | ||
346 | else | ||
347 | OT_SETIP( &peer, cookie->ip ); | ||
348 | } | ||
349 | #endif | ||
350 | OT_SETIP( &peer, cookie->ip ); | ||
324 | OT_SETPORT( &peer, &port ); | 351 | OT_SETPORT( &peer, &port ); |
325 | OT_PEERFLAG( &peer ) = 0; | 352 | OT_PEERFLAG( &peer ) = 0; |
326 | numwant = 50; | 353 | numwant = 50; |
@@ -18,6 +18,7 @@ | |||
18 | /* Opentracker */ | 18 | /* Opentracker */ |
19 | #include "trackerlogic.h" | 19 | #include "trackerlogic.h" |
20 | #include "ot_mutex.h" | 20 | #include "ot_mutex.h" |
21 | #include "ot_stats.h" | ||
21 | 22 | ||
22 | /* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */ | 23 | /* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */ |
23 | #define MTX_DBG( STRING ) | 24 | #define MTX_DBG( STRING ) |
@@ -47,8 +48,10 @@ static int bucket_check( int bucket ) { | |||
47 | 48 | ||
48 | /* See, if bucket is already locked */ | 49 | /* See, if bucket is already locked */ |
49 | for( i=0; i<bucket_locklist_count; ++i ) | 50 | for( i=0; i<bucket_locklist_count; ++i ) |
50 | if( bucket_locklist[ i ] == bucket ) | 51 | if( bucket_locklist[ i ] == bucket ) { |
52 | stats_issue_event( EVENT_BUCKET_LOCKED, 0, 0 ); | ||
51 | return -1; | 53 | return -1; |
54 | } | ||
52 | 55 | ||
53 | return 0; | 56 | return 0; |
54 | } | 57 | } |
@@ -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 ); |
@@ -17,7 +17,8 @@ typedef enum { | |||
17 | EVENT_FULLSCRAPE_REQUEST, | 17 | EVENT_FULLSCRAPE_REQUEST, |
18 | EVENT_FULLSCRAPE_REQUEST_GZIP, | 18 | EVENT_FULLSCRAPE_REQUEST_GZIP, |
19 | EVENT_FULLSCRAPE, /* TCP only */ | 19 | EVENT_FULLSCRAPE, /* TCP only */ |
20 | EVENT_FAILED | 20 | EVENT_FAILED, |
21 | EVENT_BUCKET_LOCKED | ||
21 | } ot_status_event; | 22 | } ot_status_event; |
22 | 23 | ||
23 | enum { | 24 | enum { |
diff --git a/trackerlogic.c b/trackerlogic.c index 249a2a0..8ebaa46 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -337,6 +337,23 @@ size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROTO | |||
337 | return reply_size; | 337 | return reply_size; |
338 | } | 338 | } |
339 | 339 | ||
340 | void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data ), uintptr_t data ) { | ||
341 | int bucket; | ||
342 | size_t j; | ||
343 | |||
344 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | ||
345 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | ||
346 | ot_torrent *torrents = (ot_torrent*)(torrents_list->data); | ||
347 | |||
348 | for( j=0; j<torrents_list->size; ++j ) | ||
349 | if( for_each( torrents + j, data ) ) | ||
350 | break; | ||
351 | |||
352 | mutex_bucket_unlock( bucket, 0 ); | ||
353 | if( !g_opentracker_running ) return; | ||
354 | } | ||
355 | } | ||
356 | |||
340 | void exerr( char * message ) { | 357 | void exerr( char * message ) { |
341 | fprintf( stderr, "%s\n", message ); | 358 | fprintf( stderr, "%s\n", message ); |
342 | exit( 111 ); | 359 | exit( 111 ); |
@@ -358,7 +375,7 @@ void trackerlogic_init( ) { | |||
358 | void trackerlogic_deinit( void ) { | 375 | void trackerlogic_deinit( void ) { |
359 | int bucket, delta_torrentcount = 0; | 376 | int bucket, delta_torrentcount = 0; |
360 | size_t j; | 377 | size_t j; |
361 | 378 | ||
362 | /* Free all torrents... */ | 379 | /* Free all torrents... */ |
363 | for(bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 380 | for(bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { |
364 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 381 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); |
diff --git a/trackerlogic.h b/trackerlogic.h index 69deddd..ce3feb1 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
@@ -148,6 +148,9 @@ size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROT | |||
148 | size_t return_tcp_scrape_for_torrent( ot_hash *hash, int amount, char *reply ); | 148 | size_t return_tcp_scrape_for_torrent( ot_hash *hash, int amount, char *reply ); |
149 | size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply ); | 149 | size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply ); |
150 | 150 | ||
151 | /* torrent iterator */ | ||
152 | void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data ), uintptr_t data ); | ||
153 | |||
151 | /* Helper, before it moves to its own object */ | 154 | /* Helper, before it moves to its own object */ |
152 | void free_peerlist( ot_peerlist *peer_list ); | 155 | void free_peerlist( ot_peerlist *peer_list ); |
153 | 156 | ||