diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-09-10 19:01:30 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-09-10 19:01:30 +0000 |
commit | 655f8e6e4269913c906aface3f26776f936f3be4 (patch) | |
tree | abf57ae59527d9fae445e76ee2b9481ccbba031f /src/nse/gnunet-nse-profiler.c | |
parent | ad85dcdd218b4c710793bea68f1a54d0b07e3cf3 (diff) | |
download | gnunet-655f8e6e4269913c906aface3f26776f936f3be4.tar.gz gnunet-655f8e6e4269913c906aface3f26776f936f3be4.zip |
nse profiler _compiles_ against new testbed API
Diffstat (limited to 'src/nse/gnunet-nse-profiler.c')
-rw-r--r-- | src/nse/gnunet-nse-profiler.c | 1229 |
1 files changed, 679 insertions, 550 deletions
diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c index 19adb2064..ca9ec85f4 100644 --- a/src/nse/gnunet-nse-profiler.c +++ b/src/nse/gnunet-nse-profiler.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2011 Christian Grothoff (and other contributing authors) | 3 | (C) 2011, 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -24,35 +24,65 @@ | |||
24 | * Generally, the profiler starts a given number of peers, | 24 | * Generally, the profiler starts a given number of peers, |
25 | * then churns some off, waits a certain amount of time, then | 25 | * then churns some off, waits a certain amount of time, then |
26 | * churns again, and repeats. | 26 | * churns again, and repeats. |
27 | * | ||
28 | * TODO: | ||
29 | * - need to enable user to specify topology options | ||
30 | * - need minor fix with "***"-host argument change in TESTBED (TBD there) | ||
31 | * - need to check for leaks (especially FD leaks) | ||
32 | * - need to TEST | ||
27 | */ | 33 | */ |
28 | #include "platform.h" | 34 | #include "platform.h" |
29 | #include "gnunet_testing_lib.h" | 35 | #include "gnunet_testbed_service.h" |
30 | #include "gnunet_nse_service.h" | 36 | #include "gnunet_nse_service.h" |
31 | 37 | ||
32 | #define VERBOSE 3 | ||
33 | 38 | ||
39 | /** | ||
40 | * Information we track for a peer in the testbed. | ||
41 | */ | ||
34 | struct NSEPeer | 42 | struct NSEPeer |
35 | { | 43 | { |
44 | /** | ||
45 | * Prev reference in DLL. | ||
46 | */ | ||
36 | struct NSEPeer *prev; | 47 | struct NSEPeer *prev; |
37 | 48 | ||
49 | /** | ||
50 | * Next reference in DLL. | ||
51 | */ | ||
38 | struct NSEPeer *next; | 52 | struct NSEPeer *next; |
39 | 53 | ||
40 | struct GNUNET_TESTING_Daemon *daemon; | 54 | /** |
55 | * Handle with testbed. | ||
56 | */ | ||
57 | struct GNUNET_TESTBED_Peer *daemon; | ||
41 | 58 | ||
42 | struct GNUNET_NSE_Handle *nse_handle; | 59 | /** |
60 | * Testbed operation to connect to NSE service. | ||
61 | */ | ||
62 | struct GNUNET_TESTBED_Operation *nse_op; | ||
43 | 63 | ||
64 | /** | ||
65 | * Handle to statistics service of the peer. | ||
66 | */ | ||
44 | struct GNUNET_STATISTICS_Handle *stats; | 67 | struct GNUNET_STATISTICS_Handle *stats; |
68 | |||
69 | /** | ||
70 | * Testbed operation to connect to statistics service. | ||
71 | */ | ||
72 | struct GNUNET_TESTBED_Operation *stats_op; | ||
45 | 73 | ||
74 | /** | ||
75 | * Task scheduled to get statistics from this peer. | ||
76 | */ | ||
46 | GNUNET_SCHEDULER_TaskIdentifier stats_task; | 77 | GNUNET_SCHEDULER_TaskIdentifier stats_task; |
47 | }; | 78 | }; |
48 | 79 | ||
49 | 80 | ||
81 | /** | ||
82 | * Context for the stats task? | ||
83 | */ | ||
50 | struct StatsContext | 84 | struct StatsContext |
51 | { | 85 | { |
52 | /** | ||
53 | * Whether or not shoutdown after finishing. | ||
54 | */ | ||
55 | int shutdown; | ||
56 | 86 | ||
57 | /** | 87 | /** |
58 | * How many messages have peers received during the test. | 88 | * How many messages have peers received during the test. |
@@ -81,51 +111,80 @@ struct StatsContext | |||
81 | }; | 111 | }; |
82 | 112 | ||
83 | 113 | ||
114 | /** | ||
115 | * Head of DLL of peers we monitor closely. | ||
116 | */ | ||
84 | static struct NSEPeer *peer_head; | 117 | static struct NSEPeer *peer_head; |
85 | 118 | ||
119 | /** | ||
120 | * Tail of DLL of peers we monitor closely. | ||
121 | */ | ||
86 | static struct NSEPeer *peer_tail; | 122 | static struct NSEPeer *peer_tail; |
87 | 123 | ||
88 | /** | 124 | /** |
89 | * How long until we give up on connecting the peers? | 125 | * Return value from 'main' (0 == success) |
90 | */ | 126 | */ |
91 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) | ||
92 | |||
93 | static int ok; | 127 | static int ok; |
94 | 128 | ||
95 | /** | 129 | /** |
96 | * Be verbose | 130 | * Be verbose (configuration option) |
97 | */ | 131 | */ |
98 | static int verbose; | 132 | static int verbose; |
99 | 133 | ||
100 | /** | 134 | /** |
101 | * Total number of peers in the test. | 135 | * Name of the file with the hosts to run the test over (configuration option) |
136 | */ | ||
137 | static char *hosts_file; | ||
138 | |||
139 | /** | ||
140 | * IP address of this system, as seen by the rest of the system (configuration option) | ||
102 | */ | 141 | */ |
103 | static unsigned long long num_peers; | 142 | static char *controller_ip; |
104 | 143 | ||
105 | /** | 144 | /** |
106 | * Global configuration file | 145 | * Maximum number of peers in the test. |
107 | */ | 146 | */ |
108 | static struct GNUNET_CONFIGURATION_Handle *testing_cfg; | 147 | static unsigned int num_peers; |
109 | 148 | ||
110 | /** | 149 | /** |
111 | * Total number of currently running peers. | 150 | * Total number of rounds to execute. |
112 | */ | 151 | */ |
113 | static unsigned long long peers_running; | 152 | static unsigned int num_rounds; |
114 | 153 | ||
115 | /** | 154 | /** |
116 | * Current round we are in. | 155 | * Current round we are in. |
117 | */ | 156 | */ |
118 | static unsigned long long current_round; | 157 | static unsigned int current_round; |
158 | |||
159 | /** | ||
160 | * Array of size 'num_rounds' with the requested number of peers in the given round. | ||
161 | */ | ||
162 | static unsigned int *num_peers_in_round; | ||
119 | 163 | ||
120 | /** | 164 | /** |
121 | * Peers desired in the next round. | 165 | * How many peers are running right now? |
122 | */ | 166 | */ |
123 | static unsigned long long peers_next_round; | 167 | static unsigned int peers_running; |
168 | |||
169 | /** | ||
170 | * Specification for the numbers of peers to have in each round. | ||
171 | */ | ||
172 | static char *num_peer_spec; | ||
173 | |||
174 | /** | ||
175 | * Handles to all of the running peers. | ||
176 | */ | ||
177 | static struct GNUNET_TESTBED_Peer **daemons; | ||
178 | |||
179 | /** | ||
180 | * Global configuration file | ||
181 | */ | ||
182 | static struct GNUNET_CONFIGURATION_Handle *testing_cfg; | ||
124 | 183 | ||
125 | /** | 184 | /** |
126 | * Maximum number of connections to NSE services. | 185 | * Maximum number of connections to NSE services. |
127 | */ | 186 | */ |
128 | static unsigned long long connection_limit; | 187 | static unsigned int connection_limit; |
129 | 188 | ||
130 | /** | 189 | /** |
131 | * Total number of connections in the whole network. | 190 | * Total number of connections in the whole network. |
@@ -133,14 +192,14 @@ static unsigned long long connection_limit; | |||
133 | static unsigned int total_connections; | 192 | static unsigned int total_connections; |
134 | 193 | ||
135 | /** | 194 | /** |
136 | * The currently running peer group. | 195 | * File to report results to. |
137 | */ | 196 | */ |
138 | static struct GNUNET_TESTING_PeerGroup *pg; | 197 | static struct GNUNET_DISK_FileHandle *output_file; |
139 | 198 | ||
140 | /** | 199 | /** |
141 | * File to report results to. | 200 | * Filename to log results to. |
142 | */ | 201 | */ |
143 | static struct GNUNET_DISK_FileHandle *output_file; | 202 | static char *output_filename; |
144 | 203 | ||
145 | /** | 204 | /** |
146 | * File to log connection info, statistics to. | 205 | * File to log connection info, statistics to. |
@@ -148,87 +207,106 @@ static struct GNUNET_DISK_FileHandle *output_file; | |||
148 | static struct GNUNET_DISK_FileHandle *data_file; | 207 | static struct GNUNET_DISK_FileHandle *data_file; |
149 | 208 | ||
150 | /** | 209 | /** |
151 | * How many data points to capture before triggering next round? | 210 | * Filename to log connection info, statistics to. |
152 | */ | 211 | */ |
153 | static struct GNUNET_TIME_Relative wait_time; | 212 | static char *data_filename; |
154 | 213 | ||
155 | /** | 214 | /** |
156 | * NSE interval. | 215 | * How long to wait before triggering next round? |
216 | * Default: 60 s. | ||
157 | */ | 217 | */ |
158 | static struct GNUNET_TIME_Relative interval; | 218 | static struct GNUNET_TIME_Relative wait_time = { 60 * 1000 }; |
159 | 219 | ||
160 | /** | 220 | /** |
161 | * Task called to disconnect peers. | 221 | * How often do we query for statistics during a round? |
222 | * Default: 1 s. | ||
162 | */ | 223 | */ |
163 | static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | 224 | static struct GNUNET_TIME_Relative interval = { 1000 }; |
164 | 225 | ||
165 | /** | 226 | /** |
166 | * Task called to shutdown test. | 227 | * Name of the file where we write the topology for each round; NULL for |
228 | * none. | ||
167 | */ | 229 | */ |
168 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; | 230 | static char *topology_file; |
169 | 231 | ||
170 | /** | 232 | /** |
171 | * Task used to churn the network. | 233 | * List of hosts we use for the testbed. |
172 | */ | 234 | */ |
173 | static GNUNET_SCHEDULER_TaskIdentifier churn_task; | 235 | static struct GNUNET_TESTBED_Host **hosts; |
174 | 236 | ||
175 | static char *topology_file; | 237 | /** |
238 | * Size of the 'hosts' array. | ||
239 | */ | ||
240 | static unsigned int num_hosts; | ||
176 | 241 | ||
177 | /** | 242 | /** |
178 | * Check whether peers successfully shut down. | 243 | * Handle to the master controller. |
179 | */ | 244 | */ |
180 | static void | 245 | static struct GNUNET_TESTBED_Controller *controller; |
181 | shutdown_callback (void *cls, const char *emsg) | 246 | |
182 | { | 247 | /** |
183 | if (emsg != NULL) | 248 | * Controller start handle. |
184 | { | 249 | */ |
185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n"); | 250 | static struct GNUNET_TESTBED_ControllerProc *copro; |
186 | if (ok == 0) | 251 | |
187 | ok = 666; | 252 | /** |
188 | } | 253 | * Testbed handle. |
189 | else | 254 | */ |
190 | { | 255 | static struct GNUNET_TESTBED_Testbed *testbed; |
191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n"); | ||
192 | ok = 0; | ||
193 | } | ||
194 | } | ||
195 | 256 | ||
196 | 257 | ||
258 | /** | ||
259 | * Clean up all of the monitoring connections to NSE and | ||
260 | * STATISTICS that we keep to selected peers. | ||
261 | */ | ||
197 | static void | 262 | static void |
198 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 263 | close_monitor_connections () |
199 | { | 264 | { |
200 | struct NSEPeer *pos; | 265 | struct NSEPeer *pos; |
201 | 266 | ||
202 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
203 | if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
204 | { | ||
205 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
206 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
207 | } | ||
208 | while (NULL != (pos = peer_head)) | 267 | while (NULL != (pos = peer_head)) |
209 | { | 268 | { |
210 | if (pos->nse_handle != NULL) | 269 | if (NULL != pos->nse_op) |
211 | GNUNET_NSE_disconnect (pos->nse_handle); | 270 | GNUNET_TESTBED_operation_done (pos->nse_op); |
271 | if (NULL != pos->stats_op) | ||
272 | GNUNET_TESTBED_operation_done (pos->stats_op); | ||
212 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); | 273 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); |
213 | if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task) | 274 | if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task) |
214 | { | ||
215 | GNUNET_SCHEDULER_cancel (pos->stats_task); | 275 | GNUNET_SCHEDULER_cancel (pos->stats_task); |
216 | if (NULL != pos->stats) | ||
217 | GNUNET_STATISTICS_destroy(pos->stats, GNUNET_NO); | ||
218 | } | ||
219 | GNUNET_free (pos); | 276 | GNUNET_free (pos); |
220 | } | 277 | } |
278 | } | ||
279 | |||
221 | 280 | ||
222 | if (data_file != NULL) | 281 | /** |
282 | * Task run on shutdown; cleans up everything. | ||
283 | * | ||
284 | * @param cls unused | ||
285 | * @param tc unused | ||
286 | */ | ||
287 | static void | ||
288 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
289 | { | ||
290 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
291 | close_monitor_connections (); | ||
292 | if (NULL != testbed) | ||
293 | GNUNET_TESTBED_destroy (testbed); | ||
294 | if (NULL != controller) | ||
295 | GNUNET_TESTBED_controller_disconnect (controller); | ||
296 | if (NULL != copro) | ||
297 | GNUNET_TESTBED_controller_stop (copro); | ||
298 | while (0 > num_hosts) | ||
299 | GNUNET_TESTBED_host_destroy (hosts[--num_hosts]); | ||
300 | // FIXME: what about closing other files!? | ||
301 | if (NULL != data_file) | ||
223 | GNUNET_DISK_file_close (data_file); | 302 | GNUNET_DISK_file_close (data_file); |
224 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
225 | } | 303 | } |
226 | 304 | ||
227 | 305 | ||
228 | /** | 306 | /** |
229 | * Callback to call when network size estimate is updated. | 307 | * Callback to call when network size estimate is updated. |
230 | * | 308 | * |
231 | * @param cls closure | 309 | * @param cls closure with the 'struct NSEPeer' providing the update |
232 | * @param timestamp server timestamp | 310 | * @param timestamp server timestamp |
233 | * @param estimate the value of the current network size estimate | 311 | * @param estimate the value of the current network size estimate |
234 | * @param std_dev standard deviation (rounded down to nearest integer) | 312 | * @param std_dev standard deviation (rounded down to nearest integer) |
@@ -236,32 +314,34 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
236 | * | 314 | * |
237 | */ | 315 | */ |
238 | static void | 316 | static void |
239 | handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, | 317 | handle_estimate (void *cls, |
318 | struct GNUNET_TIME_Absolute timestamp, | ||
240 | double estimate, double std_dev) | 319 | double estimate, double std_dev) |
241 | { | 320 | { |
242 | struct NSEPeer *peer = cls; | 321 | struct NSEPeer *peer = cls; |
243 | char *output_buffer; | 322 | char output_buffer[512]; |
244 | size_t size; | 323 | size_t size; |
245 | 324 | ||
246 | if (output_file != NULL) | 325 | if (NULL == output_file) |
247 | { | 326 | { |
248 | size = | 327 | FPRINTF (stderr, |
249 | GNUNET_asprintf (&output_buffer, "%s %llu %llu %f %f %f\n", | 328 | "Received network size estimate from peer %p. Size: %f std.dev. %f\n", |
250 | GNUNET_i2s (&peer->daemon->id), peers_running, | 329 | peer, estimate, std_dev); |
251 | timestamp.abs_value, | 330 | return; |
252 | GNUNET_NSE_log_estimate_to_n (estimate), estimate, | 331 | } |
253 | std_dev); | 332 | size = GNUNET_snprintf (output_buffer, |
254 | if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) | 333 | sizeof (output_buffer), |
255 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | 334 | "%p %llu %llu %f %f %f\n", |
256 | GNUNET_free (output_buffer); | 335 | peer, peers_running, |
257 | } | 336 | timestamp.abs_value, |
258 | else | 337 | GNUNET_NSE_log_estimate_to_n (estimate), estimate, |
259 | FPRINTF (stderr, | 338 | std_dev); |
260 | "Received network size estimate from peer %s. Size: %f std.dev. %f\n", | 339 | if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) |
261 | GNUNET_i2s (&peer->daemon->id), estimate, std_dev); | 340 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
262 | 341 | "Unable to write to file!\n"); | |
263 | } | 342 | } |
264 | 343 | ||
344 | |||
265 | /** | 345 | /** |
266 | * Process core statistic values. | 346 | * Process core statistic values. |
267 | * | 347 | * |
@@ -277,29 +357,30 @@ core_stats_iterator (void *cls, const char *subsystem, const char *name, | |||
277 | uint64_t value, int is_persistent) | 357 | uint64_t value, int is_persistent) |
278 | { | 358 | { |
279 | struct NSEPeer *peer = cls; | 359 | struct NSEPeer *peer = cls; |
280 | char *output_buffer; | 360 | char output_buffer[512]; |
281 | size_t size; | 361 | size_t size; |
282 | 362 | ||
283 | if (output_file != NULL) | 363 | if (NULL == output_file) |
284 | { | 364 | { |
285 | size = | 365 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
286 | GNUNET_asprintf (&output_buffer, "%s [%s] %s %llu\n", | 366 | "%p -> %s [%s]: %llu\n", |
287 | GNUNET_i2s (&peer->daemon->id), | 367 | peer, subsystem, name, value); |
288 | subsystem, name, value); | 368 | return GNUNET_OK; |
289 | if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) | 369 | } |
290 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | 370 | size = |
291 | GNUNET_free (output_buffer); | 371 | GNUNET_snprintf (output_buffer, |
292 | } | 372 | sizeof (output_buffer), |
293 | else | 373 | "%p [%s] %s %llu\n", |
294 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 374 | peer, |
295 | "%s -> %s [%s]: %llu\n", | 375 | subsystem, name, value); |
296 | GNUNET_i2s (&peer->daemon->id), subsystem, name, value); | 376 | if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) |
297 | 377 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); | |
298 | return GNUNET_OK; | 378 | return GNUNET_OK; |
299 | } | 379 | } |
300 | 380 | ||
381 | |||
301 | /** | 382 | /** |
302 | * Continuation called by "get_stats" function. | 383 | * Continuation called by "get_stats" function once we are done. |
303 | * | 384 | * |
304 | * @param cls closure | 385 | * @param cls closure |
305 | * @param success GNUNET_OK if statistics were | 386 | * @param success GNUNET_OK if statistics were |
@@ -308,32 +389,43 @@ core_stats_iterator (void *cls, const char *subsystem, const char *name, | |||
308 | static void | 389 | static void |
309 | core_stats_cont (void *cls, int success); | 390 | core_stats_cont (void *cls, int success); |
310 | 391 | ||
392 | |||
393 | /** | ||
394 | * Function invoked periodically to get the statistics. | ||
395 | * | ||
396 | * @param cls 'struct NSEPeer' to get stats from | ||
397 | * @param tc scheduler context | ||
398 | */ | ||
311 | static void | 399 | static void |
312 | core_get_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 400 | core_get_stats (void *cls, |
401 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
313 | { | 402 | { |
314 | struct NSEPeer *peer = cls; | 403 | struct NSEPeer *peer = cls; |
315 | 404 | ||
316 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | 405 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
317 | { | 406 | { |
318 | GNUNET_STATISTICS_destroy(peer->stats, GNUNET_NO); | 407 | GNUNET_TESTBED_operation_done (peer->stats_op); |
319 | peer->stats = NULL; | 408 | peer->stats = NULL; |
409 | peer->stats_op = NULL; | ||
320 | return; | 410 | return; |
321 | } | 411 | } |
322 | else | 412 | /* FIXME: code duplication! */ |
323 | { | 413 | GNUNET_STATISTICS_get (peer->stats, "core", NULL, |
324 | GNUNET_STATISTICS_get(peer->stats, "core", NULL, | 414 | GNUNET_TIME_UNIT_FOREVER_REL, |
325 | GNUNET_TIME_UNIT_FOREVER_REL, | 415 | &core_stats_cont, |
326 | &core_stats_cont, &core_stats_iterator, peer); | 416 | &core_stats_iterator, peer); |
327 | GNUNET_STATISTICS_get(peer->stats, "transport", NULL, | 417 | GNUNET_STATISTICS_get (peer->stats, "transport", NULL, |
328 | GNUNET_TIME_UNIT_FOREVER_REL, | 418 | GNUNET_TIME_UNIT_FOREVER_REL, |
329 | NULL, &core_stats_iterator, peer); | 419 | NULL, |
330 | GNUNET_STATISTICS_get(peer->stats, "nse", NULL, | 420 | &core_stats_iterator, peer); |
331 | GNUNET_TIME_UNIT_FOREVER_REL, | 421 | GNUNET_STATISTICS_get (peer->stats, "nse", NULL, |
332 | NULL, &core_stats_iterator, peer); | 422 | GNUNET_TIME_UNIT_FOREVER_REL, |
333 | } | 423 | NULL, |
424 | &core_stats_iterator, peer); | ||
334 | peer->stats_task = GNUNET_SCHEDULER_NO_TASK; | 425 | peer->stats_task = GNUNET_SCHEDULER_NO_TASK; |
335 | } | 426 | } |
336 | 427 | ||
428 | |||
337 | /** | 429 | /** |
338 | * Continuation called by "get_stats" function. | 430 | * Continuation called by "get_stats" function. |
339 | * | 431 | * |
@@ -342,19 +434,136 @@ core_get_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
342 | * successfully obtained, GNUNET_SYSERR if not. | 434 | * successfully obtained, GNUNET_SYSERR if not. |
343 | */ | 435 | */ |
344 | static void | 436 | static void |
345 | core_stats_cont (void *cls, int success) | 437 | core_stats_cont (void *cls, |
438 | int success) | ||
346 | { | 439 | { |
347 | struct NSEPeer *peer = cls; | 440 | struct NSEPeer *peer = cls; |
348 | peer->stats_task = GNUNET_SCHEDULER_add_delayed (interval, &core_get_stats, | 441 | |
349 | peer); | 442 | if (GNUNET_OK != success) |
443 | return; | ||
444 | peer->stats_task = GNUNET_SCHEDULER_add_delayed (interval, | ||
445 | &core_get_stats, peer); | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Adapter function called to establish a connection to | ||
451 | * statistics service. | ||
452 | * | ||
453 | * @param cls closure | ||
454 | * @param cfg configuration of the peer to connect to; will be available until | ||
455 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
456 | * from GNUNET_TESTBED_service_connect() | ||
457 | * @return service handle to return in 'op_result', NULL on error | ||
458 | */ | ||
459 | static void * | ||
460 | statistics_connect_adapter (void *cls, | ||
461 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
462 | { | ||
463 | return GNUNET_STATISTICS_create ("<driver>", | ||
464 | cfg); | ||
350 | } | 465 | } |
351 | 466 | ||
352 | 467 | ||
353 | /** | 468 | /** |
469 | * Adapter function called to destroy a connection to | ||
470 | * statistics service. | ||
471 | * | ||
472 | * @param cls closure | ||
473 | * @param op_result service handle returned from the connect adapter | ||
474 | */ | ||
475 | static void | ||
476 | statistics_disconnect_adapter (void *cls, | ||
477 | void *op_result) | ||
478 | { | ||
479 | GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
484 | * Function called by testbed once we are connected to stats service. | ||
354 | * | 485 | * |
486 | * @param cls the 'struct NSEPeer' for which we connected to stats | ||
487 | * @param op connect operation handle | ||
488 | * @param ca_result handle to stats service | ||
489 | * @param emsg error message on failure | ||
355 | */ | 490 | */ |
356 | static void | 491 | static void |
357 | connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 492 | stat_run (void *cls, |
493 | struct GNUNET_TESTBED_Operation *op, | ||
494 | void *ca_result, | ||
495 | const char *emsg) | ||
496 | { | ||
497 | struct NSEPeer *current_peer = cls; | ||
498 | |||
499 | if (NULL == ca_result) | ||
500 | { | ||
501 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
502 | "Failed to connect to statistics service: %s\n", | ||
503 | emsg); | ||
504 | GNUNET_SCHEDULER_shutdown (); | ||
505 | return; | ||
506 | } | ||
507 | current_peer->stats = ca_result; | ||
508 | GNUNET_STATISTICS_get (current_peer->stats, "core", NULL, | ||
509 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
510 | &core_stats_cont, | ||
511 | &core_stats_iterator, current_peer); | ||
512 | GNUNET_STATISTICS_get (current_peer->stats, "transport", NULL, | ||
513 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
514 | NULL, | ||
515 | &core_stats_iterator, current_peer); | ||
516 | GNUNET_STATISTICS_get (current_peer->stats, "nse", NULL, | ||
517 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
518 | NULL, | ||
519 | &core_stats_iterator, current_peer); | ||
520 | } | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Adapter function called to establish a connection to | ||
525 | * NSE service. | ||
526 | * | ||
527 | * @param cls closure (the 'struct NSEPeer') | ||
528 | * @param cfg configuration of the peer to connect to; will be available until | ||
529 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
530 | * from GNUNET_TESTBED_service_connect() | ||
531 | * @return service handle to return in 'op_result', NULL on error | ||
532 | */ | ||
533 | static void * | ||
534 | nse_connect_adapter (void *cls, | ||
535 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
536 | { | ||
537 | struct NSEPeer *current_peer = cls; | ||
538 | |||
539 | return GNUNET_NSE_connect (cfg, &handle_estimate, current_peer); | ||
540 | } | ||
541 | |||
542 | |||
543 | /** | ||
544 | * Adapter function called to destroy a connection to | ||
545 | * NSE service. | ||
546 | * | ||
547 | * @param cls closure | ||
548 | * @param op_result service handle returned from the connect adapter | ||
549 | */ | ||
550 | static void | ||
551 | nse_disconnect_adapter (void *cls, | ||
552 | void *op_result) | ||
553 | { | ||
554 | GNUNET_NSE_disconnect (op_result); | ||
555 | } | ||
556 | |||
557 | |||
558 | /** | ||
559 | * Task run to connect to the NSE and statistics services to a subset of | ||
560 | * all of the running peers. | ||
561 | * | ||
562 | * @param cls handle the peer | ||
563 | * @param tc ignored | ||
564 | */ | ||
565 | static void | ||
566 | connect_nse_service () | ||
358 | { | 567 | { |
359 | struct NSEPeer *current_peer; | 568 | struct NSEPeer *current_peer; |
360 | unsigned int i; | 569 | unsigned int i; |
@@ -364,123 +573,107 @@ connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
364 | { | 573 | { |
365 | if ((connection_limit > 0) && | 574 | if ((connection_limit > 0) && |
366 | (num_peers > connection_limit) && | 575 | (num_peers > connection_limit) && |
367 | (i % (num_peers / connection_limit) != 0)) | 576 | (0 != (i % (num_peers / connection_limit)))) |
368 | continue; | 577 | continue; |
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 578 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
370 | "nse-profiler: connecting to nse service of peer %d\n", i); | 579 | "nse-profiler: connecting to nse service of peer %d\n", i); |
371 | current_peer = GNUNET_malloc (sizeof (struct NSEPeer)); | 580 | current_peer = GNUNET_malloc (sizeof (struct NSEPeer)); |
372 | current_peer->daemon = GNUNET_TESTING_daemon_get (pg, i); | 581 | current_peer->daemon = daemons[i]; |
373 | if (GNUNET_YES == | 582 | current_peer->nse_op |
374 | GNUNET_TESTING_test_daemon_running (GNUNET_TESTING_daemon_get (pg, i))) | 583 | = GNUNET_TESTBED_service_connect (NULL, |
375 | { | 584 | current_peer->daemon, |
376 | current_peer->nse_handle = | 585 | "nse", |
377 | GNUNET_NSE_connect (current_peer->daemon->cfg, &handle_estimate, | 586 | NULL, NULL, |
378 | current_peer); | 587 | &nse_connect_adapter, |
379 | GNUNET_assert (current_peer->nse_handle != NULL); | 588 | &nse_disconnect_adapter, |
380 | } | 589 | current_peer); |
381 | current_peer->stats = GNUNET_STATISTICS_create("profiler", current_peer->daemon->cfg); | 590 | current_peer->stats_op |
382 | GNUNET_STATISTICS_get(current_peer->stats, "core", NULL, | 591 | = GNUNET_TESTBED_service_connect (NULL, |
383 | GNUNET_TIME_UNIT_FOREVER_REL, | 592 | current_peer->daemon, |
384 | &core_stats_cont, &core_stats_iterator, current_peer); | 593 | "statistics", |
385 | GNUNET_STATISTICS_get(current_peer->stats, "transport", NULL, | 594 | &stat_run, current_peer, |
386 | GNUNET_TIME_UNIT_FOREVER_REL, | 595 | &statistics_connect_adapter, |
387 | NULL, &core_stats_iterator, current_peer); | 596 | &statistics_disconnect_adapter, |
388 | GNUNET_STATISTICS_get(current_peer->stats, "nse", NULL, | 597 | NULL); |
389 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
390 | NULL, &core_stats_iterator, current_peer); | ||
391 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); | 598 | GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); |
392 | } | 599 | } |
393 | } | 600 | } |
394 | 601 | ||
395 | 602 | ||
603 | /** | ||
604 | * Task that starts/stops peers to move to the next round. | ||
605 | * | ||
606 | * @param cls NULL, unused | ||
607 | * @param tc scheduler context (unused) | ||
608 | */ | ||
396 | static void | 609 | static void |
397 | churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 610 | next_round (void *cls, |
611 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
398 | 612 | ||
399 | 613 | ||
400 | /** | 614 | /** |
401 | * Continuation called by the "get_all" and "get" functions. | 615 | * Continuation called by the "get_all" and "get" functions at the |
616 | * end of a round. Obtains the final statistics and writes them to | ||
617 | * the file, then either starts the next round, or, if this was the | ||
618 | * last round, terminates the run. | ||
402 | * | 619 | * |
403 | * @param cls struct StatsContext | 620 | * @param cls struct StatsContext |
404 | * @param success GNUNET_OK if statistics were | 621 | * @param success GNUNET_OK if statistics were |
405 | * successfully obtained, GNUNET_SYSERR if not. | 622 | * successfully obtained, GNUNET_SYSERR if not. |
406 | */ | 623 | */ |
407 | static void | 624 | static void |
408 | stats_finished_callback (void *cls, int success) | 625 | stats_finished_callback (void *cls, |
626 | struct GNUNET_TESTBED_Operation *op, | ||
627 | const char *emsg) | ||
409 | { | 628 | { |
410 | struct StatsContext *stats_context = cls; | 629 | struct StatsContext *stats_context = cls; |
411 | char *buf; | 630 | char buf[512]; |
412 | int buf_len; | 631 | size_t buf_len; |
413 | 632 | ||
414 | if ((GNUNET_OK == success) && (data_file != NULL)) | 633 | if (NULL != emsg) |
415 | { | ||
416 | /* Stats lookup successful, write out data */ | ||
417 | buf = NULL; | ||
418 | buf_len = | ||
419 | GNUNET_asprintf (&buf, "TOTAL_NSE_RECEIVED_MESSAGES_%d: %u \n", | ||
420 | stats_context->shutdown, | ||
421 | stats_context->total_nse_received_messages); | ||
422 | if (buf_len > 0) | ||
423 | { | 634 | { |
424 | GNUNET_DISK_file_write (data_file, buf, buf_len); | 635 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
636 | "Failed to get statistics: %s\n", | ||
637 | emsg); | ||
638 | GNUNET_SCHEDULER_shutdown (); | ||
639 | GNUNET_free (stats_context); | ||
640 | return; | ||
425 | } | 641 | } |
426 | GNUNET_free_non_null (buf); | 642 | if (NULL != data_file) |
427 | |||
428 | buf = NULL; | ||
429 | buf_len = | ||
430 | GNUNET_asprintf (&buf, "TOTAL_NSE_TRANSMITTED_MESSAGES_%d: %u\n", | ||
431 | stats_context->shutdown, | ||
432 | stats_context->total_nse_transmitted_messages); | ||
433 | if (buf_len > 0) | ||
434 | { | 643 | { |
644 | /* Stats lookup successful, write out data */ | ||
645 | buf_len = | ||
646 | GNUNET_snprintf (buf, sizeof (buf), | ||
647 | "TOTAL_NSE_RECEIVED_MESSAGES_%u: %u \n", | ||
648 | current_round, | ||
649 | stats_context->total_nse_received_messages); | ||
435 | GNUNET_DISK_file_write (data_file, buf, buf_len); | 650 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
436 | } | 651 | buf_len = |
437 | GNUNET_free_non_null (buf); | 652 | GNUNET_snprintf (buf, sizeof (buf), |
438 | 653 | "TOTAL_NSE_TRANSMITTED_MESSAGES_%u: %u\n", | |
439 | buf = NULL; | 654 | current_round, |
440 | buf_len = | 655 | stats_context->total_nse_transmitted_messages); |
441 | GNUNET_asprintf (&buf, "TOTAL_NSE_CROSS_%d: %u \n", | 656 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
442 | stats_context->shutdown, | 657 | buf_len = |
443 | stats_context->total_nse_cross); | 658 | GNUNET_snprintf (buf, sizeof (buf), |
444 | if (buf_len > 0) | 659 | "TOTAL_NSE_CROSS_%u: %u \n", |
445 | { | 660 | current_round, |
661 | stats_context->total_nse_cross); | ||
446 | GNUNET_DISK_file_write (data_file, buf, buf_len); | 662 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
447 | } | 663 | buf_len = |
448 | GNUNET_free_non_null (buf); | 664 | GNUNET_snprintf (buf, sizeof (buf), |
449 | 665 | "TOTAL_NSE_EXTRA_%u: %u \n", | |
450 | buf = NULL; | 666 | current_round, |
451 | buf_len = | 667 | stats_context->total_nse_extra); |
452 | GNUNET_asprintf (&buf, "TOTAL_NSE_EXTRA_%d: %u \n", | ||
453 | stats_context->shutdown, | ||
454 | stats_context->total_nse_extra); | ||
455 | if (buf_len > 0) | ||
456 | { | ||
457 | GNUNET_DISK_file_write (data_file, buf, buf_len); | 668 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
458 | } | 669 | buf_len = |
459 | GNUNET_free_non_null (buf); | 670 | GNUNET_snprintf (buf, sizeof (buf), |
460 | 671 | "TOTAL_NSE_DISCARDED_%u: %u \n", | |
461 | buf = NULL; | 672 | current_round, |
462 | buf_len = | 673 | stats_context->total_discarded); |
463 | GNUNET_asprintf (&buf, "TOTAL_NSE_DISCARDED_%d: %u \n", | 674 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
464 | stats_context->shutdown, | 675 | } |
465 | stats_context->total_discarded); | 676 | GNUNET_SCHEDULER_add_now (&next_round, NULL); |
466 | if (buf_len > 0) | ||
467 | { | ||
468 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
469 | } | ||
470 | GNUNET_free_non_null (buf); | ||
471 | |||
472 | } | ||
473 | |||
474 | if (GNUNET_YES == stats_context->shutdown) | ||
475 | { | ||
476 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == shutdown_handle); | ||
477 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
478 | } | ||
479 | else | ||
480 | { | ||
481 | GNUNET_assert (churn_task == GNUNET_SCHEDULER_NO_TASK); | ||
482 | churn_task = GNUNET_SCHEDULER_add_now (&churn_peers, NULL); | ||
483 | } | ||
484 | GNUNET_free (stats_context); | 677 | GNUNET_free (stats_context); |
485 | } | 678 | } |
486 | 679 | ||
@@ -497,427 +690,363 @@ stats_finished_callback (void *cls, int success) | |||
497 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | 690 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration |
498 | */ | 691 | */ |
499 | static int | 692 | static int |
500 | statistics_iterator (void *cls, const struct GNUNET_PeerIdentity *peer, | 693 | statistics_iterator (void *cls, |
694 | const struct GNUNET_TESTBED_Peer *peer, | ||
501 | const char *subsystem, const char *name, uint64_t value, | 695 | const char *subsystem, const char *name, uint64_t value, |
502 | int is_persistent) | 696 | int is_persistent) |
503 | { | 697 | { |
504 | struct StatsContext *stats_context = cls; | 698 | struct StatsContext *stats_context = cls; |
699 | char buf[512]; | ||
700 | size_t buf_len; | ||
505 | 701 | ||
506 | if (0 == strcmp (subsystem, "nse")) | 702 | if (0 != strcmp (subsystem, "nse")) |
507 | { | 703 | return GNUNET_OK; |
508 | if (0 == strcmp (name, "# flood messages received")) | 704 | if (0 == strcmp (name, "# flood messages received")) |
509 | { | 705 | { |
510 | stats_context->total_nse_received_messages += value; | 706 | stats_context->total_nse_received_messages += value; |
511 | #if VERBOSE | 707 | if ( (verbose > 1) && |
512 | if (data_file != NULL) | 708 | (NULL != data_file) ) |
513 | { | 709 | { |
514 | char *buf; | 710 | buf_len = |
515 | int buf_len; | 711 | GNUNET_snprintf (buf, sizeof (buf), |
516 | 712 | "%p %u RECEIVED\n", | |
517 | buf = NULL; | 713 | peer, value); |
518 | buf_len = | 714 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
519 | GNUNET_asprintf (&buf, "%s %u RECEIVED\n", GNUNET_i2s(peer), value); | 715 | } |
520 | if (buf_len > 0) | ||
521 | { | ||
522 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
523 | } | ||
524 | GNUNET_free_non_null (buf); | ||
525 | } | ||
526 | #endif | ||
527 | } | 716 | } |
528 | if (0 == strcmp (name, "# flood messages transmitted")) | 717 | if (0 == strcmp (name, "# flood messages transmitted")) |
529 | { | 718 | { |
530 | stats_context->total_nse_transmitted_messages += value; | 719 | stats_context->total_nse_transmitted_messages += value; |
531 | #if VERBOSE | 720 | if ( (verbose > 1) && |
532 | if (data_file != NULL) | 721 | (NULL != data_file) ) |
533 | { | 722 | { |
534 | char *buf; | 723 | buf_len = |
535 | int buf_len; | 724 | GNUNET_snprintf (buf, sizeof (buf), |
536 | 725 | "%p %u TRANSMITTED\n", | |
537 | buf = NULL; | 726 | peer, value); |
538 | buf_len = | 727 | GNUNET_DISK_file_write (data_file, buf, buf_len); |
539 | GNUNET_asprintf (&buf, "%s %u TRANSMITTED\n", | 728 | } |
540 | GNUNET_i2s(peer), value); | ||
541 | if (buf_len > 0) | ||
542 | { | ||
543 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
544 | } | ||
545 | GNUNET_free_non_null (buf); | ||
546 | } | ||
547 | #endif | ||
548 | } | ||
549 | if (0 == strcmp (name, "# cross messages")) | ||
550 | { | ||
551 | stats_context->total_nse_cross += value; | ||
552 | } | 729 | } |
553 | if (0 == strcmp (name, "# extra messages")) | 730 | if (0 == strcmp (name, "# cross messages")) |
554 | { | 731 | stats_context->total_nse_cross += value; |
555 | stats_context->total_nse_extra += value; | 732 | if (0 == strcmp (name, "# extra messages")) |
556 | } | 733 | stats_context->total_nse_extra += value; |
557 | if (0 == strcmp (name, "# flood messages discarded (clock skew too large)")) | 734 | if (0 == strcmp (name, "# flood messages discarded (clock skew too large)")) |
558 | { | 735 | stats_context->total_discarded += value; |
559 | stats_context->total_discarded += value; | ||
560 | } | ||
561 | } | ||
562 | return GNUNET_OK; | 736 | return GNUNET_OK; |
563 | } | 737 | } |
564 | 738 | ||
565 | 739 | ||
740 | /** | ||
741 | * Function called upon completion of the node start/stop operations | ||
742 | * for the current round. Writes the new topology to disk. | ||
743 | */ | ||
566 | static void | 744 | static void |
567 | disconnect_nse_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 745 | write_topology () |
568 | { | 746 | { |
569 | struct NSEPeer *pos; | 747 | char temp_output_file[1024]; |
570 | char *buf; | ||
571 | struct StatsContext *stats_context; | ||
572 | 748 | ||
573 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting nse service of peers\n"); | 749 | if (NULL != topology_file) |
574 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
575 | while (NULL != (pos = peer_head)) | ||
576 | { | ||
577 | if (pos->nse_handle != NULL) | ||
578 | { | 750 | { |
579 | GNUNET_NSE_disconnect (pos->nse_handle); | 751 | GNUNET_snprintf (temp_output_file, sizeof (temp_output_file), |
580 | pos->nse_handle = NULL; | 752 | "%s_%llu.dot", |
753 | topology_file, current_round); | ||
754 | GNUNET_TESTBED_overlay_write_topology_to_file (controller, | ||
755 | temp_output_file); | ||
581 | } | 756 | } |
582 | GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); | ||
583 | if (NULL != pos->stats) | ||
584 | GNUNET_STATISTICS_destroy(pos->stats, GNUNET_NO); | ||
585 | if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task) | ||
586 | GNUNET_SCHEDULER_cancel (pos->stats_task); | ||
587 | GNUNET_free (pos); | ||
588 | } | ||
589 | |||
590 | GNUNET_asprintf (&buf, "round%llu", current_round); | ||
591 | if (GNUNET_OK == | ||
592 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler", buf, | ||
593 | &peers_next_round)) | ||
594 | { | ||
595 | current_round++; | ||
596 | if (current_round == 1) | ||
597 | { | ||
598 | stats_context = GNUNET_malloc (sizeof (struct StatsContext)); | ||
599 | stats_context->shutdown = GNUNET_NO; | ||
600 | GNUNET_TESTING_get_statistics (pg, &stats_finished_callback, | ||
601 | &statistics_iterator, stats_context); | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | GNUNET_assert (churn_task == GNUNET_SCHEDULER_NO_TASK); | ||
606 | churn_task = GNUNET_SCHEDULER_add_now (&churn_peers, NULL); | ||
607 | } | ||
608 | } | ||
609 | else /* No more rounds, let's shut it down! */ | ||
610 | { | ||
611 | stats_context = GNUNET_malloc (sizeof (struct StatsContext)); | ||
612 | stats_context->shutdown = GNUNET_YES; | ||
613 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
614 | shutdown_handle = GNUNET_SCHEDULER_NO_TASK; | ||
615 | GNUNET_TESTING_get_statistics (pg, &stats_finished_callback, | ||
616 | &statistics_iterator, stats_context); | ||
617 | } | ||
618 | GNUNET_free (buf); | ||
619 | } | 757 | } |
620 | 758 | ||
621 | 759 | ||
622 | /** | 760 | /** |
623 | * FIXME. | 761 | * We're at the end of a round. Stop monitoring, write total |
762 | * number of connections to log and get full stats. Then trigger | ||
763 | * the next round. | ||
624 | * | 764 | * |
625 | * @param cls unused | 765 | * @param cls unused, NULL |
626 | * @param emsg NULL on success | 766 | * @param tc unused |
627 | */ | 767 | */ |
628 | static void | 768 | static void |
629 | topology_output_callback (void *cls, const char *emsg) | 769 | finish_round (void *cls, |
770 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
630 | { | 771 | { |
631 | disconnect_task = | 772 | struct StatsContext *stats_context; |
632 | GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL); | 773 | char buf[1024]; |
633 | GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL); | 774 | size_t buf_len; |
775 | |||
776 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
777 | "Have %u connections\n", | ||
778 | total_connections); | ||
779 | if (NULL != data_file) | ||
780 | { | ||
781 | buf_len = GNUNET_snprintf (buf, sizeof (buf), | ||
782 | "CONNECTIONS_0: %u\n", | ||
783 | total_connections); | ||
784 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
785 | } | ||
786 | close_monitor_connections (); | ||
787 | stats_context = GNUNET_malloc (sizeof (struct StatsContext)); | ||
788 | GNUNET_TESTBED_get_statistics (num_peers_in_round[current_round], | ||
789 | daemons, | ||
790 | &statistics_iterator, | ||
791 | &stats_finished_callback, | ||
792 | stats_context); | ||
634 | } | 793 | } |
635 | 794 | ||
636 | 795 | ||
637 | /** | 796 | /** |
638 | * FIXME. | 797 | * We have reached the desired number of peers for the current round. |
639 | * | 798 | * Run it (by connecting and monitoring a few peers and waiting the |
640 | * @param cls closure | 799 | * specified delay before finishing the round). |
641 | * @param emsg NULL on success | ||
642 | */ | 800 | */ |
643 | static void | 801 | static void |
644 | churn_callback (void *cls, const char *emsg) | 802 | run_round () |
645 | { | 803 | { |
646 | char *temp_output_file; | 804 | write_topology (); |
647 | 805 | connect_nse_service (); | |
648 | if (emsg == NULL) /* Everything is okay! */ | 806 | GNUNET_SCHEDULER_add_delayed (wait_time, |
649 | { | 807 | &finish_round, |
650 | peers_running = peers_next_round; | 808 | NULL); |
651 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
652 | "Round %llu, churn finished successfully.\n", current_round); | ||
653 | GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
654 | GNUNET_asprintf (&temp_output_file, "%s_%llu.dot", topology_file, | ||
655 | current_round); | ||
656 | GNUNET_TESTING_peergroup_topology_to_file (pg, temp_output_file, | ||
657 | &topology_output_callback, NULL); | ||
658 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Writing topology to file %s\n", | ||
659 | temp_output_file); | ||
660 | GNUNET_free (temp_output_file); | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %llu, churn FAILED!!\n", | ||
665 | current_round); | ||
666 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
667 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
668 | } | ||
669 | } | 809 | } |
670 | 810 | ||
671 | 811 | ||
812 | /** | ||
813 | * Task run at the end of a round. Disconnect from all monitored | ||
814 | * peers; then get statistics from *all* peers. | ||
815 | * | ||
816 | * @param cls NULL, unused | ||
817 | * @param tc unused | ||
818 | */ | ||
672 | static void | 819 | static void |
673 | churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 820 | next_round (void *cls, |
821 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
674 | { | 822 | { |
675 | /* peers_running = GNUNET_TESTING_daemons_running(pg); */ | 823 | unsigned int i; |
676 | churn_task = GNUNET_SCHEDULER_NO_TASK; | 824 | |
677 | if (peers_next_round == peers_running) | 825 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting nse service of peers\n"); |
678 | { | 826 | current_round++; |
679 | /* Nothing to do... */ | 827 | |
680 | GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL); | 828 | if (current_round == num_rounds) |
681 | GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
682 | disconnect_task = | ||
683 | GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL); | ||
684 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %lu, doing nothing!\n", | ||
685 | current_round); | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | if (peers_next_round > num_peers) | ||
690 | { | 829 | { |
691 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 830 | /* this was the last round, terminate */ |
692 | "Asked to turn on more peers than we have!!\n"); | 831 | GNUNET_SCHEDULER_shutdown (); |
693 | GNUNET_SCHEDULER_cancel (shutdown_handle); | 832 | return; |
694 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
695 | } | 833 | } |
696 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 834 | if (num_peers_in_round[current_round] == peers_running) |
697 | "Round %llu, turning off %llu peers, turning on %llu peers!\n", | 835 | { |
698 | current_round, | 836 | /* no need to churn, just run next round */ |
699 | (peers_running > | 837 | run_round (); |
700 | peers_next_round) ? peers_running - peers_next_round : 0, | 838 | return; |
701 | (peers_next_round > | 839 | } |
702 | peers_running) ? peers_next_round - peers_running : 0); | 840 | |
703 | GNUNET_TESTING_daemons_churn (pg, "nse", | 841 | /* start peers if we have too few */ |
704 | (peers_running > | 842 | for (i=peers_running;i<num_peers_in_round[current_round];i++) |
705 | peers_next_round) ? peers_running - | 843 | GNUNET_TESTBED_peer_start (daemons[i], NULL, NULL); |
706 | peers_next_round : 0, | 844 | |
707 | (peers_next_round > | 845 | /* stop peers if we have too many */ |
708 | peers_running) ? peers_next_round - | 846 | for (i=num_peers_in_round[current_round];i<peers_running;i++) |
709 | peers_running : 0, wait_time, &churn_callback, | 847 | GNUNET_TESTBED_peer_stop (daemons[i], NULL, NULL); |
710 | NULL); | ||
711 | } | ||
712 | } | 848 | } |
713 | 849 | ||
714 | 850 | ||
851 | /** | ||
852 | * Function that will be called whenever something in the | ||
853 | * testbed changes. | ||
854 | * | ||
855 | * @param cls closure, NULL | ||
856 | * @param event information on what is happening | ||
857 | */ | ||
715 | static void | 858 | static void |
716 | nse_started_cb (void *cls, const char *emsg) | 859 | master_controller_cb (void *cls, |
860 | const struct GNUNET_TESTBED_EventInformation *event) | ||
717 | { | 861 | { |
718 | GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL); | 862 | switch (event->type) |
719 | disconnect_task = | 863 | { |
720 | GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL); | 864 | case GNUNET_TESTBED_ET_PEER_START: |
865 | peers_running++; | ||
866 | if (num_peers_in_round[current_round] == peers_running) | ||
867 | run_round (); | ||
868 | break; | ||
869 | case GNUNET_TESTBED_ET_PEER_STOP: | ||
870 | peers_running--; | ||
871 | if (num_peers_in_round[current_round] == peers_running) | ||
872 | run_round (); | ||
873 | break; | ||
874 | case GNUNET_TESTBED_ET_CONNECT: | ||
875 | total_connections++; | ||
876 | case GNUNET_TESTBED_ET_DISCONNECT: | ||
877 | total_connections--; | ||
878 | default: | ||
879 | break; | ||
880 | } | ||
721 | } | 881 | } |
722 | 882 | ||
723 | 883 | ||
724 | static void | 884 | static void |
725 | my_cb (void *cls, const char *emsg) | 885 | controller_start_cb (void *cls, |
886 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
887 | int status) | ||
726 | { | 888 | { |
727 | char *buf; | 889 | if (GNUNET_OK != status) |
728 | int buf_len; | 890 | { |
729 | 891 | copro = NULL; | |
730 | if (emsg != NULL) | 892 | GNUNET_SCHEDULER_shutdown (); |
731 | { | 893 | return; |
732 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 894 | } |
733 | "Peergroup callback called with error, aborting test!\n"); | 895 | num_hosts = GNUNET_TESTBED_hosts_load_from_file (hosts_file, |
734 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n"); | 896 | /* FIXME: & */ hosts); |
735 | ok = 1; | 897 | if (0 == num_hosts) |
736 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | 898 | { |
737 | return; | 899 | fprintf (stderr, |
738 | } | 900 | "Failed to read host information from `%s'\n", |
739 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 901 | hosts_file); |
740 | "Peer Group started successfully, connecting to NSE service for each peer!\n"); | 902 | return; |
741 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have %u connections\n", | 903 | } |
742 | total_connections); | 904 | controller = GNUNET_TESTBED_controller_connect (cfg, |
743 | if (data_file != NULL) | 905 | NULL, |
744 | { | 906 | 0 /* mask */, |
745 | buf = NULL; | 907 | &master_controller_cb, NULL); |
746 | buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections); | 908 | testbed = GNUNET_TESTBED_create (controller, |
747 | if (buf_len > 0) | 909 | num_hosts, hosts, |
748 | GNUNET_DISK_file_write (data_file, buf, buf_len); | 910 | num_peers, |
749 | GNUNET_free (buf); | 911 | cfg, |
750 | } | 912 | 0 /* FIXME: topology */, |
751 | peers_running = GNUNET_TESTING_daemons_running (pg); | 913 | NULL /* FIXME: topology options */); |
752 | GNUNET_TESTING_daemons_start_service (pg, "nse", wait_time, &nse_started_cb, | ||
753 | NULL); | ||
754 | |||
755 | } | 914 | } |
756 | 915 | ||
757 | 916 | ||
758 | /** | 917 | /** |
759 | * Function that will be called whenever two daemons are connected by | 918 | * Actual main function that runs the emulation. |
760 | * the testing library. | ||
761 | * | 919 | * |
762 | * @param cls closure | 920 | * @param cls unused |
763 | * @param first peer id for first daemon | 921 | * @param args remaining args, unused |
764 | * @param second peer id for the second daemon | 922 | * @param cfgfile name of the configuration |
765 | * @param distance distance between the connected peers | 923 | * @param cfg configuration handle |
766 | * @param first_cfg config for the first daemon | ||
767 | * @param second_cfg config for the second daemon | ||
768 | * @param first_daemon handle for the first daemon | ||
769 | * @param second_daemon handle for the second daemon | ||
770 | * @param emsg error message (NULL on success) | ||
771 | */ | 924 | */ |
772 | static void | 925 | static void |
773 | connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
774 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
775 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
776 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
777 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
778 | struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) | ||
779 | { | ||
780 | if (emsg == NULL) | ||
781 | total_connections++; | ||
782 | } | ||
783 | |||
784 | |||
785 | static void | ||
786 | run (void *cls, char *const *args, const char *cfgfile, | 926 | run (void *cls, char *const *args, const char *cfgfile, |
787 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 927 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
788 | { | 928 | { |
789 | char *temp_str; | 929 | char *tok; |
790 | struct GNUNET_TESTING_Host *hosts; | 930 | unsigned int num; |
791 | char *data_filename; | ||
792 | 931 | ||
793 | ok = 1; | 932 | ok = 1; |
794 | //testing_cfg = GNUNET_CONFIGURATION_create (); | ||
795 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); | 933 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); |
796 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | 934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); |
797 | #if VERBOSE | 935 | if (verbose) |
798 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", | 936 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing", |
799 | "use_progressbars", "YES"); | 937 | "use_progressbars", "YES"); |
800 | #endif | 938 | if (NULL == num_peer_spec) |
801 | if (GNUNET_OK != | ||
802 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing", | ||
803 | "num_peers", &num_peers)) | ||
804 | { | ||
805 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
806 | "Option TESTING:NUM_PEERS is required!\n"); | ||
807 | return; | ||
808 | } | ||
809 | |||
810 | if (GNUNET_OK != | ||
811 | GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse-profiler", | ||
812 | "WAIT_TIME", &wait_time)) | ||
813 | { | ||
814 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
815 | "Option nse-profiler:wait_time is required!\n"); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | if (GNUNET_OK != | ||
820 | GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse", | ||
821 | "INTERVAL", &interval)) | ||
822 | { | 939 | { |
823 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 940 | fprintf (stderr, "You need to specify the number of peers to run\n"); |
824 | "Option nse:interval is required!\n"); | ||
825 | return; | 941 | return; |
826 | } | 942 | } |
827 | 943 | for (tok = strtok (num_peer_spec, ","); NULL != tok; tok = strtok (NULL, ",")) | |
828 | if (GNUNET_OK != | 944 | { |
829 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler", | 945 | if (1 != sscanf (tok, "%u", &num)) |
830 | "connection_limit", | 946 | { |
831 | &connection_limit)) | 947 | fprintf (stderr, "You need to specify numbers, not `%s'\n", tok); |
832 | { | 948 | return; |
833 | connection_limit = 0; | 949 | } |
834 | } | 950 | if (0 == num) |
835 | 951 | { | |
836 | if (GNUNET_OK != | 952 | fprintf (stderr, "Refusing to run a round with 0 peers\n"); |
837 | GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler", | 953 | return; |
838 | "topology_output_file", | 954 | } |
839 | &topology_file)) | 955 | GNUNET_array_grow (num_peers_in_round, num_rounds, num); |
840 | { | 956 | num_peers = GNUNET_MAX (num_peers, num); |
841 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 957 | } |
842 | "Option nse-profiler:topology_output_file is required!\n"); | 958 | if (0 == num_peers) |
843 | return; | 959 | { |
844 | } | 960 | fprintf (stderr, "Refusing to run a testbed with no rounds\n"); |
845 | 961 | return; | |
846 | if (GNUNET_OK == | 962 | } |
847 | GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler", | 963 | daemons = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer*) * num_peers); |
848 | "data_output_file", | 964 | if ( (NULL != data_filename) && |
849 | &data_filename)) | 965 | (NULL == (data_file = |
850 | { | 966 | GNUNET_DISK_file_open (data_filename, |
851 | data_file = | 967 | GNUNET_DISK_OPEN_READWRITE | |
852 | GNUNET_DISK_file_open (data_filename, | 968 | GNUNET_DISK_OPEN_TRUNCATE | |
853 | GNUNET_DISK_OPEN_READWRITE | | 969 | GNUNET_DISK_OPEN_CREATE, |
854 | GNUNET_DISK_OPEN_TRUNCATE | | 970 | GNUNET_DISK_PERM_USER_READ | |
855 | GNUNET_DISK_OPEN_CREATE, | 971 | GNUNET_DISK_PERM_USER_WRITE))) ) |
856 | GNUNET_DISK_PERM_USER_READ | | 972 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, |
857 | GNUNET_DISK_PERM_USER_WRITE); | 973 | "open", |
858 | if (data_file == NULL) | 974 | data_filename); |
859 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | 975 | |
860 | data_filename); | 976 | if ( (NULL != output_filename) && |
861 | GNUNET_free (data_filename); | 977 | (NULL == (output_file = |
862 | } | 978 | GNUNET_DISK_file_open (output_filename, |
863 | 979 | GNUNET_DISK_OPEN_READWRITE | | |
864 | if (GNUNET_YES == | 980 | GNUNET_DISK_OPEN_CREATE, |
865 | GNUNET_CONFIGURATION_get_value_string (cfg, "nse-profiler", "output_file", | 981 | GNUNET_DISK_PERM_USER_READ | |
866 | &temp_str)) | 982 | GNUNET_DISK_PERM_USER_WRITE))) ) |
867 | { | 983 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", |
868 | output_file = | 984 | output_filename); |
869 | GNUNET_DISK_file_open (temp_str, | 985 | |
870 | GNUNET_DISK_OPEN_READWRITE | | 986 | if (NULL == |
871 | GNUNET_DISK_OPEN_CREATE, | 987 | (copro = GNUNET_TESTBED_controller_start (controller_ip, NULL, |
872 | GNUNET_DISK_PERM_USER_READ | | 988 | cfg, |
873 | GNUNET_DISK_PERM_USER_WRITE); | 989 | &controller_start_cb, NULL))) |
874 | if (output_file == NULL) | 990 | { |
875 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | 991 | fprintf (stderr, |
876 | temp_str); | 992 | "Failed to start controller\n"); |
877 | } | 993 | return; |
878 | GNUNET_free_non_null (temp_str); | 994 | } |
879 | 995 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | |
880 | hosts = GNUNET_TESTING_hosts_load (testing_cfg); | 996 | &shutdown_task, NULL); |
881 | |||
882 | pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, | ||
883 | &connect_cb, &my_cb, NULL, hosts); | ||
884 | GNUNET_assert (pg != NULL); | ||
885 | shutdown_handle = | ||
886 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
887 | &shutdown_task, NULL); | ||
888 | } | 997 | } |
889 | 998 | ||
890 | 999 | ||
891 | |||
892 | /** | 1000 | /** |
893 | * nse-profiler command line options | 1001 | * Main function. |
1002 | * | ||
1003 | * @return 0 on success | ||
894 | */ | 1004 | */ |
895 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
896 | {'V', "verbose", NULL, | ||
897 | gettext_noop ("be verbose (print progress information)"), | ||
898 | 0, &GNUNET_GETOPT_set_one, &verbose}, | ||
899 | GNUNET_GETOPT_OPTION_END | ||
900 | }; | ||
901 | |||
902 | |||
903 | int | 1005 | int |
904 | main (int argc, char *const *argv) | 1006 | main (int argc, char *const *argv) |
905 | { | 1007 | { |
1008 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1009 | {'C', "connections", "COUNT", | ||
1010 | gettext_noop ("limit to the number of connections to NSE services, 0 for none"), | ||
1011 | 1, &GNUNET_GETOPT_set_string, &num_peer_spec}, | ||
1012 | {'d', "details", "FILENAME", | ||
1013 | gettext_noop ("name of the file for writing connection information and statistics"), | ||
1014 | 1, &GNUNET_GETOPT_set_string, &data_filename}, | ||
1015 | {'H', "hosts", "FILENAME", | ||
1016 | gettext_noop ("name of the file with the login information for the testbed"), | ||
1017 | 1, &GNUNET_GETOPT_set_string, &hosts_file}, | ||
1018 | {'i', "ip", "CONTROLLER_IP", | ||
1019 | gettext_noop ("IP address of this system as seen by the rest of the testbed"), | ||
1020 | 1, &GNUNET_GETOPT_set_string, &controller_ip}, | ||
1021 | {'I', "interval", "DELAY", | ||
1022 | gettext_noop ("delay between queries to statistics during a round"), | ||
1023 | 1, &GNUNET_GETOPT_set_relative_time, &interval}, | ||
1024 | {'t', "topology", "FILENAME", | ||
1025 | gettext_noop ("prefix of the filenames we use for writing the topology for each round"), | ||
1026 | 1, &GNUNET_GETOPT_set_string, &topology_file}, | ||
1027 | {'o', "output", "FILENAME", | ||
1028 | gettext_noop ("name of the file for writing the main results"), | ||
1029 | 1, &GNUNET_GETOPT_set_string, &output_filename}, | ||
1030 | {'p', "peers", "NETWORKSIZESPEC", | ||
1031 | gettext_noop ("Number of peers to run in each round, separated by commas"), | ||
1032 | 1, &GNUNET_GETOPT_set_string, &num_peer_spec}, | ||
1033 | {'V', "verbose", NULL, | ||
1034 | gettext_noop ("be verbose (print progress information)"), | ||
1035 | 0, &GNUNET_GETOPT_increment_value, &verbose}, | ||
1036 | {'w', "wait", "DELAY", | ||
1037 | gettext_noop ("delay between rounds"), | ||
1038 | 1, &GNUNET_GETOPT_set_relative_time, &wait_time}, | ||
1039 | GNUNET_GETOPT_OPTION_END | ||
1040 | }; | ||
906 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | 1041 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) |
907 | return 2; | 1042 | return 2; |
908 | 1043 | GNUNET_log_setup ("nse-profiler", "WARNING", NULL); | |
909 | GNUNET_log_setup ("nse-profiler", | ||
910 | "WARNING", | ||
911 | NULL); | ||
912 | if (GNUNET_OK != | 1044 | if (GNUNET_OK != |
913 | GNUNET_PROGRAM_run (argc, argv, "nse-profiler", | 1045 | GNUNET_PROGRAM_run (argc, argv, "nse-profiler", |
914 | gettext_noop | 1046 | gettext_noop |
915 | ("Measure quality and performance of the NSE service."), | 1047 | ("Measure quality and performance of the NSE service."), |
916 | options, &run, NULL)) | 1048 | options, &run, NULL)) |
917 | ok = 1; | 1049 | ok = 1; |
918 | #if REMOVE_DIR | ||
919 | GNUNET_DISK_directory_remove ("/tmp/nse-profiler"); | ||
920 | #endif | ||
921 | return ok; | 1050 | return ok; |
922 | } | 1051 | } |
923 | 1052 | ||