aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nse/gnunet-nse-profiler.c291
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;
247static struct OpListEntry *oplist_tail; 256static struct OpListEntry *oplist_tail;
248 257
249/** 258/**
250 * The get stats operation
251 */
252static struct GNUNET_TESTBED_Operation *get_stats_op;
253
254/**
255 * Are we shutting down 259 * Are we shutting down
256 */ 260 */
257static int shutting_down; 261static 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 */
419static int
420stat_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 */
453static void *
454stat_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 */
470static void
471stat_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 */
496static void
497stat_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 */
467static void
468stats_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 */
538static int
539statistics_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
595finish_round (void *cls, 586finish_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