summaryrefslogtreecommitdiff
path: root/ot_stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_stats.c')
-rw-r--r--ot_stats.c186
1 files changed, 153 insertions, 33 deletions
diff --git a/ot_stats.c b/ot_stats.c
index 6857376..7cfb1dc 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -17,57 +17,59 @@
17#include "ot_mutex.h" 17#include "ot_mutex.h"
18#include "ot_stats.h" 18#include "ot_stats.h"
19 19
20/* Clumsy counters... to be rethought */
21static unsigned long long ot_overall_tcp_connections = 0;
22static unsigned long long ot_overall_udp_connections = 0;
23static unsigned long long ot_overall_tcp_successfulannounces = 0;
24static unsigned long long ot_overall_udp_successfulannounces = 0;
25static unsigned long long ot_overall_tcp_successfulscrapes = 0;
26static unsigned long long ot_overall_udp_successfulscrapes = 0;
27static unsigned long long ot_full_scrape_count = 0;
28static unsigned long long ot_full_scrape_size = 0;
29
20/* Converter function from memory to human readable hex strings */ 30/* Converter function from memory to human readable hex strings */
21static char*to_hex(char*d,ot_byte*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;} 31static char*to_hex(char*d,ot_byte*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;}
22 32
23typedef struct { size_t val; ot_torrent * torrent; } ot_record; 33typedef struct { size_t val; ot_torrent * torrent; } ot_record;
24 34
25/* Fetches stats from tracker */ 35/* Fetches stats from tracker */
26size_t return_stats_for_tracker( char *reply, int mode ) { 36size_t stats_top5_txt( char * reply ) {
27 size_t torrent_count = 0, peer_count = 0, seed_count = 0, j; 37 size_t j;
28 ot_record top5s[5], top5c[5]; 38 ot_record top5s[5], top5c[5];
29 char *r = reply; 39 char *r = reply, hex_out[42];
30 int bucket; 40 int idx, bucket;
31 41
32 byte_zero( top5s, sizeof( top5s ) ); 42 byte_zero( top5s, sizeof( top5s ) );
33 byte_zero( top5c, sizeof( top5c ) ); 43 byte_zero( top5c, sizeof( top5c ) );
34 44
35 for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { 45 for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) {
36 ot_vector *torrents_list = mutex_bucket_lock( bucket ); 46 ot_vector *torrents_list = mutex_bucket_lock( bucket );
37 torrent_count += torrents_list->size;
38 for( j=0; j<torrents_list->size; ++j ) { 47 for( j=0; j<torrents_list->size; ++j ) {
39 ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; 48 ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
40 if( mode == STATS_TOP5 ) { 49 int idx = 4; while( (idx >= 0) && ( peer_list->peer_count > top5c[idx].val ) ) --idx;
41 int idx = 4; while( (idx >= 0) && ( peer_list->peer_count > top5c[idx].val ) ) --idx; 50 if ( idx++ != 4 ) {
42 if ( idx++ != 4 ) { 51 memmove( top5c + idx + 1, top5c + idx, ( 4 - idx ) * sizeof( ot_record ) );
43 memmove( top5c + idx + 1, top5c + idx, ( 4 - idx ) * sizeof( ot_record ) ); 52 top5c[idx].val = peer_list->peer_count;
44 top5c[idx].val = peer_list->peer_count; 53 top5c[idx].torrent = (ot_torrent*)(torrents_list->data) + j;
45 top5c[idx].torrent = (ot_torrent*)(torrents_list->data) + j; 54 }
46 } 55 idx = 4; while( (idx >= 0) && ( peer_list->seed_count > top5s[idx].val ) ) --idx;
47 idx = 4; while( (idx >= 0) && ( peer_list->seed_count > top5s[idx].val ) ) --idx; 56 if ( idx++ != 4 ) {
48 if ( idx++ != 4 ) { 57 memmove( top5s + idx + 1, top5s + idx, ( 4 - idx ) * sizeof( ot_record ) );
49 memmove( top5s + idx + 1, top5s + idx, ( 4 - idx ) * sizeof( ot_record ) ); 58 top5s[idx].val = peer_list->seed_count;
50 top5s[idx].val = peer_list->seed_count; 59 top5s[idx].torrent = (ot_torrent*)(torrents_list->data) + j;
51 top5s[idx].torrent = (ot_torrent*)(torrents_list->data) + j;
52 }
53 } 60 }
54 peer_count += peer_list->peer_count; seed_count += peer_list->seed_count;
55 } 61 }
56 mutex_bucket_unlock( bucket ); 62 mutex_bucket_unlock( bucket );
57 } 63 }
58 if( mode == STATS_TOP5 ) { 64
59 char hex_out[42]; 65 r += sprintf( r, "Top5 torrents by peers:\n" );
60 int idx; 66 for( idx=0; idx<5; ++idx )
61 r += sprintf( r, "Top5 torrents by peers:\n" ); 67 if( top5c[idx].torrent )
62 for( idx=0; idx<5; ++idx ) 68 r += sprintf( r, "\t%zd\t%s\n", top5c[idx].val, to_hex( hex_out, top5c[idx].torrent->hash) );
63 if( top5c[idx].torrent ) 69 r += sprintf( r, "Top5 torrents by seeds:\n" );
64 r += sprintf( r, "\t%zd\t%s\n", top5c[idx].val, to_hex( hex_out, top5c[idx].torrent->hash) ); 70 for( idx=0; idx<5; ++idx )
65 r += sprintf( r, "Top5 torrents by seeds:\n" ); 71 if( top5s[idx].torrent )
66 for( idx=0; idx<5; ++idx ) 72 r += sprintf( r, "\t%zd\t%s\n", top5s[idx].val, to_hex( hex_out, top5s[idx].torrent->hash) );
67 if( top5s[idx].torrent )
68 r += sprintf( r, "\t%zd\t%s\n", top5s[idx].val, to_hex( hex_out, top5s[idx].torrent->hash) );
69 } else
70 r += sprintf( r, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", peer_count, seed_count, torrent_count );
71 73
72 return r - reply; 74 return r - reply;
73} 75}
@@ -75,7 +77,7 @@ size_t return_stats_for_tracker( char *reply, int mode ) {
75/* This function collects 4096 /24s in 4096 possible 77/* This function collects 4096 /24s in 4096 possible
76 malloc blocks 78 malloc blocks
77*/ 79*/
78size_t return_stats_for_slash24s( char *reply, size_t amount, ot_dword thresh ) { 80static size_t stats_slash24s_txt( char * reply, size_t amount, ot_dword thresh ) {
79 81
80#define NUM_TOPBITS 12 82#define NUM_TOPBITS 12
81#define NUM_LOWBITS (24-NUM_TOPBITS) 83#define NUM_LOWBITS (24-NUM_TOPBITS)
@@ -200,3 +202,121 @@ size_t return_memstat_for_tracker( char **reply ) {
200 202
201 return replysize; 203 return replysize;
202} 204}
205
206static unsigned long events_per_time( unsigned long long events, time_t t ) {
207 return events / ( (unsigned int)t ? (unsigned int)t : 1 );
208}
209
210static size_t stats_connections_mrtg( char * reply ) {
211 ot_time t = time( NULL ) - ot_start_time;
212 return sprintf( reply,
213 "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.",
214 ot_overall_tcp_connections+ot_overall_udp_connections,
215 ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces,
216 (int)t,
217 (int)(t / 3600),
218 events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ),
219 events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces, t )
220 );
221}
222
223static size_t stats_udpconnections_mrtg( char * reply ) {
224 ot_time t = time( NULL ) - ot_start_time;
225 return sprintf( reply,
226 "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.",
227 ot_overall_udp_connections,
228 ot_overall_udp_successfulannounces,
229 (int)t,
230 (int)(t / 3600),
231 events_per_time( ot_overall_udp_connections, t ),
232 events_per_time( ot_overall_udp_successfulannounces, t )
233 );
234}
235
236static size_t stats_tcpconnections_mrtg( char * reply ) {
237 time_t t = time( NULL ) - ot_start_time;
238 return sprintf( reply,
239 "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.",
240 ot_overall_tcp_connections,
241 ot_overall_tcp_successfulannounces,
242 (int)t,
243 (int)(t / 3600),
244 events_per_time( ot_overall_tcp_connections, t ),
245 events_per_time( ot_overall_tcp_successfulannounces, t )
246 );
247}
248
249
250static size_t stats_fullscrapes_mrtg( char * reply ) {
251 ot_time t = time( NULL ) - ot_start_time;
252 return sprintf( reply,
253 "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.",
254 ot_full_scrape_count * 1000,
255 ot_full_scrape_size,
256 (int)t,
257 (int)(t / 3600),
258 events_per_time( ot_full_scrape_count, t ),
259 events_per_time( ot_full_scrape_size, t )
260 );
261}
262
263static size_t stats_peers_mrtg( char * reply ) {
264 size_t torrent_count = 0, peer_count = 0, seed_count = 0, j;
265 int bucket;
266
267 for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) {
268 ot_vector *torrents_list = mutex_bucket_lock( bucket );
269 torrent_count += torrents_list->size;
270 for( j=0; j<torrents_list->size; ++j ) {
271 ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
272 peer_count += peer_list->peer_count; seed_count += peer_list->seed_count;
273 }
274 mutex_bucket_unlock( bucket );
275 }
276 return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker",
277 peer_count,
278 seed_count,
279 torrent_count
280 );
281}
282
283size_t return_stats_for_tracker( char *reply, int mode, int format ) {
284 format = format;
285 switch( mode ) {
286 case STATS_CONNS:
287 return stats_connections_mrtg( reply );
288 case STATS_UDP:
289 return stats_udpconnections_mrtg( reply );
290 case STATS_TCP:
291 return stats_tcpconnections_mrtg( reply );
292 case STATS_PEERS:
293 return stats_peers_mrtg( reply );
294 case STATS_SLASH24S:
295 return stats_slash24s_txt( reply, 25, 16 );
296 case STATS_TOP5:
297 return stats_top5_txt( reply );
298 case STATS_FULLSCRAPE:
299 return stats_fullscrapes_mrtg( reply );
300 default:
301 return 0;
302 }
303}
304
305void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) {
306 switch( event ) {
307 case EVENT_ACCEPT:
308 if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++;
309 break;
310 case EVENT_ANNOUNCE:
311 if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++;
312 break;
313 case EVENT_SCRAPE:
314 if( is_tcp ) ot_overall_tcp_successfulscrapes++; else ot_overall_udp_successfulscrapes++;
315 case EVENT_FULLSCRAPE:
316 ot_full_scrape_count++;
317 ot_full_scrape_size += event_data;
318 break;
319 default:
320 break;
321 }
322} \ No newline at end of file