summaryrefslogtreecommitdiff
path: root/ot_stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_stats.c')
-rw-r--r--ot_stats.c302
1 files changed, 149 insertions, 153 deletions
diff --git a/ot_stats.c b/ot_stats.c
index 53bd749..45dc8db 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -22,6 +22,7 @@
22#include "ot_iovec.h" 22#include "ot_iovec.h"
23#include "ot_ip.h" 23#include "ot_ip.h"
24#include "ot_mutex.h" 24#include "ot_mutex.h"
25#include "ot_fmt.h"
25#include "ot_stats.h" 26#include "ot_stats.h"
26#include "trackerlogic.h" 27#include "trackerlogic.h"
27 28
@@ -184,12 +185,11 @@ static size_t stats_get_highscore_networks(stats_network_node *node, int depth,
184 return score; 185 return score;
185} 186}
186 187
187static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, size_t amount, int limit) { 188static void stats_return_busy_networks(char **reply, const char *reply_end, stats_network_node *tree, size_t amount, int limit) {
188 ot_ip6 networks[amount]; 189 ot_ip6 networks[amount];
189 ot_ip6 node_value; 190 ot_ip6 node_value;
190 size_t scores[amount]; 191 size_t scores[amount];
191 size_t i; 192 size_t i;
192 char *r = reply;
193 193
194 memset(scores, 0, sizeof(scores)); 194 memset(scores, 0, sizeof(scores));
195 memset(networks, 0, sizeof(networks)); 195 memset(networks, 0, sizeof(networks));
@@ -197,24 +197,21 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree,
197 197
198 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit); 198 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit);
199 199
200 r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH); 200 fmt_append(reply, reply_end, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH);
201 for (i = amount; i > 0; --i) { 201 for (i = amount; i > 0; --i) {
202 if (scores[i - 1]) { 202 if (scores[i - 1]) {
203 r += sprintf(r, "%08zd: ", scores[i - 1]); 203 char ip_readable[64];
204 // #ifdef WANT_V6 204
205 r += ip_format(r, networks[i - 1]); 205 ip_readable[ip_format(ip_readable, networks[i - 1])] = 0;
206 *r++ = '\n'; 206 fmt_append(reply, reply_end, "%08zd: %s\n", scores[i - 1], ip_readable);
207 } 207 }
208 } 208 }
209 *r++ = '\n'; 209 fmt_append(reply, reply_end, "\n");
210
211 return r - reply;
212} 210}
213 211
214static size_t stats_slash24s_txt(char *reply, size_t amount) { 212static void stats_slash24s_txt(char **reply, const char *reply_end, size_t amount) {
215 stats_network_node *slash24s_network_counters_root = NULL; 213 stats_network_node *slash24s_network_counters_root = NULL;
216 char *r = reply; 214 size_t i, bucket, peer_size = OT_PEER_SIZE4;
217 size_t i, bucket, peer_size = OT_PEER_SIZE4;
218 215
219 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 216 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
220 ot_vector *torrents_list = mutex_bucket_lock(bucket); 217 ot_vector *torrents_list = mutex_bucket_lock(bucket);
@@ -241,35 +238,28 @@ static size_t stats_slash24s_txt(char *reply, size_t amount) {
241 } 238 }
242 mutex_bucket_unlock(bucket, 0); 239 mutex_bucket_unlock(bucket, 0);
243 if (!g_opentracker_running) 240 if (!g_opentracker_running)
244 goto bailout_error; 241 goto done;
245 } 242 }
246 243
247 /* The tree is built. Now analyze */ 244 /* The tree is built. Now analyze */
248 r += stats_return_busy_networks(r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_MAXDEPTH); 245 stats_return_busy_networks(reply, reply_end, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_MAXDEPTH);
249 r += stats_return_busy_networks(r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_LIMIT); 246 stats_return_busy_networks(reply, reply_end, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_LIMIT);
250 goto success; 247 goto done;
251 248
252bailout_unlock: 249bailout_unlock:
253 mutex_bucket_unlock(bucket, 0); 250 mutex_bucket_unlock(bucket, 0);
254bailout_error: 251done:
255 r = reply;
256success:
257 stats_shift_down_network_count(&slash24s_network_counters_root, 0, sizeof(int) * 8 - 1); 252 stats_shift_down_network_count(&slash24s_network_counters_root, 0, sizeof(int) * 8 - 1);
258
259 return r - reply;
260} 253}
261 254
262#ifdef WANT_SPOT_WOODPECKER 255#ifdef WANT_SPOT_WOODPECKER
263static stats_network_node *stats_woodpeckers_tree; 256static stats_network_node *stats_woodpeckers_tree;
264static pthread_mutex_t g_woodpeckers_mutex = PTHREAD_MUTEX_INITIALIZER; 257static pthread_mutex_t g_woodpeckers_mutex = PTHREAD_MUTEX_INITIALIZER;
265 258
266static size_t stats_return_woodpeckers(char *reply, int amount) { 259static void stats_return_woodpeckers(char **reply, const char *reply_end, int amount) {
267 char *r = reply;
268
269 pthread_mutex_lock(&g_woodpeckers_mutex); 260 pthread_mutex_lock(&g_woodpeckers_mutex);
270 r += stats_return_busy_networks(r, stats_woodpeckers_tree, amount, STATS_NETWORK_NODE_MAXDEPTH); 261 stats_return_busy_networks(reply, reply_end, stats_woodpeckers_tree, amount, STATS_NETWORK_NODE_MAXDEPTH);
271 pthread_mutex_unlock(&g_woodpeckers_mutex); 262 pthread_mutex_unlock(&g_woodpeckers_mutex);
272 return r - reply;
273} 263}
274#endif 264#endif
275 265
@@ -309,10 +299,10 @@ static inline void stats_insert_into_highscore(size_t val, ot_record* list, size
309 299
310 300
311/* Fetches stats from tracker */ 301/* Fetches stats from tracker */
312size_t stats_top_txt(char *reply, size_t amount) { 302void stats_top_txt(char **reply, const char *reply_end, size_t amount) {
313 size_t j, idx, bucket; 303 size_t j, idx, bucket;
314 ot_record top100s[100], top100c[100], top100l[100]; 304 ot_record top100s[100], top100c[100], top100l[100];
315 char *r = reply, hex_out[42]; 305 char hex_out[42];
316 306
317 if (amount > 100) 307 if (amount > 100)
318 amount = 100; 308 amount = 100;
@@ -323,7 +313,7 @@ size_t stats_top_txt(char *reply, size_t amount) {
323 313
324 /* Iterate over complete torrent list */ 314 /* Iterate over complete torrent list */
325 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 315 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
326 ot_vector *torrents_list = mutex_bucket_lock(bucket); 316 ot_vector *torrents_list = mutex_bucket_lock(bucket);
327 for (j = 0; j < torrents_list->size; ++j) { 317 for (j = 0; j < torrents_list->size; ++j) {
328 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; 318 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j;
329 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; 319 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count;
@@ -336,114 +326,110 @@ size_t stats_top_txt(char *reply, size_t amount) {
336 } 326 }
337 mutex_bucket_unlock(bucket, 0); 327 mutex_bucket_unlock(bucket, 0);
338 if (!g_opentracker_running) 328 if (!g_opentracker_running)
339 return 0; 329 return;
340 } 330 }
341 331
342 r += sprintf(r, "Top %zd torrents by peers:\n", amount); 332 fmt_append(reply, reply_end, "Top %zd torrents by peers:\n", amount);
343 for (idx = 0; idx < amount; ++idx) 333 for (idx = 0; idx < amount; ++idx)
344 if (top100c[idx].val) 334 if (top100c[idx].val)
345 r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, hex_from_hash(hex_out, top100c[idx].hash)); 335 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100c[idx].val, hex_from_hash(hex_out, top100c[idx].hash));
346 r += sprintf(r, "Top %zd torrents by seeds:\n", amount); 336 fmt_append(reply, reply_end, "Top %zd torrents by seeds:\n", amount);
347 for (idx = 0; idx < amount; ++idx) 337 for (idx = 0; idx < amount; ++idx)
348 if (top100s[idx].val) 338 if (top100s[idx].val)
349 r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, hex_from_hash(hex_out, top100s[idx].hash)); 339 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100s[idx].val, hex_from_hash(hex_out, top100s[idx].hash));
350 r += sprintf(r, "Top %zd torrents by leechers:\n", amount); 340 fmt_append(reply, reply_end, "Top %zd torrents by leechers:\n", amount);
351 for (idx = 0; idx < amount; ++idx) 341 for (idx = 0; idx < amount; ++idx)
352 if (top100l[idx].val) 342 if (top100l[idx].val)
353 r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, hex_from_hash(hex_out, top100l[idx].hash)); 343 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100l[idx].val, hex_from_hash(hex_out, top100l[idx].hash));
354
355 return r - reply;
356} 344}
357 345
358static unsigned long events_per_time(unsigned long long events, time_t t) { return events / ((unsigned int)t ? (unsigned int)t : 1); } 346static unsigned long events_per_time(unsigned long long events, time_t t) { return events / ((unsigned int)t ? (unsigned int)t : 1); }
359 347
360static size_t stats_connections_mrtg(char *reply) { 348static void stats_connections_mrtg(char **reply, const char *reply_end) {
361 ot_time t = time(NULL) - ot_start_time; 349 ot_time t = time(NULL) - ot_start_time;
362 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", 350 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.",
363 ot_overall_tcp_connections + ot_overall_udp_connections, 351 ot_overall_tcp_connections + ot_overall_udp_connections,
364 ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), 352 ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600),
365 events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t), 353 events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
366 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 354 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
367} 355}
368 356
369static size_t stats_udpconnections_mrtg(char *reply) { 357static void stats_udpconnections_mrtg(char **reply, const char *reply_end) {
370 ot_time t = time(NULL) - ot_start_time; 358 ot_time t = time(NULL) - ot_start_time;
371 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_connections, 359 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_connections,
372 ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), events_per_time(ot_overall_udp_connections, t), 360 ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), events_per_time(ot_overall_udp_connections, t),
373 events_per_time(ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 361 events_per_time(ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
374} 362}
375 363
376static size_t stats_tcpconnections_mrtg(char *reply) { 364static void stats_tcpconnections_mrtg(char **reply, const char *reply_end) {
377 time_t t = time(NULL) - ot_start_time; 365 time_t t = time(NULL) - ot_start_time;
378 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_connections, 366 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_connections,
379 ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections, t), 367 ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections, t),
380 events_per_time(ot_overall_tcp_successfulannounces, t)); 368 events_per_time(ot_overall_tcp_successfulannounces, t));
381} 369}
382 370
383static size_t stats_scrape_mrtg(char *reply) { 371static void stats_scrape_mrtg(char **reply, const char *reply_end) {
384 time_t t = time(NULL) - ot_start_time; 372 time_t t = time(NULL) - ot_start_time;
385 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", ot_overall_tcp_successfulscrapes, 373 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)",
386 ot_overall_udp_successfulscrapes, (int)t, (int)(t / 3600), 374 ot_overall_tcp_successfulscrapes, ot_overall_udp_successfulscrapes, (int)t, (int)(t / 3600),
387 events_per_time((ot_overall_tcp_successfulscrapes + ot_overall_udp_successfulscrapes), t)); 375 events_per_time((ot_overall_tcp_successfulscrapes + ot_overall_udp_successfulscrapes), t));
388} 376}
389 377
390static size_t stats_fullscrapes_mrtg(char *reply) { 378static void stats_fullscrapes_mrtg(char **reply, const char *reply_end) {
391 ot_time t = time(NULL) - ot_start_time; 379 ot_time t = time(NULL) - ot_start_time;
392 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", ot_full_scrape_count * 1000, 380 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.",
393 ot_full_scrape_size, (int)t, (int)(t / 3600), events_per_time(ot_full_scrape_count, t), events_per_time(ot_full_scrape_size, t)); 381 ot_full_scrape_count * 1000, ot_full_scrape_size, (int)t, (int)(t / 3600), events_per_time(ot_full_scrape_count, t),
382 events_per_time(ot_full_scrape_size, t));
394} 383}
395 384
396static size_t stats_peers_mrtg(char *reply) { 385static void stats_peers_mrtg(char **reply, const char *reply_end) {
397 torrent_stats stats = {0, 0, 0}; 386 torrent_stats stats = {0, 0, 0};
398 387
399 iterate_all_torrents(torrent_statter, (uintptr_t)&stats); 388 iterate_all_torrents(torrent_statter, (uintptr_t)&stats);
400 389
401 return sprintf(reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", stats.peer_count, stats.seed_count, stats.torrent_count); 390 fmt_append(reply, reply_end, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", stats.peer_count, stats.seed_count,
391 stats.torrent_count);
402} 392}
403 393
404static size_t stats_torrents_mrtg(char *reply) { 394static void stats_torrents_mrtg(char **reply, const char *reply_end) {
405 size_t torrent_count = mutex_get_torrent_count(); 395 size_t torrent_count = mutex_get_torrent_count();
406 396
407 return sprintf(reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", torrent_count, (size_t)0, torrent_count); 397 fmt_append(reply, reply_end, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", torrent_count, (size_t)0, torrent_count);
408} 398}
409 399
410static size_t stats_httperrors_txt(char *reply) { 400static void stats_httperrors_txt(char **reply, const char *reply_end) {
411 return sprintf(reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", ot_failed_request_counts[0], 401 fmt_append(reply, reply_end, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n",
412 ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[3], ot_failed_request_counts[4], 402 ot_failed_request_counts[0], ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[3],
413 ot_failed_request_counts[5], ot_failed_request_counts[6]); 403 ot_failed_request_counts[4], ot_failed_request_counts[5], ot_failed_request_counts[6]);
414} 404}
415 405
416static size_t stats_return_renew_bucket(char *reply) { 406static void stats_return_renew_bucket(char **reply, const char *reply_end) {
417 char *r = reply; 407 int i;
418 int i;
419 408
420 for (i = 0; i < OT_PEER_TIMEOUT; ++i) 409 for (i = 0; i < OT_PEER_TIMEOUT; ++i)
421 r += sprintf(r, "%02i %llu\n", i, ot_renewed[i]); 410 fmt_append(reply, reply_end, "%02i %llu\n", i, ot_renewed[i]);
422 return r - reply;
423} 411}
424 412
425static size_t stats_return_sync_mrtg(char *reply) { 413static void stats_return_sync_mrtg(char **reply, const char *reply_end) {
426 ot_time t = time(NULL) - ot_start_time; 414 ot_time t = time(NULL) - ot_start_time;
427 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", ot_overall_sync_count, 0LL, (int)t, 415 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", ot_overall_sync_count, 0LL,
428 (int)(t / 3600), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t), 416 (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
429 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 417 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
430} 418}
431 419
432static size_t stats_return_completed_mrtg(char *reply) { 420static void stats_return_completed_mrtg(char **reply, const char *reply_end) {
433 ot_time t = time(NULL) - ot_start_time; 421 ot_time t = time(NULL) - ot_start_time;
434 422
435 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", ot_overall_completed, 0LL, (int)t, (int)(t / 3600), 423 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", ot_overall_completed, 0LL, (int)t, (int)(t / 3600),
436 events_per_time(ot_overall_completed, t / 3600)); 424 events_per_time(ot_overall_completed, t / 3600));
437} 425}
438 426
439#ifdef WANT_LOG_NUMWANT 427#ifdef WANT_LOG_NUMWANT
440extern unsigned long long numwants[201]; 428extern unsigned long long numwants[201];
441static size_t stats_return_numwants(char *reply) { 429static void stats_return_numwants(char **reply, const char *reply_end) {
442 char *r = reply; 430 int i;
443 int i;
444 for (i = 0; i <= 200; ++i) 431 for (i = 0; i <= 200; ++i)
445 r += sprintf(r, "%03d => %lld\n", i, numwants[i]); 432 fmt_append(reply, reply_end, "%03d => %lld\n", i, numwants[i]);
446 return r - reply;
447} 433}
448#endif 434#endif
449 435
@@ -461,17 +447,14 @@ static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector,
461 return; 447 return;
462 re = r + 32 * OT_STATS_TMPSIZE; 448 re = r + 32 * OT_STATS_TMPSIZE;
463 } 449 }
464 r += sprintf(r, "%08ld: ", loglist->time); 450 char ip_readable[64];
465 r += ip_format(r, loglist->ip); 451
466 *r++ = '\n'; 452 ip_readable[ip_format(ip_readable, loglist->ip)] = 0;
467 memcpy(r, loglist->data, loglist->size); 453 fmt_append(&r, re, "%08ld: %s\n", loglist->time, ip_readable);
468 r += loglist->size; 454 fmt_bytes(&r, re, loglist->data, loglist->size);
469 *r++ = '\n'; 455 fmt_append(&r, re, "\n*\n\n");
470 *r++ = '*';
471 *r++ = '\n';
472 *r++ = '\n';
473 456
474 llnext = loglist->next; 457 llnext = loglist->next;
475 free(loglist->data); 458 free(loglist->data);
476 free(loglist); 459 free(loglist);
477 loglist = llnext; 460 loglist = llnext;
@@ -480,124 +463,137 @@ static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector,
480} 463}
481#endif 464#endif
482 465
483static size_t stats_return_everything(char *reply) { 466static void stats_return_everything(char **reply, const char *reply_end) {
484 torrent_stats stats = {0, 0, 0}; 467 torrent_stats stats = {0, 0, 0};
485 int i; 468 int i;
486 char *r = reply;
487 469
488 iterate_all_torrents(torrent_statter, (uintptr_t)&stats); 470 iterate_all_torrents(torrent_statter, (uintptr_t)&stats);
489 471
490 r += sprintf(r, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 472 fmt_append(reply, reply_end, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
491 r += sprintf(r, "<stats>\n"); 473 fmt_append(reply, reply_end, "<stats>\n");
492 r += sprintf(r, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id); 474 fmt_append(reply, reply_end, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id);
493 r += sprintf(r, " <version>\n"); 475 fmt_append(reply, reply_end, " <version>\n");
494 r += stats_return_tracker_version(r); 476 stats_return_tracker_version(reply, reply_end);
495 r += sprintf(r, " </version>\n"); 477 fmt_append(reply, reply_end, " </version>\n");
496 r += sprintf(r, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time)); 478 fmt_append(reply, reply_end, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time));
497 r += sprintf(r, " <torrents>\n"); 479 fmt_append(reply, reply_end, " <torrents>\n");
498 r += sprintf(r, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count()); 480 fmt_append(reply, reply_end, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count());
499 r += sprintf(r, " <count_iterator>%llu</count_iterator>\n", stats.torrent_count); 481 fmt_append(reply, reply_end, " <count_iterator>%llu</count_iterator>\n", stats.torrent_count);
500 r += sprintf(r, " </torrents>\n"); 482 fmt_append(reply, reply_end, " </torrents>\n");
501 r += sprintf(r, " <peers>\n <count>%llu</count>\n </peers>\n", stats.peer_count); 483 fmt_append(reply, reply_end, " <peers>\n <count>%llu</count>\n </peers>\n", stats.peer_count);
502 r += sprintf(r, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count); 484 fmt_append(reply, reply_end, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count);
503 r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); 485 fmt_append(reply, reply_end, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed);
504 r += sprintf(r, " <connections>\n"); 486 fmt_append(reply, reply_end, " <connections>\n");
505 r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", 487 fmt_append(reply, reply_end, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n",
506 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes); 488 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes);
507 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", 489 fmt_append(reply, reply_end, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n",
508 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, 490 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes,
509 ot_overall_udp_connectionidmissmatches); 491 ot_overall_udp_connectionidmissmatches);
510 r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); 492 fmt_append(reply, reply_end, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count);
511 r += sprintf(r, " </connections>\n"); 493 fmt_append(reply, reply_end, " </connections>\n");
512 r += sprintf(r, " <debug>\n"); 494 fmt_append(reply, reply_end, " <debug>\n");
513 r += sprintf(r, " <renew>\n"); 495 fmt_append(reply, reply_end, " <renew>\n");
514 for (i = 0; i < OT_PEER_TIMEOUT; ++i) 496 for (i = 0; i < OT_PEER_TIMEOUT; ++i)
515 r += sprintf(r, " <count interval=\"%02i\">%llu</count>\n", i, ot_renewed[i]); 497 fmt_append(reply, reply_end, " <count interval=\"%02i\">%llu</count>\n", i, ot_renewed[i]);
516 r += sprintf(r, " </renew>\n"); 498 fmt_append(reply, reply_end, " </renew>\n");
517 r += sprintf(r, " <http_error>\n"); 499 fmt_append(reply, reply_end, " <http_error>\n");
518 for (i = 0; i < CODE_HTTPERROR_COUNT; ++i) 500 for (i = 0; i < CODE_HTTPERROR_COUNT; ++i)
519 r += sprintf(r, " <count code=\"%s\">%llu</count>\n", ot_failed_request_names[i], ot_failed_request_counts[i]); 501 fmt_append(reply, reply_end, " <count code=\"%s\">%llu</count>\n", ot_failed_request_names[i], ot_failed_request_counts[i]);
520 r += sprintf(r, " </http_error>\n"); 502 fmt_append(reply, reply_end, " </http_error>\n");
521 r += sprintf(r, " <mutex_stall>\n <count>%llu</count>\n </mutex_stall>\n", ot_overall_stall_count); 503 fmt_append(reply, reply_end, " <mutex_stall>\n <count>%llu</count>\n </mutex_stall>\n", ot_overall_stall_count);
522 r += sprintf(r, " </debug>\n"); 504 fmt_append(reply, reply_end, " </debug>\n");
523 r += sprintf(r, "</stats>"); 505 fmt_append(reply, reply_end, "</stats>");
524 return r - reply;
525} 506}
526 507
527size_t stats_return_tracker_version(char *reply) { 508void stats_return_tracker_version(char **reply, const char *reply_end) {
528#define QUOTE(name) #name 509#define QUOTE(name) #name
529#define SQUOTE(name) QUOTE(name) 510#define SQUOTE(name) QUOTE(name)
530 return sprintf(reply, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n"); 511 fmt_append(reply, reply_end, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n");
531} 512}
532 513
533size_t return_stats_for_tracker(char *reply, int mode, int format) { 514void return_stats_for_tracker(char **reply, const char *reply_end, int mode, int format) {
534 (void)format; 515 (void)format;
535 switch (mode & TASK_TASK_MASK) { 516 switch (mode & TASK_TASK_MASK) {
536 case TASK_STATS_CONNS: 517 case TASK_STATS_CONNS:
537 return stats_connections_mrtg(reply); 518 stats_connections_mrtg(reply, reply_end);
519 break;
538 case TASK_STATS_SCRAPE: 520 case TASK_STATS_SCRAPE:
539 return stats_scrape_mrtg(reply); 521 stats_scrape_mrtg(reply, reply_end);
522 break;
540 case TASK_STATS_UDP: 523 case TASK_STATS_UDP:
541 return stats_udpconnections_mrtg(reply); 524 stats_udpconnections_mrtg(reply, reply_end);
525 break;
542 case TASK_STATS_TCP: 526 case TASK_STATS_TCP:
543 return stats_tcpconnections_mrtg(reply); 527 stats_tcpconnections_mrtg(reply, reply_end);
528 break;
544 case TASK_STATS_FULLSCRAPE: 529 case TASK_STATS_FULLSCRAPE:
545 return stats_fullscrapes_mrtg(reply); 530 stats_fullscrapes_mrtg(reply, reply_end);
531 break;
546 case TASK_STATS_COMPLETED: 532 case TASK_STATS_COMPLETED:
547 return stats_return_completed_mrtg(reply); 533 stats_return_completed_mrtg(reply, reply_end);
534 break;
548 case TASK_STATS_HTTPERRORS: 535 case TASK_STATS_HTTPERRORS:
549 return stats_httperrors_txt(reply); 536 stats_httperrors_txt(reply, reply_end);
537 break;
550 case TASK_STATS_VERSION: 538 case TASK_STATS_VERSION:
551 return stats_return_tracker_version(reply); 539 stats_return_tracker_version(reply, reply_end);
540 break;
552 case TASK_STATS_RENEW: 541 case TASK_STATS_RENEW:
553 return stats_return_renew_bucket(reply); 542 stats_return_renew_bucket(reply, reply_end);
543 break;
554 case TASK_STATS_SYNCS: 544 case TASK_STATS_SYNCS:
555 return stats_return_sync_mrtg(reply); 545 stats_return_sync_mrtg(reply, reply_end);
546 break;
556#ifdef WANT_LOG_NUMWANT 547#ifdef WANT_LOG_NUMWANT
557 case TASK_STATS_NUMWANTS: 548 case TASK_STATS_NUMWANTS:
558 return stats_return_numwants(reply); 549 stats_return_numwants(reply, reply_end);
550 break;
559#endif 551#endif
560 default: 552 default:
561 return 0; 553 break;
562 } 554 }
563} 555}
564 556
565static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) { 557static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) {
566 char *r; 558 char *r;
559 const char *r_end;
567 560
568 *iovec_entries = 0; 561 *iovec_entries = 0;
569 *iovector = NULL; 562 *iovector = NULL;
570 if (!(r = iovec_new_chunk(iovec_entries, iovector, OT_STATS_TMPSIZE))) 563 if (!(r = iovec_new_chunk(iovec_entries, iovector, OT_STATS_TMPSIZE)))
571 return; 564 return;
565 r_end = r + OT_STATS_TMPSIZE;
572 566
573 switch (mode & TASK_TASK_MASK) { 567 switch (mode & TASK_TASK_MASK) {
574 case TASK_STATS_TORRENTS: 568 case TASK_STATS_TORRENTS:
575 r += stats_torrents_mrtg(r); 569 stats_torrents_mrtg(&r, r_end);
576 break; 570 break;
577 case TASK_STATS_PEERS: 571 case TASK_STATS_PEERS:
578 r += stats_peers_mrtg(r); 572 stats_peers_mrtg(&r, r_end);
579 break; 573 break;
580 case TASK_STATS_SLASH24S: 574 case TASK_STATS_SLASH24S:
581 r += stats_slash24s_txt(r, 128); 575 stats_slash24s_txt(&r, r_end, 128);
582 break; 576 break;
583 case TASK_STATS_TOP10: 577 case TASK_STATS_TOP10:
584 r += stats_top_txt(r, 10); 578 stats_top_txt(&r, r_end, 10);
585 break; 579 break;
586 case TASK_STATS_TOP100: 580 case TASK_STATS_TOP100:
587 r = iovec_next_chunk(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE); 581 r = iovec_next_chunk(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE);
588 if (!r) 582 if (!r)
589 return; 583 return;
590 r += stats_top_txt(r, 100); 584 r_end = r + 4 * OT_STATS_TMPSIZE;
585 stats_top_txt(&r, r_end, 100);
591 break; 586 break;
592 case TASK_STATS_EVERYTHING: 587 case TASK_STATS_EVERYTHING:
593 r = iovec_next_chunk(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT); 588 r = iovec_next_chunk(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT);
594 if (!r) 589 if (!r)
595 return; 590 return;
596 r += stats_return_everything(r); 591 r_end = r + OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT;
592 stats_return_everything(&r, r_end);
597 break; 593 break;
598#ifdef WANT_SPOT_WOODPECKER 594#ifdef WANT_SPOT_WOODPECKER
599 case TASK_STATS_WOODPECKERS: 595 case TASK_STATS_WOODPECKERS:
600 r += stats_return_woodpeckers(r, 128); 596 stats_return_woodpeckers(&r, r_end, 128);
601 break; 597 break;
602#endif 598#endif
603#ifdef WANT_FULLLOG_NETWORKS 599#ifdef WANT_FULLLOG_NETWORKS