/**
* Number of peers we want to start
*/
-#define NUM_PEERS 2
+#define NUM_PEERS 10
+
+#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 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
static void
do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+ 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);
if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects)
{
result = GNUNET_OK;
- GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+ 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:
- GNUNET_assert (NULL != event->details.operation_finished.emsg);
break;
default:
GNUNET_break (0);
}
}
+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.
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,
/* NUM_PEERS, */
GNUNET_TESTBED_TOPOLOGY_OPTION_END);
GNUNET_assert (NULL != op);
- shutdown_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 300),
- do_shutdown, NULL);
+ shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL);
}