aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrothoff <grothoff@140774ce-b5e7-0310-ab8b-a85725594a96>2012-09-10 19:01:30 +0000
committergrothoff <grothoff@140774ce-b5e7-0310-ab8b-a85725594a96>2012-09-10 19:01:30 +0000
commit4a70cddccce3b389677d334f7c1503f70019eeea (patch)
treeabf57ae59527d9fae445e76ee2b9481ccbba031f
parentf20bd9202bf4e3c4e9e1fc00f26b1e24a70f1353 (diff)
nse profiler _compiles_ against new testbed API
git-svn-id: https://gnunet.org/svn/gnunet@23741 140774ce-b5e7-0310-ab8b-a85725594a96
-rw-r--r--src/nse/Makefile.am2
-rw-r--r--src/nse/gnunet-nse-profiler.c1229
2 files changed, 680 insertions, 551 deletions
diff --git a/src/nse/Makefile.am b/src/nse/Makefile.am
index 5303b4cdb7..276f792b84 100644
--- a/src/nse/Makefile.am
+++ b/src/nse/Makefile.am
@@ -39,7 +39,7 @@ gnunet_nse_profiler_LDADD = -lm \
$(top_builddir)/src/nse/libgnunetnse.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/testing_old/libgnunettesting_old.la \
+ $(top_builddir)/src/testbed/libgnunettestbed.la \
$(GN_LIBINTL)
gnunet_nse_profiler_DEPENDENCIES = \
libgnunetnse.la
diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c
index 19adb2064b..ca9ec85f43 100644
--- a/src/nse/gnunet-nse-profiler.c
+++ b/src/nse/gnunet-nse-profiler.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2011 Christian Grothoff (and other contributing authors)
+ (C) 2011, 2012 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
@@ -24,35 +24,65 @@
* Generally, the profiler starts a given number of peers,
* then churns some off, waits a certain amount of time, then
* churns again, and repeats.
+ *
+ * TODO:
+ * - need to enable user to specify topology options
+ * - need minor fix with "***"-host argument change in TESTBED (TBD there)
+ * - need to check for leaks (especially FD leaks)
+ * - need to TEST
*/
#include "platform.h"
-#include "gnunet_testing_lib.h"
+#include "gnunet_testbed_service.h"
#include "gnunet_nse_service.h"
-#define VERBOSE 3
+/**
+ * Information we track for a peer in the testbed.
+ */
struct NSEPeer
{
+ /**
+ * Prev reference in DLL.
+ */
struct NSEPeer *prev;
+ /**
+ * Next reference in DLL.
+ */
struct NSEPeer *next;
- struct GNUNET_TESTING_Daemon *daemon;
+ /**
+ * Handle with testbed.
+ */
+ struct GNUNET_TESTBED_Peer *daemon;
- struct GNUNET_NSE_Handle *nse_handle;
+ /**
+ * Testbed operation to connect to NSE service.
+ */
+ struct GNUNET_TESTBED_Operation *nse_op;
+ /**
+ * Handle to statistics service of the peer.
+ */
struct GNUNET_STATISTICS_Handle *stats;
+
+ /**
+ * Testbed operation to connect to statistics service.
+ */
+ struct GNUNET_TESTBED_Operation *stats_op;
+ /**
+ * Task scheduled to get statistics from this peer.
+ */
GNUNET_SCHEDULER_TaskIdentifier stats_task;
};
+/**
+ * Context for the stats task?
+ */
struct StatsContext
{
- /**
- * Whether or not shoutdown after finishing.
- */
- int shutdown;
/**
* How many messages have peers received during the test.
@@ -81,51 +111,80 @@ struct StatsContext
};
+/**
+ * Head of DLL of peers we monitor closely.
+ */
static struct NSEPeer *peer_head;
+/**
+ * Tail of DLL of peers we monitor closely.
+ */
static struct NSEPeer *peer_tail;
/**
- * How long until we give up on connecting the peers?
+ * Return value from 'main' (0 == success)
*/
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
-
static int ok;
/**
- * Be verbose
+ * Be verbose (configuration option)
*/
static int verbose;
/**
- * Total number of peers in the test.
+ * Name of the file with the hosts to run the test over (configuration option)
+ */
+static char *hosts_file;
+
+/**
+ * IP address of this system, as seen by the rest of the system (configuration option)
*/
-static unsigned long long num_peers;
+static char *controller_ip;
/**
- * Global configuration file
+ * Maximum number of peers in the test.
*/
-static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
+static unsigned int num_peers;
/**
- * Total number of currently running peers.
+ * Total number of rounds to execute.
*/
-static unsigned long long peers_running;
+static unsigned int num_rounds;
/**
* Current round we are in.
*/
-static unsigned long long current_round;
+static unsigned int current_round;
+
+/**
+ * Array of size 'num_rounds' with the requested number of peers in the given round.
+ */
+static unsigned int *num_peers_in_round;
/**
- * Peers desired in the next round.
+ * How many peers are running right now?
*/
-static unsigned long long peers_next_round;
+static unsigned int peers_running;
+
+/**
+ * Specification for the numbers of peers to have in each round.
+ */
+static char *num_peer_spec;
+
+/**
+ * Handles to all of the running peers.
+ */
+static struct GNUNET_TESTBED_Peer **daemons;
+
+/**
+ * Global configuration file
+ */
+static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
/**
* Maximum number of connections to NSE services.
*/
-static unsigned long long connection_limit;
+static unsigned int connection_limit;
/**
* Total number of connections in the whole network.
@@ -133,14 +192,14 @@ static unsigned long long connection_limit;
static unsigned int total_connections;
/**
- * The currently running peer group.
+ * File to report results to.
*/
-static struct GNUNET_TESTING_PeerGroup *pg;
+static struct GNUNET_DISK_FileHandle *output_file;
/**
- * File to report results to.
+ * Filename to log results to.
*/
-static struct GNUNET_DISK_FileHandle *output_file;
+static char *output_filename;
/**
* File to log connection info, statistics to.
@@ -148,87 +207,106 @@ static struct GNUNET_DISK_FileHandle *output_file;
static struct GNUNET_DISK_FileHandle *data_file;
/**
- * How many data points to capture before triggering next round?
+ * Filename to log connection info, statistics to.
*/
-static struct GNUNET_TIME_Relative wait_time;
+static char *data_filename;
/**
- * NSE interval.
+ * How long to wait before triggering next round?
+ * Default: 60 s.
*/
-static struct GNUNET_TIME_Relative interval;
+static struct GNUNET_TIME_Relative wait_time = { 60 * 1000 };
/**
- * Task called to disconnect peers.
+ * How often do we query for statistics during a round?
+ * Default: 1 s.
*/
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+static struct GNUNET_TIME_Relative interval = { 1000 };
/**
- * Task called to shutdown test.
+ * Name of the file where we write the topology for each round; NULL for
+ * none.
*/
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+static char *topology_file;
/**
- * Task used to churn the network.
+ * List of hosts we use for the testbed.
*/
-static GNUNET_SCHEDULER_TaskIdentifier churn_task;
+static struct GNUNET_TESTBED_Host **hosts;
-static char *topology_file;
+/**
+ * Size of the 'hosts' array.
+ */
+static unsigned int num_hosts;
/**
- * Check whether peers successfully shut down.
+ * Handle to the master controller.
*/
-static void
-shutdown_callback (void *cls, const char *emsg)
-{
- if (emsg != NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
- if (ok == 0)
- ok = 666;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
- ok = 0;
- }
-}
+static struct GNUNET_TESTBED_Controller *controller;
+
+/**
+ * Controller start handle.
+ */
+static struct GNUNET_TESTBED_ControllerProc *copro;
+
+/**
+ * Testbed handle.
+ */
+static struct GNUNET_TESTBED_Testbed *testbed;
+/**
+ * Clean up all of the monitoring connections to NSE and
+ * STATISTICS that we keep to selected peers.
+ */
static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+close_monitor_connections ()
{
struct NSEPeer *pos;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
- if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (disconnect_task);
- disconnect_task = GNUNET_SCHEDULER_NO_TASK;
- }
while (NULL != (pos = peer_head))
{
- if (pos->nse_handle != NULL)
- GNUNET_NSE_disconnect (pos->nse_handle);
+ if (NULL != pos->nse_op)
+ GNUNET_TESTBED_operation_done (pos->nse_op);
+ if (NULL != pos->stats_op)
+ GNUNET_TESTBED_operation_done (pos->stats_op);
GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos);
if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task)
- {
GNUNET_SCHEDULER_cancel (pos->stats_task);
- if (NULL != pos->stats)
- GNUNET_STATISTICS_destroy(pos->stats, GNUNET_NO);
- }
GNUNET_free (pos);
}
+}
+
- if (data_file != NULL)
+/**
+ * Task run on shutdown; cleans up everything.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
+ close_monitor_connections ();
+ if (NULL != testbed)
+ GNUNET_TESTBED_destroy (testbed);
+ if (NULL != controller)
+ GNUNET_TESTBED_controller_disconnect (controller);
+ if (NULL != copro)
+ GNUNET_TESTBED_controller_stop (copro);
+ while (0 > num_hosts)
+ GNUNET_TESTBED_host_destroy (hosts[--num_hosts]);
+ // FIXME: what about closing other files!?
+ if (NULL != data_file)
GNUNET_DISK_file_close (data_file);
- GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
}
/**
* Callback to call when network size estimate is updated.
*
- * @param cls closure
+ * @param cls closure with the 'struct NSEPeer' providing the update
* @param timestamp server timestamp
* @param estimate the value of the current network size estimate
* @param std_dev standard deviation (rounded down to nearest integer)
@@ -236,32 +314,34 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
*
*/
static void
-handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp,
+handle_estimate (void *cls,
+ struct GNUNET_TIME_Absolute timestamp,
double estimate, double std_dev)
{
struct NSEPeer *peer = cls;
- char *output_buffer;
+ char output_buffer[512];
size_t size;
- if (output_file != NULL)
- {
- size =
- GNUNET_asprintf (&output_buffer, "%s %llu %llu %f %f %f\n",
- GNUNET_i2s (&peer->daemon->id), peers_running,
- timestamp.abs_value,
- GNUNET_NSE_log_estimate_to_n (estimate), estimate,
- std_dev);
- if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
- GNUNET_free (output_buffer);
- }
- else
- FPRINTF (stderr,
- "Received network size estimate from peer %s. Size: %f std.dev. %f\n",
- GNUNET_i2s (&peer->daemon->id), estimate, std_dev);
-
+ if (NULL == output_file)
+ {
+ FPRINTF (stderr,
+ "Received network size estimate from peer %p. Size: %f std.dev. %f\n",
+ peer, estimate, std_dev);
+ return;
+ }
+ size = GNUNET_snprintf (output_buffer,
+ sizeof (output_buffer),
+ "%p %llu %llu %f %f %f\n",
+ peer, peers_running,
+ timestamp.abs_value,
+ GNUNET_NSE_log_estimate_to_n (estimate), estimate,
+ std_dev);
+ if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Unable to write to file!\n");
}
+
/**
* Process core statistic values.
*
@@ -277,29 +357,30 @@ core_stats_iterator (void *cls, const char *subsystem, const char *name,
uint64_t value, int is_persistent)
{
struct NSEPeer *peer = cls;
- char *output_buffer;
+ char output_buffer[512];
size_t size;
- if (output_file != NULL)
- {
- size =
- GNUNET_asprintf (&output_buffer, "%s [%s] %s %llu\n",
- GNUNET_i2s (&peer->daemon->id),
- subsystem, name, value);
- if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
- GNUNET_free (output_buffer);
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "%s -> %s [%s]: %llu\n",
- GNUNET_i2s (&peer->daemon->id), subsystem, name, value);
-
+ if (NULL == output_file)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%p -> %s [%s]: %llu\n",
+ peer, subsystem, name, value);
+ return GNUNET_OK;
+ }
+ size =
+ GNUNET_snprintf (output_buffer,
+ sizeof (output_buffer),
+ "%p [%s] %s %llu\n",
+ peer,
+ subsystem, name, value);
+ if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
return GNUNET_OK;
}
+
/**
- * Continuation called by "get_stats" function.
+ * Continuation called by "get_stats" function once we are done.
*
* @param cls closure
* @param success GNUNET_OK if statistics were
@@ -308,32 +389,43 @@ core_stats_iterator (void *cls, const char *subsystem, const char *name,
static void
core_stats_cont (void *cls, int success);
+
+/**
+ * Function invoked periodically to get the statistics.
+ *
+ * @param cls 'struct NSEPeer' to get stats from
+ * @param tc scheduler context
+ */
static void
-core_get_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+core_get_stats (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct NSEPeer *peer = cls;
- if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
{
- GNUNET_STATISTICS_destroy(peer->stats, GNUNET_NO);
+ GNUNET_TESTBED_operation_done (peer->stats_op);
peer->stats = NULL;
+ peer->stats_op = NULL;
return;
}
- else
- {
- GNUNET_STATISTICS_get(peer->stats, "core", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &core_stats_cont, &core_stats_iterator, peer);
- GNUNET_STATISTICS_get(peer->stats, "transport", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, &core_stats_iterator, peer);
- GNUNET_STATISTICS_get(peer->stats, "nse", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, &core_stats_iterator, peer);
- }
+ /* FIXME: code duplication! */
+ GNUNET_STATISTICS_get (peer->stats, "core", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &core_stats_cont,
+ &core_stats_iterator, peer);
+ GNUNET_STATISTICS_get (peer->stats, "transport", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL,
+ &core_stats_iterator, peer);
+ GNUNET_STATISTICS_get (peer->stats, "nse", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL,
+ &core_stats_iterator, peer);
peer->stats_task = GNUNET_SCHEDULER_NO_TASK;
}
+
/**
* Continuation called by "get_stats" function.
*
@@ -342,19 +434,136 @@ core_get_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
* successfully obtained, GNUNET_SYSERR if not.
*/
static void
-core_stats_cont (void *cls, int success)
+core_stats_cont (void *cls,
+ int success)
{
struct NSEPeer *peer = cls;
- peer->stats_task = GNUNET_SCHEDULER_add_delayed (interval, &core_get_stats,
- peer);
+
+ if (GNUNET_OK != success)
+ return;
+ peer->stats_task = GNUNET_SCHEDULER_add_delayed (interval,
+ &core_get_stats, peer);
+}
+
+
+/**
+ * Adapter function called to establish a connection to
+ * statistics service.
+ *
+ * @param cls closure
+ * @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 *
+statistics_connect_adapter (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ return GNUNET_STATISTICS_create ("<driver>",
+ cfg);
}
/**
+ * Adapter function called to destroy a connection to
+ * statistics service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void
+statistics_disconnect_adapter (void *cls,
+ void *op_result)
+{
+ GNUNET_STATISTICS_destroy (op_result, GNUNET_NO);
+}
+
+
+/**
+ * Function called by testbed once we are connected to stats service.
*
+ * @param cls the 'struct NSEPeer' for which we connected to stats
+ * @param op connect operation handle
+ * @param ca_result handle to stats service
+ * @param emsg error message on failure
*/
static void
-connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+stat_run (void *cls,
+ struct GNUNET_TESTBED_Operation *op,
+ void *ca_result,
+ const char *emsg)
+{
+ struct NSEPeer *current_peer = cls;
+
+ if (NULL == ca_result)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to statistics service: %s\n",
+ emsg);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ current_peer->stats = ca_result;
+ GNUNET_STATISTICS_get (current_peer->stats, "core", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &core_stats_cont,
+ &core_stats_iterator, current_peer);
+ GNUNET_STATISTICS_get (current_peer->stats, "transport", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL,
+ &core_stats_iterator, current_peer);
+ GNUNET_STATISTICS_get (current_peer->stats, "nse", NULL,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL,
+ &core_stats_iterator, current_peer);
+}
+
+
+/**
+ * Adapter function called to establish a connection to
+ * NSE service.
+ *
+ * @param cls closure (the 'struct NSEPeer')
+ * @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 *
+nse_connect_adapter (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct NSEPeer *current_peer = cls;
+
+ return GNUNET_NSE_connect (cfg, &handle_estimate, current_peer);
+}
+
+
+/**
+ * Adapter function called to destroy a connection to
+ * NSE service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void
+nse_disconnect_adapter (void *cls,
+ void *op_result)
+{
+ GNUNET_NSE_disconnect (op_result);
+}
+
+
+/**
+ * Task run to connect to the NSE and statistics services to a subset of
+ * all of the running peers.
+ *
+ * @param cls handle the peer
+ * @param tc ignored
+ */
+static void
+connect_nse_service ()
{
struct NSEPeer *current_peer;
unsigned int i;
@@ -364,123 +573,107 @@ connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
if ((connection_limit > 0) &&
(num_peers > connection_limit) &&
- (i % (num_peers / connection_limit) != 0))
+ (0 != (i % (num_peers / connection_limit))))
continue;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"nse-profiler: connecting to nse service of peer %d\n", i);
current_peer = GNUNET_malloc (sizeof (struct NSEPeer));
- current_peer->daemon = GNUNET_TESTING_daemon_get (pg, i);
- if (GNUNET_YES ==
- GNUNET_TESTING_test_daemon_running (GNUNET_TESTING_daemon_get (pg, i)))
- {
- current_peer->nse_handle =
- GNUNET_NSE_connect (current_peer->daemon->cfg, &handle_estimate,
- current_peer);
- GNUNET_assert (current_peer->nse_handle != NULL);
- }
- current_peer->stats = GNUNET_STATISTICS_create("profiler", current_peer->daemon->cfg);
- GNUNET_STATISTICS_get(current_peer->stats, "core", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &core_stats_cont, &core_stats_iterator, current_peer);
- GNUNET_STATISTICS_get(current_peer->stats, "transport", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, &core_stats_iterator, current_peer);
- GNUNET_STATISTICS_get(current_peer->stats, "nse", NULL,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, &core_stats_iterator, current_peer);
+ current_peer->daemon = daemons[i];
+ current_peer->nse_op
+ = GNUNET_TESTBED_service_connect (NULL,
+ current_peer->daemon,
+ "nse",
+ NULL, NULL,
+ &nse_connect_adapter,
+ &nse_disconnect_adapter,
+ current_peer);
+ current_peer->stats_op
+ = GNUNET_TESTBED_service_connect (NULL,
+ current_peer->daemon,
+ "statistics",
+ &stat_run, current_peer,
+ &statistics_connect_adapter,
+ &statistics_disconnect_adapter,
+ NULL);
GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer);
}
}
+/**
+ * Task that starts/stops peers to move to the next round.
+ *
+ * @param cls NULL, unused
+ * @param tc scheduler context (unused)
+ */
static void
-churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+next_round (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
/**
- * Continuation called by the "get_all" and "get" functions.
+ * Continuation called by the "get_all" and "get" functions at the
+ * end of a round. Obtains the final statistics and writes them to
+ * the file, then either starts the next round, or, if this was the
+ * last round, terminates the run.
*
* @param cls struct StatsContext
* @param success GNUNET_OK if statistics were
* successfully obtained, GNUNET_SYSERR if not.
*/
static void
-stats_finished_callback (void *cls, int success)
+stats_finished_callback (void *cls,
+ struct GNUNET_TESTBED_Operation *op,
+ const char *emsg)
{
struct StatsContext *stats_context = cls;
- char *buf;
- int buf_len;
+ char buf[512];
+ size_t buf_len;
- if ((GNUNET_OK == success) && (data_file != NULL))
- {
- /* Stats lookup successful, write out data */
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "TOTAL_NSE_RECEIVED_MESSAGES_%d: %u \n",
- stats_context->shutdown,
- stats_context->total_nse_received_messages);
- if (buf_len > 0)
+ if (NULL != emsg)
{
- GNUNET_DISK_file_write (data_file, buf, buf_len);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to get statistics: %s\n",
+ emsg);
+ GNUNET_SCHEDULER_shutdown ();
+ GNUNET_free (stats_context);
+ return;
}
- GNUNET_free_non_null (buf);
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "TOTAL_NSE_TRANSMITTED_MESSAGES_%d: %u\n",
- stats_context->shutdown,
- stats_context->total_nse_transmitted_messages);
- if (buf_len > 0)
+ if (NULL != data_file)
{
+ /* Stats lookup successful, write out data */
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "TOTAL_NSE_RECEIVED_MESSAGES_%u: %u \n",
+ current_round,
+ stats_context->total_nse_received_messages);
GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "TOTAL_NSE_CROSS_%d: %u \n",
- stats_context->shutdown,
- stats_context->total_nse_cross);
- if (buf_len > 0)
- {
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "TOTAL_NSE_TRANSMITTED_MESSAGES_%u: %u\n",
+ current_round,
+ stats_context->total_nse_transmitted_messages);
+ GNUNET_DISK_file_write (data_file, buf, buf_len);
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "TOTAL_NSE_CROSS_%u: %u \n",
+ current_round,
+ stats_context->total_nse_cross);
GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "TOTAL_NSE_EXTRA_%d: %u \n",
- stats_context->shutdown,
- stats_context->total_nse_extra);
- if (buf_len > 0)
- {
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "TOTAL_NSE_EXTRA_%u: %u \n",
+ current_round,
+ stats_context->total_nse_extra);
GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "TOTAL_NSE_DISCARDED_%d: %u \n",
- stats_context->shutdown,
- stats_context->total_discarded);
- if (buf_len > 0)
- {
- GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
-
- }
-
- if (GNUNET_YES == stats_context->shutdown)
- {
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == shutdown_handle);
- shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
- }
- else
- {
- GNUNET_assert (churn_task == GNUNET_SCHEDULER_NO_TASK);
- churn_task = GNUNET_SCHEDULER_add_now (&churn_peers, NULL);
- }
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "TOTAL_NSE_DISCARDED_%u: %u \n",
+ current_round,
+ stats_context->total_discarded);
+ GNUNET_DISK_file_write (data_file, buf, buf_len);
+ }
+ GNUNET_SCHEDULER_add_now (&next_round, NULL);
GNUNET_free (stats_context);
}
@@ -497,427 +690,363 @@ stats_finished_callback (void *cls, int success)
* @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
*/
static int
-statistics_iterator (void *cls, const struct GNUNET_PeerIdentity *peer,
+statistics_iterator (void *cls,
+ const struct GNUNET_TESTBED_Peer *peer,
const char *subsystem, const char *name, uint64_t value,
int is_persistent)
{
struct StatsContext *stats_context = cls;
+ char buf[512];
+ size_t buf_len;
- if (0 == strcmp (subsystem, "nse"))
- {
- if (0 == strcmp (name, "# flood messages received"))
+ if (0 != strcmp (subsystem, "nse"))
+ return GNUNET_OK;
+ if (0 == strcmp (name, "# flood messages received"))
{
stats_context->total_nse_received_messages += value;
-#if VERBOSE
- if (data_file != NULL)
- {
- char *buf;
- int buf_len;
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "%s %u RECEIVED\n", GNUNET_i2s(peer), value);
- if (buf_len > 0)
- {
- GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
- }
-#endif
+ if ( (verbose > 1) &&
+ (NULL != data_file) )
+ {
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "%p %u RECEIVED\n",
+ peer, value);
+ GNUNET_DISK_file_write (data_file, buf, buf_len);
+ }
}
- if (0 == strcmp (name, "# flood messages transmitted"))
+ if (0 == strcmp (name, "# flood messages transmitted"))
{
stats_context->total_nse_transmitted_messages += value;
-#if VERBOSE
- if (data_file != NULL)
- {
- char *buf;
- int buf_len;
-
- buf = NULL;
- buf_len =
- GNUNET_asprintf (&buf, "%s %u TRANSMITTED\n",
- GNUNET_i2s(peer), value);
- if (buf_len > 0)
- {
- GNUNET_DISK_file_write (data_file, buf, buf_len);
- }
- GNUNET_free_non_null (buf);
- }
-#endif
- }
- if (0 == strcmp (name, "# cross messages"))
- {
- stats_context->total_nse_cross += value;
+ if ( (verbose > 1) &&
+ (NULL != data_file) )
+ {
+ buf_len =
+ GNUNET_snprintf (buf, sizeof (buf),
+ "%p %u TRANSMITTED\n",
+ peer, value);
+ GNUNET_DISK_file_write (data_file, buf, buf_len);
+ }
}
- if (0 == strcmp (name, "# extra messages"))
- {
- stats_context->total_nse_extra += value;
- }
- if (0 == strcmp (name, "# flood messages discarded (clock skew too large)"))
- {
- stats_context->total_discarded += value;
- }
- }
+ if (0 == strcmp (name, "# cross messages"))
+ stats_context->total_nse_cross += value;
+ if (0 == strcmp (name, "# extra messages"))
+ stats_context->total_nse_extra += value;
+ if (0 == strcmp (name, "# flood messages discarded (clock skew too large)"))
+ stats_context->total_discarded += value;
return GNUNET_OK;
}
+/**
+ * Function called upon completion of the node start/stop operations
+ * for the current round. Writes the new topology to disk.
+ */
static void
-disconnect_nse_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+write_topology ()
{
- struct NSEPeer *pos;
- char *buf;
- struct StatsContext *stats_context;
+ char temp_output_file[1024];
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting nse service of peers\n");
- disconnect_task = GNUNET_SCHEDULER_NO_TASK;
- while (NULL != (pos = peer_head))
- {
- if (pos->nse_handle != NULL)
+ if (NULL != topology_file)
{
- GNUNET_NSE_disconnect (pos->nse_handle);
- pos->nse_handle = NULL;
+ GNUNET_snprintf (temp_output_file, sizeof (temp_output_file),
+ "%s_%llu.dot",
+ topology_file, current_round);
+ GNUNET_TESTBED_overlay_write_topology_to_file (controller,
+ temp_output_file);
}
- GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos);
- if (NULL != pos->stats)
- GNUNET_STATISTICS_destroy(pos->stats, GNUNET_NO);
- if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task)
- GNUNET_SCHEDULER_cancel (pos->stats_task);
- GNUNET_free (pos);
- }
-
- GNUNET_asprintf (&buf, "round%llu", current_round);
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler", buf,
- &peers_next_round))
- {
- current_round++;
- if (current_round == 1)
- {
- stats_context = GNUNET_malloc (sizeof (struct StatsContext));
- stats_context->shutdown = GNUNET_NO;
- GNUNET_TESTING_get_statistics (pg, &stats_finished_callback,
- &statistics_iterator, stats_context);
- }
- else
- {
- GNUNET_assert (churn_task == GNUNET_SCHEDULER_NO_TASK);
- churn_task = GNUNET_SCHEDULER_add_now (&churn_peers, NULL);
- }
- }
- else /* No more rounds, let's shut it down! */
- {
- stats_context = GNUNET_malloc (sizeof (struct StatsContext));
- stats_context->shutdown = GNUNET_YES;
- GNUNET_SCHEDULER_cancel (shutdown_handle);
- shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_TESTING_get_statistics (pg, &stats_finished_callback,
- &statistics_iterator, stats_context);
- }
- GNUNET_free (buf);
}
/**
- * FIXME.
+ * We're at the end of a round. Stop monitoring, write total
+ * number of connections to log and get full stats. Then trigger
+ * the next round.
*
- * @param cls unused
- * @param emsg NULL on success
+ * @param cls unused, NULL
+ * @param tc unused
*/
static void
-topology_output_callback (void *cls, const char *emsg)
+finish_round (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- disconnect_task =
- GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
- GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
+ struct StatsContext *stats_context;
+ char buf[1024];
+ size_t buf_len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Have %u connections\n",
+ total_connections);
+ if (NULL != data_file)
+ {
+ buf_len = GNUNET_snprintf (buf, sizeof (buf),
+ "CONNECTIONS_0: %u\n",
+ total_connections);
+ GNUNET_DISK_file_write (data_file, buf, buf_len);
+ }
+ close_monitor_connections ();
+ stats_context = GNUNET_malloc (sizeof (struct StatsContext));
+ GNUNET_TESTBED_get_statistics (num_peers_in_round[current_round],
+ daemons,
+ &statistics_iterator,
+ &stats_finished_callback,
+ stats_context);
}
/**
- * FIXME.
- *
- * @param cls closure
- * @param emsg NULL on success
+ * We have reached the desired number of peers for the current round.
+ * Run it (by connecting and monitoring a few peers and waiting the
+ * specified delay before finishing the round).
*/
static void
-churn_callback (void *cls, const char *emsg)
+run_round ()
{
- char *temp_output_file;
-
- if (emsg == NULL) /* Everything is okay! */
- {
- peers_running = peers_next_round;
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Round %llu, churn finished successfully.\n", current_round);
- GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK);
- GNUNET_asprintf (&temp_output_file, "%s_%llu.dot", topology_file,
- current_round);
- GNUNET_TESTING_peergroup_topology_to_file (pg, temp_output_file,
- &topology_output_callback, NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Writing topology to file %s\n",
- temp_output_file);
- GNUNET_free (temp_output_file);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %llu, churn FAILED!!\n",
- current_round);
- GNUNET_SCHEDULER_cancel (shutdown_handle);
- shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
- }
+ write_topology ();
+ connect_nse_service ();
+ GNUNET_SCHEDULER_add_delayed (wait_time,
+ &finish_round,
+ NULL);
}
+/**
+ * Task run at the end of a round. Disconnect from all monitored
+ * peers; then get statistics from *all* peers.
+ *
+ * @param cls NULL, unused
+ * @param tc unused
+ */
static void
-churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+next_round (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- /* peers_running = GNUNET_TESTING_daemons_running(pg); */
- churn_task = GNUNET_SCHEDULER_NO_TASK;
- if (peers_next_round == peers_running)
- {
- /* Nothing to do... */
- GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
- GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK);
- disconnect_task =
- GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %lu, doing nothing!\n",
- current_round);
- }
- else
- {
- if (peers_next_round > num_peers)
+ unsigned int i;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting nse service of peers\n");
+ current_round++;
+
+ if (current_round == num_rounds)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Asked to turn on more peers than we have!!\n");
- GNUNET_SCHEDULER_cancel (shutdown_handle);
- GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+ /* this was the last round, terminate */
+ GNUNET_SCHEDULER_shutdown ();
+ return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Round %llu, turning off %llu peers, turning on %llu peers!\n",
- current_round,
- (peers_running >
- peers_next_round) ? peers_running - peers_next_round : 0,
- (peers_next_round >
- peers_running) ? peers_next_round - peers_running : 0);
- GNUNET_TESTING_daemons_churn (pg, "nse",
- (peers_running >
- peers_next_round) ? peers_running -
- peers_next_round : 0,
- (peers_next_round >
- peers_running) ? peers_next_round -
- peers_running : 0, wait_time, &churn_callback,
- NULL);
- }
+ if (num_peers_in_round[current_round] == peers_running)
+ {
+ /* no need to churn, just run next round */
+ run_round ();
+ return;
+ }
+
+ /* start peers if we have too few */
+ for (i=peers_running;i<num_peers_in_round[current_round];i++)
+ GNUNET_TESTBED_peer_start (daemons[i], NULL, NULL);
+
+ /* stop peers if we have too many */
+ for (i=num_peers_in_round[current_round];i<peers_running;i++)
+ GNUNET_TESTBED_peer_stop (daemons[i], NULL, NULL);
}
+/**
+ * Function that will be called whenever something in the
+ * testbed changes.
+ *
+ * @param cls closure, NULL
+ * @param event information on what is happening
+ */
static void
-nse_started_cb (void *cls, const char *emsg)
+master_controller_cb (void *cls,
+ const struct GNUNET_TESTBED_EventInformation *event)
{
- GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
- disconnect_task =
- GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
+ switch (event->type)
+ {
+ case GNUNET_TESTBED_ET_PEER_START:
+ peers_running++;
+ if (num_peers_in_round[current_round] == peers_running)
+ run_round ();
+ break;
+ case GNUNET_TESTBED_ET_PEER_STOP:
+ peers_running--;
+ if (num_peers_in_round[current_round] == peers_running)
+ run_round ();
+ break;
+ case GNUNET_TESTBED_ET_CONNECT:
+ total_connections++;
+ case GNUNET_TESTBED_ET_DISCONNECT:
+ total_connections--;
+ default:
+ break;
+ }
}
static void
-my_cb (void *cls, const char *emsg)
+controller_start_cb (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ int status)
{
- char *buf;
- int buf_len;
-
- if (emsg != NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peergroup callback called with error, aborting test!\n");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
- ok = 1;
- GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peer Group started successfully, connecting to NSE service for each peer!\n");
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have %u connections\n",
- total_connections);
- if (data_file != NULL)
- {
- buf = NULL;
- buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections);
- if (buf_len > 0)
- GNUNET_DISK_file_write (data_file, buf, buf_len);
- GNUNET_free (buf);
- }
- peers_running = GNUNET_TESTING_daemons_running (pg);
- GNUNET_TESTING_daemons_start_service (pg, "nse", wait_time, &nse_started_cb,
- NULL);
-
+ if (GNUNET_OK != status)
+ {
+ copro = NULL;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ num_hosts = GNUNET_TESTBED_hosts_load_from_file (hosts_file,
+ /* FIXME: & */ hosts);
+ if (0 == num_hosts)
+ {
+ fprintf (stderr,
+ "Failed to read host information from `%s'\n",
+ hosts_file);
+ return;
+ }
+ controller = GNUNET_TESTBED_controller_connect (cfg,
+ NULL,
+ 0 /* mask */,
+ &master_controller_cb, NULL);
+ testbed = GNUNET_TESTBED_create (controller,
+ num_hosts, hosts,
+ num_peers,
+ cfg,
+ 0 /* FIXME: topology */,
+ NULL /* FIXME: topology options */);
}
/**
- * Function that will be called whenever two daemons are connected by
- * the testing library.
+ * Actual main function that runs the emulation.
*
- * @param cls closure
- * @param first peer id for first daemon
- * @param second peer id for the second daemon
- * @param distance distance between the connected peers
- * @param first_cfg config for the first daemon
- * @param second_cfg config for the second daemon
- * @param first_daemon handle for the first daemon
- * @param second_daemon handle for the second daemon
- * @param emsg error message (NULL on success)
+ * @param cls unused
+ * @param args remaining args, unused
+ * @param cfgfile name of the configuration
+ * @param cfg configuration handle
*/
static void
-connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
- const struct GNUNET_PeerIdentity *second, uint32_t distance,
- const struct GNUNET_CONFIGURATION_Handle *first_cfg,
- const struct GNUNET_CONFIGURATION_Handle *second_cfg,
- struct GNUNET_TESTING_Daemon *first_daemon,
- struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
-{
- if (emsg == NULL)
- total_connections++;
-}
-
-
-static void
run (void *cls, char *const *args, const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- char *temp_str;
- struct GNUNET_TESTING_Host *hosts;
- char *data_filename;
+ char *tok;
+ unsigned int num;
ok = 1;
- //testing_cfg = GNUNET_CONFIGURATION_create ();
testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
-#if VERBOSE
- GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
- "use_progressbars", "YES");
-#endif
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing",
- "num_peers", &num_peers))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Option TESTING:NUM_PEERS is required!\n");
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse-profiler",
- "WAIT_TIME", &wait_time))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Option nse-profiler:wait_time is required!\n");
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse",
- "INTERVAL", &interval))
+ if (verbose)
+ GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
+ "use_progressbars", "YES");
+ if (NULL == num_peer_spec)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Option nse:interval is required!\n");
+ fprintf (stderr, "You need to specify the number of peers to run\n");
return;
}
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler",
- "connection_limit",
- &connection_limit))
- {
- connection_limit = 0;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler",
- "topology_output_file",
- &topology_file))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Option nse-profiler:topology_output_file is required!\n");
- return;
- }
-
- if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler",
- "data_output_file",
- &data_filename))
- {
- data_file =
- GNUNET_DISK_file_open (data_filename,
- GNUNET_DISK_OPEN_READWRITE |
- GNUNET_DISK_OPEN_TRUNCATE |
- GNUNET_DISK_OPEN_CREATE,
- GNUNET_DISK_PERM_USER_READ |
- GNUNET_DISK_PERM_USER_WRITE);
- if (data_file == NULL)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
- data_filename);
- GNUNET_free (data_filename);
- }
-
- if (GNUNET_YES ==
- GNUNET_CONFIGURATION_get_value_string (cfg, "nse-profiler", "output_file",
- &temp_str))
- {
- output_file =
- GNUNET_DISK_file_open (temp_str,
- GNUNET_DISK_OPEN_READWRITE |
- GNUNET_DISK_OPEN_CREATE,
- GNUNET_DISK_PERM_USER_READ |
- GNUNET_DISK_PERM_USER_WRITE);
- if (output_file == NULL)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
- temp_str);
- }
- GNUNET_free_non_null (temp_str);
-
- hosts = GNUNET_TESTING_hosts_load (testing_cfg);
-
- pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
- &connect_cb, &my_cb, NULL, hosts);
- GNUNET_assert (pg != NULL);
- shutdown_handle =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &shutdown_task, NULL);
+ for (tok = strtok (num_peer_spec, ","); NULL != tok; tok = strtok (NULL, ","))
+ {
+ if (1 != sscanf (tok, "%u", &num))
+ {
+ fprintf (stderr, "You need to specify numbers, not `%s'\n", tok);
+ return;
+ }
+ if (0 == num)
+ {
+ fprintf (stderr, "Refusing to run a round with 0 peers\n");
+ return;
+ }
+ GNUNET_array_grow (num_peers_in_round, num_rounds, num);
+ num_peers = GNUNET_MAX (num_peers, num);
+ }
+ if (0 == num_peers)
+ {
+ fprintf (stderr, "Refusing to run a testbed with no rounds\n");
+ return;
+ }
+ daemons = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer*) * num_peers);
+ if ( (NULL != data_filename) &&
+ (NULL == (data_file =
+ GNUNET_DISK_file_open (data_filename,
+ GNUNET_DISK_OPEN_READWRITE |
+ GNUNET_DISK_OPEN_TRUNCATE |
+ GNUNET_DISK_OPEN_CREATE,
+ GNUNET_DISK_PERM_USER_READ |
+ GNUNET_DISK_PERM_USER_WRITE))) )
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "open",
+ data_filename);
+
+ if ( (NULL != output_filename) &&
+ (NULL == (output_file =
+ GNUNET_DISK_file_open (output_filename,
+ GNUNET_DISK_OPEN_READWRITE |
+ GNUNET_DISK_OPEN_CREATE,
+ GNUNET_DISK_PERM_USER_READ |
+ GNUNET_DISK_PERM_USER_WRITE))) )
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open",
+ output_filename);
+
+ if (NULL ==
+ (copro = GNUNET_TESTBED_controller_start (controller_ip, NULL,
+ cfg,
+ &controller_start_cb, NULL)))
+ {
+ fprintf (stderr,
+ "Failed to start controller\n");
+ return;
+ }
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+ &shutdown_task, NULL);
}
-
/**
- * nse-profiler command line options
+ * Main function.
+ *
+ * @return 0 on success
*/
-static struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'V', "verbose", NULL,
- gettext_noop ("be verbose (print progress information)"),
- 0, &GNUNET_GETOPT_set_one, &verbose},
- GNUNET_GETOPT_OPTION_END
-};
-
-
int
main (int argc, char *const *argv)
{
+ static struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'C', "connections", "COUNT",
+ gettext_noop ("limit to the number of connections to NSE services, 0 for none"),
+ 1, &GNUNET_GETOPT_set_string, &num_peer_spec},
+ {'d', "details", "FILENAME",
+ gettext_noop ("name of the file for writing connection information and statistics"),
+ 1, &GNUNET_GETOPT_set_string, &data_filename},
+ {'H', "hosts", "FILENAME",
+ gettext_noop ("name of the file with the login information for the testbed"),
+ 1, &GNUNET_GETOPT_set_string, &hosts_file},
+ {'i', "ip", "CONTROLLER_IP",
+ gettext_noop ("IP address of this system as seen by the rest of the testbed"),
+ 1, &GNUNET_GETOPT_set_string, &controller_ip},
+ {'I', "interval", "DELAY",
+ gettext_noop ("delay between queries to statistics during a round"),
+ 1, &GNUNET_GETOPT_set_relative_time, &interval},
+ {'t', "topology", "FILENAME",
+ gettext_noop ("prefix of the filenames we use for writing the topology for each round"),
+ 1, &GNUNET_GETOPT_set_string, &topology_file},
+ {'o', "output", "FILENAME",
+ gettext_noop ("name of the file for writing the main results"),
+ 1, &GNUNET_GETOPT_set_string, &output_filename},
+ {'p', "peers", "NETWORKSIZESPEC",
+ gettext_noop ("Number of peers to run in each round, separated by commas"),
+ 1, &GNUNET_GETOPT_set_string, &num_peer_spec},
+ {'V', "verbose", NULL,
+ gettext_noop ("be verbose (print progress information)"),
+ 0, &GNUNET_GETOPT_increment_value, &verbose},
+ {'w', "wait", "DELAY",
+ gettext_noop ("delay between rounds"),
+ 1, &GNUNET_GETOPT_set_relative_time, &wait_time},
+ GNUNET_GETOPT_OPTION_END
+ };
if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
return 2;
-
- GNUNET_log_setup ("nse-profiler",
- "WARNING",
- NULL);
+ GNUNET_log_setup ("nse-profiler", "WARNING", NULL);
if (GNUNET_OK !=
GNUNET_PROGRAM_run (argc, argv, "nse-profiler",
gettext_noop
("Measure quality and performance of the NSE service."),
options, &run, NULL))
ok = 1;
-#if REMOVE_DIR
- GNUNET_DISK_directory_remove ("/tmp/nse-profiler");
-#endif
return ok;
}