diff options
-rw-r--r-- | src/nse/gnunet-nse-profiler.c | 291 |
1 files changed, 132 insertions, 159 deletions
diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c index 0ba36749c..7803ca947 100644 --- a/src/nse/gnunet-nse-profiler.c +++ b/src/nse/gnunet-nse-profiler.c | |||
@@ -71,6 +71,15 @@ struct NSEPeer | |||
71 | */ | 71 | */ |
72 | struct GNUNET_TESTBED_Operation *nse_op; | 72 | struct GNUNET_TESTBED_Operation *nse_op; |
73 | 73 | ||
74 | /** | ||
75 | * Testbed operation to connect to statistics service | ||
76 | */ | ||
77 | struct GNUNET_TESTBED_Operation *stat_op; | ||
78 | |||
79 | /** | ||
80 | * Handle to the statistics service | ||
81 | */ | ||
82 | struct GNUNET_STATISTICS_Handle *sh; | ||
74 | }; | 83 | }; |
75 | 84 | ||
76 | 85 | ||
@@ -247,11 +256,6 @@ static struct OpListEntry *oplist_head; | |||
247 | static struct OpListEntry *oplist_tail; | 256 | static struct OpListEntry *oplist_tail; |
248 | 257 | ||
249 | /** | 258 | /** |
250 | * The get stats operation | ||
251 | */ | ||
252 | static struct GNUNET_TESTBED_Operation *get_stats_op; | ||
253 | |||
254 | /** | ||
255 | * Are we shutting down | 259 | * Are we shutting down |
256 | */ | 260 | */ |
257 | static int shutting_down; | 261 | static int shutting_down; |
@@ -271,6 +275,8 @@ close_monitor_connections () | |||
271 | { | 275 | { |
272 | if (NULL != pos->nse_op) | 276 | if (NULL != pos->nse_op) |
273 | GNUNET_TESTBED_operation_done (pos->nse_op); | 277 | GNUNET_TESTBED_operation_done (pos->nse_op); |
278 | if (NULL != pos->stat_op) | ||
279 | GNUNET_TESTBED_operation_done (pos->stat_op); | ||
274 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); | 280 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); |
275 | GNUNET_free (pos); | 281 | GNUNET_free (pos); |
276 | } | 282 | } |
@@ -298,11 +304,6 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
298 | shutting_down = GNUNET_YES; | 304 | shutting_down = GNUNET_YES; |
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | 305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); |
300 | close_monitor_connections (); | 306 | close_monitor_connections (); |
301 | if (NULL != get_stats_op) | ||
302 | { | ||
303 | GNUNET_TESTBED_operation_done (get_stats_op); | ||
304 | get_stats_op = NULL; | ||
305 | } | ||
306 | if (NULL != data_file) | 307 | if (NULL != data_file) |
307 | { | 308 | { |
308 | GNUNET_DISK_file_close (data_file); | 309 | GNUNET_DISK_file_close (data_file); |
@@ -405,6 +406,115 @@ nse_disconnect_adapter (void *cls, | |||
405 | 406 | ||
406 | 407 | ||
407 | /** | 408 | /** |
409 | * Callback function to process statistic values. | ||
410 | * | ||
411 | * @param cls struct StatsContext | ||
412 | * @param peer the peer the statistics belong to | ||
413 | * @param subsystem name of subsystem that created the statistic | ||
414 | * @param name the name of the datum | ||
415 | * @param value the current value | ||
416 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
417 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
418 | */ | ||
419 | static int | ||
420 | stat_iterator (void *cls, const char *subsystem, const char *name, | ||
421 | uint64_t value, int is_persistent) | ||
422 | { | ||
423 | char *output_buffer; | ||
424 | struct GNUNET_TIME_Absolute now; | ||
425 | size_t size; | ||
426 | unsigned int flag; | ||
427 | |||
428 | GNUNET_assert (NULL != data_file); | ||
429 | now = GNUNET_TIME_absolute_get (); | ||
430 | flag = strcasecmp (subsystem, "core"); | ||
431 | if (0 != flag) | ||
432 | flag = 1; | ||
433 | size = GNUNET_asprintf (&output_buffer, "%llu %llu %u\n", | ||
434 | now.abs_value/1000, value, flag); | ||
435 | if (size != GNUNET_DISK_file_write (data_file, output_buffer, size)) | ||
436 | { | ||
437 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | ||
438 | return GNUNET_SYSERR; | ||
439 | } | ||
440 | return GNUNET_OK; | ||
441 | } | ||
442 | |||
443 | |||
444 | /** | ||
445 | * Called to open a connection to the peer's statistics | ||
446 | * | ||
447 | * @param cls peer context | ||
448 | * @param cfg configuration of the peer to connect to; will be available until | ||
449 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
450 | * from GNUNET_TESTBED_service_connect() | ||
451 | * @return service handle to return in 'op_result', NULL on error | ||
452 | */ | ||
453 | static void * | ||
454 | stat_connect_adapter (void *cls, | ||
455 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
456 | { | ||
457 | struct NSEPeer *peer = cls; | ||
458 | |||
459 | peer->sh = GNUNET_STATISTICS_create ("nse-profiler", cfg); | ||
460 | return peer->sh; | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Called to disconnect from peer's statistics service | ||
466 | * | ||
467 | * @param cls peer context | ||
468 | * @param op_result service handle returned from the connect adapter | ||
469 | */ | ||
470 | static void | ||
471 | stat_disconnect_adapter (void *cls, void *op_result) | ||
472 | { | ||
473 | struct NSEPeer *peer = cls; | ||
474 | |||
475 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel | ||
476 | (peer->sh, "core", "# peers connected", | ||
477 | stat_iterator, peer)); | ||
478 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel | ||
479 | (peer->sh, "nse", "# peers connected", | ||
480 | stat_iterator, peer)); | ||
481 | GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); | ||
482 | peer->sh = NULL; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Called after successfully opening a connection to a peer's statistics | ||
488 | * service; we register statistics monitoring for CORE and NSE here. | ||
489 | * | ||
490 | * @param cls the callback closure from functions generating an operation | ||
491 | * @param op the operation that has been finished | ||
492 | * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() | ||
493 | * @param emsg error message in case the operation has failed; will be NULL if | ||
494 | * operation has executed successfully. | ||
495 | */ | ||
496 | static void | ||
497 | stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, | ||
498 | void *ca_result, const char *emsg ) | ||
499 | { | ||
500 | struct GNUNET_STATISTICS_Handle *sh = ca_result; | ||
501 | struct NSEPeer *peer = cls; | ||
502 | |||
503 | if (NULL != emsg) | ||
504 | { | ||
505 | GNUNET_break (0); | ||
506 | return; | ||
507 | } | ||
508 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch | ||
509 | (sh, "core", "# peers connected", | ||
510 | stat_iterator, peer)); | ||
511 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch | ||
512 | (sh, "nse", "# peers connected", | ||
513 | stat_iterator, peer)); | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
408 | * Task run to connect to the NSE and statistics services to a subset of | 518 | * Task run to connect to the NSE and statistics services to a subset of |
409 | * all of the running peers. | 519 | * all of the running peers. |
410 | */ | 520 | */ |
@@ -436,6 +546,16 @@ connect_nse_service () | |||
436 | &nse_connect_adapter, | 546 | &nse_connect_adapter, |
437 | &nse_disconnect_adapter, | 547 | &nse_disconnect_adapter, |
438 | current_peer); | 548 | current_peer); |
549 | if (NULL != data_file) | ||
550 | current_peer->stat_op | ||
551 | = GNUNET_TESTBED_service_connect (NULL, | ||
552 | current_peer->daemon, | ||
553 | "statistics", | ||
554 | stat_comp_cb, | ||
555 | current_peer, | ||
556 | &stat_connect_adapter, | ||
557 | &stat_disconnect_adapter, | ||
558 | current_peer); | ||
439 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); | 559 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); |
440 | if (++connections == connection_limit) | 560 | if (++connections == connection_limit) |
441 | break; | 561 | break; |
@@ -455,135 +575,6 @@ next_round (void *cls, | |||
455 | 575 | ||
456 | 576 | ||
457 | /** | 577 | /** |
458 | * Continuation called by the "get_all" and "get" functions at the | ||
459 | * end of a round. Obtains the final statistics and writes them to | ||
460 | * the file, then either starts the next round, or, if this was the | ||
461 | * last round, terminates the run. | ||
462 | * | ||
463 | * @param cls struct StatsContext | ||
464 | * @param op operation handle | ||
465 | * @param emsg error message, NULL on success | ||
466 | */ | ||
467 | static void | ||
468 | stats_finished_callback (void *cls, | ||
469 | struct GNUNET_TESTBED_Operation *op, | ||
470 | const char *emsg) | ||
471 | { | ||
472 | struct StatsContext *stats_context = cls; | ||
473 | char buf[512]; | ||
474 | size_t buf_len; | ||
475 | |||
476 | GNUNET_TESTBED_operation_done (get_stats_op); | ||
477 | get_stats_op = NULL; | ||
478 | if (NULL != emsg) | ||
479 | { | ||
480 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
481 | "Failed to get statistics: %s\n", | ||
482 | emsg); | ||
483 | GNUNET_SCHEDULER_shutdown (); | ||
484 | GNUNET_free (stats_context); | ||
485 | return; | ||
486 | } | ||
487 | LOG_DEBUG ("Finished collecting statistics\n"); | ||
488 | if (NULL != data_file) | ||
489 | { | ||
490 | /* Stats lookup successful, write out data */ | ||
491 | buf_len = | ||
492 | GNUNET_snprintf (buf, sizeof (buf), | ||
493 | "TOTAL_NSE_RECEIVED_MESSAGES_%u: %u \n", | ||
494 | current_round, | ||
495 | stats_context->total_nse_received_messages); | ||
496 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
497 | buf_len = | ||
498 | GNUNET_snprintf (buf, sizeof (buf), | ||
499 | "TOTAL_NSE_TRANSMITTED_MESSAGES_%u: %u\n", | ||
500 | current_round, | ||
501 | stats_context->total_nse_transmitted_messages); | ||
502 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
503 | buf_len = | ||
504 | GNUNET_snprintf (buf, sizeof (buf), | ||
505 | "TOTAL_NSE_CROSS_%u: %u \n", | ||
506 | current_round, | ||
507 | stats_context->total_nse_cross); | ||
508 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
509 | buf_len = | ||
510 | GNUNET_snprintf (buf, sizeof (buf), | ||
511 | "TOTAL_NSE_EXTRA_%u: %u \n", | ||
512 | current_round, | ||
513 | stats_context->total_nse_extra); | ||
514 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
515 | buf_len = | ||
516 | GNUNET_snprintf (buf, sizeof (buf), | ||
517 | "TOTAL_NSE_DISCARDED_%u: %u \n", | ||
518 | current_round, | ||
519 | stats_context->total_discarded); | ||
520 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
521 | } | ||
522 | GNUNET_SCHEDULER_add_now (&next_round, NULL); | ||
523 | GNUNET_free (stats_context); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Callback function to process statistic values. | ||
529 | * | ||
530 | * @param cls struct StatsContext | ||
531 | * @param peer the peer the statistics belong to | ||
532 | * @param subsystem name of subsystem that created the statistic | ||
533 | * @param name the name of the datum | ||
534 | * @param value the current value | ||
535 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
536 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
537 | */ | ||
538 | static int | ||
539 | statistics_iterator (void *cls, | ||
540 | const struct GNUNET_TESTBED_Peer *peer, | ||
541 | const char *subsystem, const char *name, uint64_t value, | ||
542 | int is_persistent) | ||
543 | { | ||
544 | struct StatsContext *stats_context = cls; | ||
545 | char buf[512]; | ||
546 | size_t buf_len; | ||
547 | |||
548 | if (0 != strcasecmp (subsystem, "nse")) | ||
549 | return GNUNET_SYSERR; | ||
550 | if (0 == strcmp (name, "# flood messages received")) | ||
551 | { | ||
552 | stats_context->total_nse_received_messages += value; | ||
553 | if ( (verbose > 1) && | ||
554 | (NULL != data_file) ) | ||
555 | { | ||
556 | buf_len = | ||
557 | GNUNET_snprintf (buf, sizeof (buf), | ||
558 | "%p %u RECEIVED\n", | ||
559 | peer, value); | ||
560 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
561 | } | ||
562 | } | ||
563 | if (0 == strcmp (name, "# flood messages transmitted")) | ||
564 | { | ||
565 | stats_context->total_nse_transmitted_messages += value; | ||
566 | if ( (verbose > 1) && | ||
567 | (NULL != data_file) ) | ||
568 | { | ||
569 | buf_len = | ||
570 | GNUNET_snprintf (buf, sizeof (buf), | ||
571 | "%p %u TRANSMITTED\n", | ||
572 | peer, value); | ||
573 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
574 | } | ||
575 | } | ||
576 | if (0 == strcmp (name, "# cross messages")) | ||
577 | stats_context->total_nse_cross += value; | ||
578 | if (0 == strcmp (name, "# extra messages")) | ||
579 | stats_context->total_nse_extra += value; | ||
580 | if (0 == strcmp (name, "# flood messages discarded (clock skew too large)")) | ||
581 | stats_context->total_discarded += value; | ||
582 | return GNUNET_OK; | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * We're at the end of a round. Stop monitoring, write total | 578 | * We're at the end of a round. Stop monitoring, write total |
588 | * number of connections to log and get full stats. Then trigger | 579 | * number of connections to log and get full stats. Then trigger |
589 | * the next round. | 580 | * the next round. |
@@ -595,29 +586,11 @@ static void | |||
595 | finish_round (void *cls, | 586 | finish_round (void *cls, |
596 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 587 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
597 | { | 588 | { |
598 | struct StatsContext *stats_context; | ||
599 | char buf[1024]; | ||
600 | size_t buf_len; | ||
601 | |||
602 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 589 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
603 | return; | 590 | return; |
604 | LOG (GNUNET_ERROR_TYPE_INFO, "Have %u connections\n", total_connections); | 591 | LOG (GNUNET_ERROR_TYPE_INFO, "Have %u connections\n", total_connections); |
605 | if (NULL != data_file) | 592 | close_monitor_connections (); |
606 | { | 593 | GNUNET_SCHEDULER_add_now (&next_round, NULL); |
607 | buf_len = GNUNET_snprintf (buf, sizeof (buf), | ||
608 | "CONNECTIONS_0: %u\n", | ||
609 | total_connections); | ||
610 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
611 | } | ||
612 | close_monitor_connections (); | ||
613 | stats_context = GNUNET_malloc (sizeof (struct StatsContext)); | ||
614 | get_stats_op = | ||
615 | GNUNET_TESTBED_get_statistics (num_peers_in_round[current_round], | ||
616 | daemons, | ||
617 | "nse", NULL, | ||
618 | &statistics_iterator, | ||
619 | &stats_finished_callback, | ||
620 | stats_context); | ||
621 | } | 594 | } |
622 | 595 | ||
623 | 596 | ||