diff options
Diffstat (limited to 'ot_stats.c')
| -rw-r--r-- | ot_stats.c | 128 |
1 files changed, 62 insertions, 66 deletions
| @@ -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 */ |
| 41 | static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode); | 38 | static 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 | ||
| 115 | static int stats_shift_down_network_count(stats_network_node **node, int depth, int shift) { | 112 | static 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 | ||
| 135 | static 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, | 132 | static 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 | ||
| 194 | static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, int amount, int limit) { | 190 | static 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, | |||
| 225 | static size_t stats_slash24s_txt(char *reply, size_t amount) { | 221 | static 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 | ||
| 315 | static 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 */ |
| 321 | size_t stats_top_txt(char *reply, int amount) { | 331 | size_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 |
| 466 | static void stats_return_fulllog(int *iovec_entries, struct iovec **iovector, char *r) { | 470 | static 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 | ||
| 544 | extern 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 | |||
| 548 | size_t stats_return_tracker_version(char *reply) { | 546 | size_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 | ||
| 554 | size_t return_stats_for_tracker(char *reply, int mode, int format) { | 552 | size_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 | ||
| 586 | static void stats_make(int *iovec_entries, struct iovec **iovector, ot_tasktype mode) { | 584 | static 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 | ||
| 743 | void stats_cleanup() { | 741 | void 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 | ||
| 751 | static void *stats_worker(void *args) { | 749 | static 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) { | |||
| 767 | void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); } | 765 | void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); } |
| 768 | 766 | ||
| 769 | static pthread_t thread_id; | 767 | static pthread_t thread_id; |
| 770 | void stats_init() { | 768 | void 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 | ||
| 775 | void stats_deinit() { | 773 | void stats_deinit(void) { |
| 776 | pthread_cancel(thread_id); | 774 | pthread_cancel(thread_id); |
| 777 | } | 775 | } |
| 778 | |||
| 779 | const char *g_version_stats_c = "$Source$: $Revision$\n"; | ||
