summaryrefslogtreecommitdiff
path: root/ot_stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_stats.c')
-rw-r--r--ot_stats.c128
1 files changed, 62 insertions, 66 deletions
diff --git a/ot_stats.c b/ot_stats.c
index fa456c3..afc972a 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -4,13 +4,11 @@
4 $id$ */ 4 $id$ */
5 5
6/* System */ 6/* System */
7#include <arpa/inet.h>
8#include <inttypes.h> 7#include <inttypes.h>
9#include <pthread.h> 8#include <pthread.h>
10#include <stdio.h> 9#include <stdio.h>
11#include <stdlib.h> 10#include <stdlib.h>
12#include <string.h> 11#include <string.h>
13#include <sys/mman.h>
14#include <sys/types.h> 12#include <sys/types.h>
15#include <sys/uio.h> 13#include <sys/uio.h>
16#include <unistd.h> 14#include <unistd.h>
@@ -19,7 +17,6 @@
19#endif 17#endif
20 18
21/* Libowfat */ 19/* Libowfat */
22#include "byte.h"
23#include "io.h" 20#include "io.h"
24#include "ip4.h" 21#include "ip4.h"
25#include "ip6.h" 22#include "ip6.h"
@@ -38,7 +35,7 @@
38#endif 35#endif
39 36
40/* Forward declaration */ 37/* Forward declaration */
41static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode); 38static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode);
42#define OT_STATS_TMPSIZE 8192 39#define OT_STATS_TMPSIZE 8192
43 40
44/* Clumsy counters... to be rethought */ 41/* Clumsy counters... to be rethought */
@@ -113,7 +110,7 @@ static int stat_increase_network_count(stats_network_node **pnode, int depth, ui
113} 110}
114 111
115static int stats_shift_down_network_count(stats_network_node **node, int depth, int shift) { 112static int stats_shift_down_network_count(stats_network_node **node, int depth, int shift) {
116 int i, rest = 0; 113 size_t i, rest = 0;
117 114
118 if (!*node) 115 if (!*node)
119 return 0; 116 return 0;
@@ -134,8 +131,7 @@ static int stats_shift_down_network_count(stats_network_node **node, int depth,
134 131
135static size_t stats_get_highscore_networks(stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count, 132static size_t stats_get_highscore_networks(stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count,
136 int limit) { 133 int limit) {
137 size_t score = 0; 134 size_t i, score = 0;
138 int i;
139 135
140 if (!node) 136 if (!node)
141 return 0; 137 return 0;
@@ -191,11 +187,11 @@ static size_t stats_get_highscore_networks(stats_network_node *node, int depth,
191 return score; 187 return score;
192} 188}
193 189
194static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, int amount, int limit) { 190static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, size_t amount, int limit) {
195 ot_ip6 networks[amount]; 191 ot_ip6 networks[amount];
196 ot_ip6 node_value; 192 ot_ip6 node_value;
197 size_t scores[amount]; 193 size_t scores[amount];
198 int i; 194 size_t i;
199 char *r = reply; 195 char *r = reply;
200 196
201 memset(scores, 0, sizeof(scores)); 197 memset(scores, 0, sizeof(scores));
@@ -205,14 +201,14 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree,
205 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit); 201 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit);
206 202
207 r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH); 203 r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH);
208 for (i = amount - 1; i >= 0; --i) { 204 for (i = amount; i > 0; --i) {
209 if (scores[i]) { 205 if (scores[i - 1]) {
210 r += sprintf(r, "%08zd: ", scores[i]); 206 r += sprintf(r, "%08zd: ", scores[i - 1]);
211 // #ifdef WANT_V6 207 // #ifdef WANT_V6
212 r += fmt_ip6c(r, networks[i]); 208 r += fmt_ip6c(r, networks[i - 1]);
213#if 0 209#if 0
214 // XXX 210 // XXX
215 r += fmt_ip4( r, networks[i]); 211 r += fmt_ip4( r, networks[i - 1]);
216#endif 212#endif
217 *r++ = '\n'; 213 *r++ = '\n';
218 } 214 }
@@ -225,8 +221,7 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree,
225static size_t stats_slash24s_txt(char *reply, size_t amount) { 221static size_t stats_slash24s_txt(char *reply, size_t amount) {
226 stats_network_node *slash24s_network_counters_root = NULL; 222 stats_network_node *slash24s_network_counters_root = NULL;
227 char *r = reply; 223 char *r = reply;
228 int bucket; 224 size_t i, bucket, peer_size = OT_PEER_SIZE4;
229 size_t i, peer_size = OT_PEER_SIZE4;
230 225
231 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 226 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
232 ot_vector *torrents_list = mutex_bucket_lock(bucket); 227 ot_vector *torrents_list = mutex_bucket_lock(bucket);
@@ -317,55 +312,64 @@ typedef struct {
317 ot_hash hash; 312 ot_hash hash;
318} ot_record; 313} ot_record;
319 314
315static inline void stats_insert_into_highscore(size_t val, ot_record* list, size_t amount, ot_hash* hash) {
316 size_t i;
317 for (i = 0; (i < amount) && (list[i].val > val); ++i)
318 {}
319 /* if we score better than a record in the list, we need to make room in the high
320 score array by moving lower scoring entries up */
321 if (i < amount) {
322 memmove(list + i + 1, list + i, (amount - i - 1) * sizeof(ot_record));
323
324 memcpy(&list[i].hash, hash, sizeof(ot_hash));
325 list[i].val = val;
326 }
327}
328
329
320/* Fetches stats from tracker */ 330/* Fetches stats from tracker */
321size_t stats_top_txt(char *reply, int amount) { 331size_t stats_top_txt(char *reply, size_t amount) {
322 size_t j; 332 size_t j, idx, bucket;
323 ot_record top100s[100], top100c[100]; 333 ot_record top100s[100], top100c[100], top100l[100];
324 char *r = reply, hex_out[42]; 334 char *r = reply, hex_out[42];
325 int idx, bucket;
326 335
327 if (amount > 100) 336 if (amount > 100)
328 amount = 100; 337 amount = 100;
329 338
330 byte_zero(top100s, sizeof(top100s)); 339 memset(top100s, 0, sizeof(top100s));
331 byte_zero(top100c, sizeof(top100c)); 340 memset(top100c, 0, sizeof(top100c));
341 memset(top100l, 0, sizeof(top100l));
332 342
343 /* Iterate over complete torrent list */
333 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 344 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
334 ot_vector *torrents_list = mutex_bucket_lock(bucket); 345 ot_vector *torrents_list = mutex_bucket_lock(bucket);
335 for (j = 0; j < torrents_list->size; ++j) { 346 for (j = 0; j < torrents_list->size; ++j) {
336 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; 347 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j;
337 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; 348 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count;
338 size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; 349 size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count;
339 idx = amount - 1; 350 size_t leech_count = peer_count - seed_count;
340 while ((idx >= 0) && (peer_count > top100c[idx].val)) 351
341 --idx; 352 stats_insert_into_highscore(peer_count, top100c, amount, &torrent->hash);
342 if (idx++ != amount - 1) { 353 stats_insert_into_highscore(seed_count, top100s, amount, &torrent->hash);
343 memmove(top100c + idx + 1, top100c + idx, (amount - 1 - idx) * sizeof(ot_record)); 354 stats_insert_into_highscore(leech_count, top100l, amount, &torrent->hash);
344 memcpy(&top100c[idx].hash, &torrent->hash, sizeof(ot_hash));
345 top100c[idx].val = peer_count;
346 }
347 idx = amount - 1;
348 while ((idx >= 0) && (seed_count > top100s[idx].val))
349 --idx;
350 if (idx++ != amount - 1) {
351 memmove(top100s + idx + 1, top100s + idx, (amount - 1 - idx) * sizeof(ot_record));
352 memcpy(&top100s[idx].hash, &torrent->hash, sizeof(ot_hash));
353 top100s[idx].val = seed_count;
354 }
355 } 355 }
356 mutex_bucket_unlock(bucket, 0); 356 mutex_bucket_unlock(bucket, 0);
357 if (!g_opentracker_running) 357 if (!g_opentracker_running)
358 return 0; 358 return 0;
359 } 359 }
360 360
361 r += sprintf(r, "Top %d torrents by peers:\n", amount); 361 r += sprintf(r, "Top %zd torrents by peers:\n", amount);
362 for (idx = 0; idx < amount; ++idx) 362 for (idx = 0; idx < amount; ++idx)
363 if (top100c[idx].val) 363 if (top100c[idx].val)
364 r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, to_hex(hex_out, top100c[idx].hash)); 364 r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, to_hex(hex_out, top100c[idx].hash));
365 r += sprintf(r, "Top %d torrents by seeds:\n", amount); 365 r += sprintf(r, "Top %zd torrents by seeds:\n", amount);
366 for (idx = 0; idx < amount; ++idx) 366 for (idx = 0; idx < amount; ++idx)
367 if (top100s[idx].val) 367 if (top100s[idx].val)
368 r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash)); 368 r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, to_hex(hex_out, top100s[idx].hash));
369 r += sprintf(r, "Top %zd torrents by leechers:\n", amount);
370 for (idx = 0; idx < amount; ++idx)
371 if (top100l[idx].val)
372 r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, to_hex(hex_out, top100l[idx].hash));
369 373
370 return r - reply; 374 return r - reply;
371} 375}
@@ -463,7 +467,7 @@ static size_t stats_return_numwants(char *reply) {
463#endif 467#endif
464 468
465#ifdef WANT_FULLLOG_NETWORKS 469#ifdef WANT_FULLLOG_NETWORKS
466static void stats_return_fulllog(int *iovec_entries, struct iovec **iovector, char *r) { 470static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector, char *r) {
467 ot_log *loglist = g_logchain_first, *llnext; 471 ot_log *loglist = g_logchain_first, *llnext;
468 char *re = r + OT_STATS_TMPSIZE; 472 char *re = r + OT_STATS_TMPSIZE;
469 473
@@ -476,9 +480,9 @@ static void stats_return_fulllog(int *iovec_entries, struct iovec **iovector, ch
476 return; 480 return;
477 re = r + 32 * OT_STATS_TMPSIZE; 481 re = r + 32 * OT_STATS_TMPSIZE;
478 } 482 }
479 r += sprintf(r, "%08ld: ", loglist->time); 483 r += sprintf(r, "%08ld: ", loglist->time);
480 r += fmt_ip6c(r, loglist->ip); 484 r += fmt_ip6c(r, loglist->ip);
481 *r++ = '\n'; 485 *r++ = '\n';
482 memcpy(r, loglist->data, loglist->size); 486 memcpy(r, loglist->data, loglist->size);
483 r += loglist->size; 487 r += loglist->size;
484 *r++ = '\n'; 488 *r++ = '\n';
@@ -518,10 +522,8 @@ static size_t stats_return_everything(char *reply) {
518 r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); 522 r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed);
519 r += sprintf(r, " <connections>\n"); 523 r += sprintf(r, " <connections>\n");
520 r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", 524 r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n",
521 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes); 525 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes);
522 r += sprintf( 526 r += sprintf(r, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n",
523 r,
524 " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n",
525 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, 527 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes,
526 ot_overall_udp_connectionidmissmatches); 528 ot_overall_udp_connectionidmissmatches);
527 r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); 529 r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count);
@@ -541,14 +543,10 @@ static size_t stats_return_everything(char *reply) {
541 return r - reply; 543 return r - reply;
542} 544}
543 545
544extern const char *g_version_opentracker_c, *g_version_accesslist_c, *g_version_clean_c, *g_version_fullscrape_c, *g_version_http_c, *g_version_iovec_c,
545 *g_version_mutex_c, *g_version_stats_c, *g_version_udp_c, *g_version_vector_c, *g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c,
546 *g_version_livesync_c, *g_version_rijndael_c;
547
548size_t stats_return_tracker_version(char *reply) { 546size_t stats_return_tracker_version(char *reply) {
549 return sprintf(reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, 547#define QUOTE(name) #name
550 g_version_http_c, g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, 548#define SQUOTE(name) QUOTE(name)
551 g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c, g_version_rijndael_c); 549 return sprintf(reply, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n");
552} 550}
553 551
554size_t return_stats_for_tracker(char *reply, int mode, int format) { 552size_t return_stats_for_tracker(char *reply, int mode, int format) {
@@ -583,7 +581,7 @@ size_t return_stats_for_tracker(char *reply, int mode, int format) {
583 } 581 }
584} 582}
585 583
586static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode) { 584static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) {
587 char *r; 585 char *r;
588 586
589 *iovec_entries = 0; 587 *iovec_entries = 0;
@@ -740,7 +738,7 @@ void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_
740 } 738 }
741} 739}
742 740
743void stats_cleanup() { 741void stats_cleanup(void) {
744#ifdef WANT_SPOT_WOODPECKER 742#ifdef WANT_SPOT_WOODPECKER
745 pthread_mutex_lock(&g_woodpeckers_mutex); 743 pthread_mutex_lock(&g_woodpeckers_mutex);
746 stats_shift_down_network_count(&stats_woodpeckers_tree, 0, 1); 744 stats_shift_down_network_count(&stats_woodpeckers_tree, 0, 1);
@@ -749,7 +747,7 @@ void stats_cleanup() {
749} 747}
750 748
751static void *stats_worker(void *args) { 749static void *stats_worker(void *args) {
752 int iovec_entries; 750 size_t iovec_entries;
753 struct iovec *iovector; 751 struct iovec *iovector;
754 752
755 (void)args; 753 (void)args;
@@ -767,13 +765,11 @@ static void *stats_worker(void *args) {
767void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); } 765void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); }
768 766
769static pthread_t thread_id; 767static pthread_t thread_id;
770void stats_init() { 768void stats_init(void) {
771 ot_start_time = g_now_seconds; 769 ot_start_time = g_now_seconds;
772 pthread_create(&thread_id, NULL, stats_worker, NULL); 770 pthread_create(&thread_id, NULL, stats_worker, NULL);
773} 771}
774 772
775void stats_deinit() { 773void stats_deinit(void) {
776 pthread_cancel(thread_id); 774 pthread_cancel(thread_id);
777} 775}
778
779const char *g_version_stats_c = "$Source$: $Revision$\n";