From: Matthias Wachs Date: Wed, 29 May 2013 13:20:41 +0000 (+0000) Subject: changes X-Git-Tag: initial-import-from-subversion-38251~8876 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=0f821828934dfa4959c75f8ca06be651fd535001;p=oweals%2Fgnunet.git changes --- diff --git a/src/experimentation/Makefile.am b/src/experimentation/Makefile.am index aaa205460..49876adc1 100644 --- a/src/experimentation/Makefile.am +++ b/src/experimentation/Makefile.am @@ -18,7 +18,7 @@ endif if HAVE_EXPERIMENTAL - TEXT_EXP_CLIQUE = test_experimentation_clique + TEXT_EXP_CLIQUE = test_experimentation_clique_connect endif check_PROGRAMS = \ @@ -44,9 +44,9 @@ gnunet_daemon_experimentation_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la -test_experimentation_clique_SOURCES = \ - test_experimentation_clique.c -test_experimentation_clique_LDADD = \ +test_experimentation_clique_connect_SOURCES = \ + test_experimentation_clique_connect.c +test_experimentation_clique_connect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la diff --git a/src/experimentation/gnunet-daemon-experimentation.h b/src/experimentation/gnunet-daemon-experimentation.h index 8be39fa93..2d19720d0 100644 --- a/src/experimentation/gnunet-daemon-experimentation.h +++ b/src/experimentation/gnunet-daemon-experimentation.h @@ -291,7 +291,7 @@ GNUNET_EXPERIMENTATION_experiments_stop (); * Start the scheduler component */ void -GNUNET_EXPERIMENTATION_scheduler_add (struct Experiment *e); +GNUNET_EXPERIMENTATION_scheduler_add (struct Node *n, struct Experiment *e); /** * Start the scheduler component diff --git a/src/experimentation/gnunet-daemon-experimentation_nodes.c b/src/experimentation/gnunet-daemon-experimentation_nodes.c index 2e8628088..8631e5d58 100644 --- a/src/experimentation/gnunet-daemon-experimentation_nodes.c +++ b/src/experimentation/gnunet-daemon-experimentation_nodes.c @@ -225,7 +225,7 @@ size_t send_request_cb (void *cls, size_t bufsize, void *buf) msg.capabilities = htonl (GSE_node_capabilities); msg.issuer_count = htonl (GSE_my_issuer_count); memcpy (buf, &msg, msg_size); - memcpy (&buf[msg_size], GSE_my_issuer, ri_size); + memcpy (&((char *) buf)[msg_size], GSE_my_issuer, ri_size); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Sending request to peer %s\n"), GNUNET_i2s (&n->id)); @@ -292,7 +292,7 @@ size_t send_response_cb (void *cls, size_t bufsize, void *buf) msg.capabilities = htonl (GSE_node_capabilities); msg.issuer_count = htonl (GSE_my_issuer_count); memcpy (buf, &msg, msg_size); - memcpy (&buf[msg_size], GSE_my_issuer, ri_size); + memcpy (&((char *) buf)[msg_size], GSE_my_issuer, ri_size); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Sending response to peer %s\n"), GNUNET_i2s (&n->id)); @@ -304,6 +304,7 @@ static void get_experiments_cb (struct Node *n, struct Experiment *e) { static int counter = 0; + //size_t start_size; if (NULL == e) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Added %u experiments for peer %s\n"), @@ -314,7 +315,14 @@ get_experiments_cb (struct Node *n, struct Experiment *e) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting experiment `%s' with peer %s\n"), e->name, GNUNET_i2s (&n->id)); - //GNUNET_EXPERIMENTATION_scheduler_add (e); + + /* Request experiment */ +/* start_size = sizeof (struct Experimentation_Start); + GNUNET_CORE_notify_transmit_ready (ch, GNUNET_NO, 0, EXP_RESPONSE_TIMEOUT, + n->id, start_size, send_start_cb, n);*/ + + GNUNET_EXPERIMENTATION_scheduler_add (n, e); + counter ++; } diff --git a/src/experimentation/gnunet-daemon-experimentation_scheduler.c b/src/experimentation/gnunet-daemon-experimentation_scheduler.c index 39b541574..37f4f0640 100644 --- a/src/experimentation/gnunet-daemon-experimentation_scheduler.c +++ b/src/experimentation/gnunet-daemon-experimentation_scheduler.c @@ -31,11 +31,21 @@ #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" +enum ExperimentState +{ + NOT_RUNNING, + REQUESTED, + STARTED, + STOPPED +}; + struct ScheduledExperiment { struct ScheduledExperiment *next; struct ScheduledExperiment *prev; struct Experiment *e; + struct Node *n; + int state; GNUNET_SCHEDULER_TaskIdentifier task; }; @@ -43,27 +53,70 @@ struct ScheduledExperiment *list_head; struct ScheduledExperiment *list_tail; +static void +request_timeout (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc) +{ + struct ScheduledExperiment *se = cls; + se->task = GNUNET_SCHEDULER_NO_TASK; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer `%s' did not respond to request for experiment `%s'\n", + GNUNET_i2s (&se->n->id), se->e->name); + + GNUNET_CONTAINER_DLL_remove (list_head, list_tail, se); + GNUNET_free (se); + + /* Remove experiment */ +} + static void run (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc) { struct ScheduledExperiment *se = cls; - //struct GNUNET_TIME_Relative end; + struct GNUNET_TIME_Relative end; se->task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Running `%s'\n", se->e->name); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Executing `%s'\n", se->e->name); + -// end = GNUNET_TIME_absolute_get_remaining(se->e->stop); -// if (0 < end.rel_value) -// return; /* End of experiment is reached */ + if (NOT_RUNNING == se->state) + { + /* Send start message */ + //GNUNET_EXPERIMENT_nodes_request_start (se->e); + se->state = REQUESTED; + se->task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &request_timeout, se); + return; + } + else if (REQUESTED == se->state) + { + /* Already requested */ + return; + } + else if (STARTED == se->state) + { + /* Experiment is running */ + + /* do work here */ -//GNUNET_break (0); - se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run, se); + /* Reschedule */ + end = GNUNET_TIME_absolute_get_remaining(GNUNET_TIME_absolute_add (se->e->stop, se->e->frequency)); + if (0 == end.rel_value) + { + se->state = STOPPED; + return; /* End of experiment is reached */ + } + se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run, se); + } + + else if (STOPPED == se->state) + { + /* Experiment expired */ + } } /** * Start the scheduler component */ void -GNUNET_EXPERIMENTATION_scheduler_add (struct Experiment *e) +GNUNET_EXPERIMENTATION_scheduler_add (struct Node *n, struct Experiment *e) { struct ScheduledExperiment *se; struct GNUNET_TIME_Relative start; @@ -72,18 +125,23 @@ GNUNET_EXPERIMENTATION_scheduler_add (struct Experiment *e) start = GNUNET_TIME_absolute_get_remaining(e->start); end = GNUNET_TIME_absolute_get_remaining(e->stop); + /* Add additional checks here if required */ + if (0 == end.rel_value) return; /* End of experiment is reached */ se = GNUNET_malloc (sizeof (struct ScheduledExperiment)); + se->state = NOT_RUNNING; se->e = e; + se->n = n; if (0 == start.rel_value) se->task = GNUNET_SCHEDULER_add_now (&run, se); else se->task = GNUNET_SCHEDULER_add_delayed (start, &run, se); GNUNET_CONTAINER_DLL_insert (list_head, list_tail, se); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scheduled `%s'\n", e->name); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Added experiment `%s' for node to be scheduled\n", + e->name, GNUNET_i2s(&se->n->id)); } /** diff --git a/src/experimentation/test_experimentation_clique.c b/src/experimentation/test_experimentation_clique.c deleted file mode 100644 index 0913c1a7f..000000000 --- a/src/experimentation/test_experimentation_clique.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - This file is part of GNUnet - (C) 2008--2013 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file src/testbed/test_testbed_api_topology.c - * @brief test case to connect experimentation daemons in a clique - * @author Sree Harsha Totakura - * @author Matthias Wachs - */ - -#include "platform.h" -#include "gnunet_common.h" -#include "gnunet_testbed_service.h" - - -/** - * Number of peers we want to start - */ -#define NUM_PEERS 20 - -#define NUM_ISSUER 1 - -#define NUM_EXPERIMENTS 2 - -#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20) - -/** - * Array of peers - */ -static struct GNUNET_TESTBED_Peer **peers; - -/** - * Operation handle - */ -static struct GNUNET_TESTBED_Operation *op; - -/** - * Shutdown task - */ -static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; - -/** - * Testing result - */ -static int result; - -/** - * Counter for counting overlay connections - */ -static unsigned int overlay_connects; - -/** - * Information we track for a peer in the testbed. - */ -struct ExperimentationPeer -{ - /** - * Handle with testbed. - */ - struct GNUNET_TESTBED_Peer *daemon; - - /** - * Testbed operation to connect to statistics service - */ - struct GNUNET_TESTBED_Operation *stat_op; - - /** - * Handle to the statistics service - */ - struct GNUNET_STATISTICS_Handle *sh; - - unsigned int active_nodes; - unsigned int requested_nodes; - unsigned int inactive_nodes; - unsigned int issuer; - unsigned int experiments; -}; - - -struct ExperimentationPeer ph[NUM_PEERS]; - -/** - * Shutdown nicely - * - * @param cls NULL - * @param tc the task context - */ -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - unsigned int peer; - shutdown_task = GNUNET_SCHEDULER_NO_TASK; - - for (peer = 0; peer < NUM_PEERS; peer++) - { - if (NULL != ph[peer].stat_op) - GNUNET_TESTBED_operation_done (ph[peer].stat_op); - ph[peer].stat_op = NULL; - } - - if (NULL != op) - { - GNUNET_TESTBED_operation_done (op); - op = NULL; - } - GNUNET_SCHEDULER_shutdown (); -} - -/** - * Controller event callback - * - * @param cls NULL - * @param event the controller event - */ -static void -controller_event_cb (void *cls, - const struct GNUNET_TESTBED_EventInformation *event) -{ - switch (event->type) - { - case GNUNET_TESTBED_ET_CONNECT: - overlay_connects++; - if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) - { - result = GNUNET_OK; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS); - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - { - GNUNET_SCHEDULER_cancel (shutdown_task); - } - shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); - } - break; - case GNUNET_TESTBED_ET_OPERATION_FINISHED: - break; - default: - GNUNET_break (0); - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - -static void -check_end () -{ - static int last_active_value = 0; - static int last_issuer_value = 0; - static int last_experiments_value = 0; - unsigned int peer; - unsigned int total_active = 0; - unsigned int total_inactive = 0; - unsigned int total_requested = 0; - unsigned int issuer = 0; - unsigned int experiments = 0; - - for (peer = 0; peer < NUM_PEERS; peer++) - { - total_active += ph[peer].active_nodes; - total_requested += ph[peer].requested_nodes; - total_inactive += ph[peer].inactive_nodes; - if (NUM_ISSUER == ph[peer].issuer) - issuer ++; - if (NUM_EXPERIMENTS == ph[peer].experiments) - experiments ++; - } - if ((last_issuer_value < issuer) && (issuer == NUM_PEERS)) - fprintf (stderr, "I"); - last_issuer_value = issuer; - - if ((last_experiments_value < experiments) && (experiments == NUM_PEERS)) - fprintf (stderr, "E"); - last_experiments_value = experiments; - - if (last_active_value < total_active) - fprintf (stderr, "."); - last_active_value = total_active; - - - if ((total_active == (NUM_PEERS * (NUM_PEERS -1))) && - (total_requested == 0) && (total_inactive == 0) && - (issuer == NUM_PEERS) && (experiments == NUM_PEERS)) - { - fprintf (stderr, "\n"); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers active in a clique\n", NUM_PEERS); - GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); - } -} - - - -/** - * Callback function to process statistic values. - * - * @param cls struct StatsContext - * @param subsystem name of subsystem that created the statistic - * @param name the name of the datum - * @param value the current value - * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not - * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration - */ -static int -stat_iterator (void *cls, const char *subsystem, const char *name, - uint64_t value, int is_persistent) -{ - struct ExperimentationPeer *peer = cls; - - if (0 == strcmp (name, "# nodes active")) - { - peer->active_nodes = value; - } - if (0 == strcmp (name, "# nodes inactive")) - { - peer->inactive_nodes = value; - } - if (0 == strcmp (name, "# nodes requested")) - { - peer->requested_nodes = value; - } - if (0 == strcmp (name, "# issuer")) - { - peer->issuer = value; - } - if (0 == strcmp (name, "# experiments")) - { - peer->experiments = value; - } - - check_end (); - - return GNUNET_OK; -} - -/** - * Called after successfully opening a connection to a peer's statistics - * service; we register statistics monitoring here. - * - * @param cls the callback closure from functions generating an operation - * @param op the operation that has been finished - * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() - * @param emsg error message in case the operation has failed; will be NULL if - * operation has executed successfully. - */ -static void -stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, - void *ca_result, const char *emsg ) -{ - struct GNUNET_STATISTICS_Handle *sh = ca_result; - struct ExperimentationPeer *peer = cls; - - if (NULL != emsg) - { - GNUNET_break (0); - return; - } - - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch - (sh, "experimentation", "# nodes active", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch - (sh, "experimentation", "# nodes inactive", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch - (sh, "experimentation", "# nodes requested", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch - (sh, "experimentation", "# issuer", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch - (sh, "experimentation", "# experiments", - stat_iterator, peer)); -} - -/** - * Called to open a connection to the peer's statistics - * - * @param cls peer context - * @param cfg configuration of the peer to connect to; will be available until - * GNUNET_TESTBED_operation_done() is called on the operation returned - * from GNUNET_TESTBED_service_connect() - * @return service handle to return in 'op_result', NULL on error - */ -static void * -stat_connect_adapter (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct ExperimentationPeer *peer = cls; - peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg); - if (NULL == peer->sh) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n"); - return peer->sh; -} - - -/** - * Called to disconnect from peer's statistics service - * - * @param cls peer context - * @param op_result service handle returned from the connect adapter - */ -static void -stat_disconnect_adapter (void *cls, void *op_result) -{ - struct ExperimentationPeer *peer = cls; - - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel - (peer->sh, "experimentation", "# nodes active", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel - (peer->sh, "experimentation", "# nodes inactive", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel - (peer->sh, "experimentation", "# nodes requested", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel - (peer->sh, "experimentation", "# issuer", - stat_iterator, peer)); - GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel - (peer->sh, "experimentation", "# experiments", - stat_iterator, peer)); - GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); - peer->sh = NULL; -} - - - -/** - * Signature of a main function for a testcase. - * - * @param cls closure - * @param num_peers number of peers in 'peers' - * @param peers_ handle to peers run in the testbed - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -test_master (void *cls, unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers_, - unsigned int links_succeeded, - unsigned int links_failed) -{ - unsigned int peer; - - GNUNET_assert (NULL == cls); - GNUNET_assert (NUM_PEERS == num_peers); - GNUNET_assert (NULL != peers_); - for (peer = 0; peer < num_peers; peer++) - { - GNUNET_assert (NULL != peers_[peer]); - /* Connect to peer's statistic service */ - ph[peer].stat_op = GNUNET_TESTBED_service_connect (NULL, - peers_[peer], "statistics", - &stat_comp_cb, &ph[peer], - &stat_connect_adapter, - &stat_disconnect_adapter, - &ph[peer]); - - } - peers = peers_; - overlay_connects = 0; - op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, - NULL, - NULL, - GNUNET_TESTBED_TOPOLOGY_CLIQUE, - /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ - /* NUM_PEERS, */ - GNUNET_TESTBED_TOPOLOGY_OPTION_END); - GNUNET_assert (NULL != op); - shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); -} - - -/** - * Main function - */ -int -main (int argc, char **argv) -{ - uint64_t event_mask; - - result = GNUNET_SYSERR; - event_mask = 0; - event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); - event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); - (void) GNUNET_TESTBED_test_run ("test_experimentation_clique", - "test_experimentation_clique.conf", NUM_PEERS, - event_mask, &controller_event_cb, NULL, - &test_master, NULL); - if (GNUNET_OK != result) - return 1; - return 0; -} - -/* end of test_testbed_api_topology.c */ diff --git a/src/experimentation/test_experimentation_clique_connect.c b/src/experimentation/test_experimentation_clique_connect.c new file mode 100644 index 000000000..9b4d0117b --- /dev/null +++ b/src/experimentation/test_experimentation_clique_connect.c @@ -0,0 +1,413 @@ +/* + This file is part of GNUnet + (C) 2008--2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file src/experimentation/test_experimentation_clique_connect.c + * @brief test case to connect experimentation daemons in a clique + * @author Sree Harsha Totakura + * @author Matthias Wachs + */ + +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_testbed_service.h" + + +/** + * Number of peers we want to start + */ +#define NUM_PEERS 2 + +#define NUM_ISSUER 1 + +#define NUM_EXPERIMENTS 2 + +#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20) + +/** + * Array of peers + */ +static struct GNUNET_TESTBED_Peer **peers; + +/** + * Operation handle + */ +static struct GNUNET_TESTBED_Operation *op; + +/** + * Shutdown task + */ +static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; + +/** + * Testing result + */ +static int result; + +/** + * Counter for counting overlay connections + */ +static unsigned int overlay_connects; + +/** + * Information we track for a peer in the testbed. + */ +struct ExperimentationPeer +{ + /** + * Handle with testbed. + */ + struct GNUNET_TESTBED_Peer *daemon; + + /** + * Testbed operation to connect to statistics service + */ + struct GNUNET_TESTBED_Operation *stat_op; + + /** + * Handle to the statistics service + */ + struct GNUNET_STATISTICS_Handle *sh; + + unsigned int active_nodes; + unsigned int requested_nodes; + unsigned int inactive_nodes; + unsigned int issuer; + unsigned int experiments; +}; + + +struct ExperimentationPeer ph[NUM_PEERS]; + +/** + * Shutdown nicely + * + * @param cls NULL + * @param tc the task context + */ +static void +do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + unsigned int peer; + shutdown_task = GNUNET_SCHEDULER_NO_TASK; + + for (peer = 0; peer < NUM_PEERS; peer++) + { + if (NULL != ph[peer].stat_op) + GNUNET_TESTBED_operation_done (ph[peer].stat_op); + ph[peer].stat_op = NULL; + } + + if (NULL != op) + { + GNUNET_TESTBED_operation_done (op); + op = NULL; + } + GNUNET_SCHEDULER_shutdown (); +} + +/** + * Controller event callback + * + * @param cls NULL + * @param event the controller event + */ +static void +controller_event_cb (void *cls, + const struct GNUNET_TESTBED_EventInformation *event) +{ + switch (event->type) + { + case GNUNET_TESTBED_ET_CONNECT: + overlay_connects++; + if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) + { + result = GNUNET_OK; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS); + if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) + { + GNUNET_SCHEDULER_cancel (shutdown_task); + } + shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); + } + break; + case GNUNET_TESTBED_ET_OPERATION_FINISHED: + break; + default: + GNUNET_break (0); + result = GNUNET_SYSERR; + GNUNET_SCHEDULER_cancel (shutdown_task); + shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + } +} + +static void +check_end () +{ + static int last_active_value = 0; + static int last_issuer_value = 0; + static int last_experiments_value = 0; + unsigned int peer; + unsigned int total_active = 0; + unsigned int total_inactive = 0; + unsigned int total_requested = 0; + unsigned int issuer = 0; + unsigned int experiments = 0; + + for (peer = 0; peer < NUM_PEERS; peer++) + { + total_active += ph[peer].active_nodes; + total_requested += ph[peer].requested_nodes; + total_inactive += ph[peer].inactive_nodes; + if (NUM_ISSUER == ph[peer].issuer) + issuer ++; + if (NUM_EXPERIMENTS == ph[peer].experiments) + experiments ++; + } + if ((last_issuer_value < issuer) && (issuer == NUM_PEERS)) + fprintf (stderr, "I"); + last_issuer_value = issuer; + + if ((last_experiments_value < experiments) && (experiments == NUM_PEERS)) + fprintf (stderr, "E"); + last_experiments_value = experiments; + + if (last_active_value < total_active) + fprintf (stderr, "."); + last_active_value = total_active; + + + if ((total_active == (NUM_PEERS * (NUM_PEERS -1))) && + (total_requested == 0) && (total_inactive == 0) && + (issuer == NUM_PEERS) && (experiments == NUM_PEERS)) + { + fprintf (stderr, "\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers active in a clique\n", NUM_PEERS); + GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); + } +} + + + +/** + * Callback function to process statistic values. + * + * @param cls struct StatsContext + * @param subsystem name of subsystem that created the statistic + * @param name the name of the datum + * @param value the current value + * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not + * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration + */ +static int +stat_iterator (void *cls, const char *subsystem, const char *name, + uint64_t value, int is_persistent) +{ + struct ExperimentationPeer *peer = cls; + + if (0 == strcmp (name, "# nodes active")) + { + peer->active_nodes = value; + } + if (0 == strcmp (name, "# nodes inactive")) + { + peer->inactive_nodes = value; + } + if (0 == strcmp (name, "# nodes requested")) + { + peer->requested_nodes = value; + } + if (0 == strcmp (name, "# issuer")) + { + peer->issuer = value; + } + if (0 == strcmp (name, "# experiments")) + { + peer->experiments = value; + } + + check_end (); + + return GNUNET_OK; +} + +/** + * Called after successfully opening a connection to a peer's statistics + * service; we register statistics monitoring here. + * + * @param cls the callback closure from functions generating an operation + * @param op the operation that has been finished + * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() + * @param emsg error message in case the operation has failed; will be NULL if + * operation has executed successfully. + */ +static void +stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, + void *ca_result, const char *emsg ) +{ + struct GNUNET_STATISTICS_Handle *sh = ca_result; + struct ExperimentationPeer *peer = cls; + + if (NULL != emsg) + { + GNUNET_break (0); + return; + } + + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch + (sh, "experimentation", "# nodes active", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch + (sh, "experimentation", "# nodes inactive", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch + (sh, "experimentation", "# nodes requested", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch + (sh, "experimentation", "# issuer", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch + (sh, "experimentation", "# experiments", + stat_iterator, peer)); +} + +/** + * Called to open a connection to the peer's statistics + * + * @param cls peer context + * @param cfg configuration of the peer to connect to; will be available until + * GNUNET_TESTBED_operation_done() is called on the operation returned + * from GNUNET_TESTBED_service_connect() + * @return service handle to return in 'op_result', NULL on error + */ +static void * +stat_connect_adapter (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct ExperimentationPeer *peer = cls; + peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg); + if (NULL == peer->sh) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n"); + return peer->sh; +} + + +/** + * Called to disconnect from peer's statistics service + * + * @param cls peer context + * @param op_result service handle returned from the connect adapter + */ +static void +stat_disconnect_adapter (void *cls, void *op_result) +{ + struct ExperimentationPeer *peer = cls; + + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel + (peer->sh, "experimentation", "# nodes active", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel + (peer->sh, "experimentation", "# nodes inactive", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel + (peer->sh, "experimentation", "# nodes requested", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel + (peer->sh, "experimentation", "# issuer", + stat_iterator, peer)); + GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel + (peer->sh, "experimentation", "# experiments", + stat_iterator, peer)); + GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); + peer->sh = NULL; +} + + + +/** + * Signature of a main function for a testcase. + * + * @param cls closure + * @param num_peers number of peers in 'peers' + * @param peers_ handle to peers run in the testbed + * @param links_succeeded the number of overlay link connection attempts that + * succeeded + * @param links_failed the number of overlay link connection attempts that + * failed + */ +static void +test_master (void *cls, unsigned int num_peers, + struct GNUNET_TESTBED_Peer **peers_, + unsigned int links_succeeded, + unsigned int links_failed) +{ + unsigned int peer; + + GNUNET_assert (NULL == cls); + GNUNET_assert (NUM_PEERS == num_peers); + GNUNET_assert (NULL != peers_); + for (peer = 0; peer < num_peers; peer++) + { + GNUNET_assert (NULL != peers_[peer]); + /* Connect to peer's statistic service */ + ph[peer].stat_op = GNUNET_TESTBED_service_connect (NULL, + peers_[peer], "statistics", + &stat_comp_cb, &ph[peer], + &stat_connect_adapter, + &stat_disconnect_adapter, + &ph[peer]); + + } + peers = peers_; + overlay_connects = 0; + op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, + NULL, + NULL, + GNUNET_TESTBED_TOPOLOGY_CLIQUE, + /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ + /* NUM_PEERS, */ + GNUNET_TESTBED_TOPOLOGY_OPTION_END); + GNUNET_assert (NULL != op); + shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); +} + + +/** + * Main function + */ +int +main (int argc, char **argv) +{ + uint64_t event_mask; + + result = GNUNET_SYSERR; + event_mask = 0; + event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); + event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); + (void) GNUNET_TESTBED_test_run ("test_experimentation_clique_connect", + "test_experimentation_clique.conf", NUM_PEERS, + event_mask, &controller_event_cb, NULL, + &test_master, NULL); + if (GNUNET_OK != result) + return 1; + return 0; +} + +/* end of test_experimentation_clique_connect.c */