diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/statistics/gnunet-statistics.c | 473 |
1 files changed, 434 insertions, 39 deletions
diff --git a/src/statistics/gnunet-statistics.c b/src/statistics/gnunet-statistics.c index 648fc89bb..2aefcadee 100644 --- a/src/statistics/gnunet-statistics.c +++ b/src/statistics/gnunet-statistics.c | |||
@@ -39,6 +39,11 @@ static int ret; | |||
39 | static char *subsystem; | 39 | static char *subsystem; |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * The path of the testbed data. | ||
43 | */ | ||
44 | static char *path_testbed; | ||
45 | |||
46 | /** | ||
42 | * Set to the specific stat value that we are after (or NULL for all). | 47 | * Set to the specific stat value that we are after (or NULL for all). |
43 | */ | 48 | */ |
44 | static char *name; | 49 | static char *name; |
@@ -79,10 +84,192 @@ static unsigned long long set_val; | |||
79 | static int set_value; | 84 | static int set_value; |
80 | 85 | ||
81 | /** | 86 | /** |
82 | * Handle for pending GET operation. | 87 | * @brief Representation of all (testbed) nodes. |
83 | */ | 88 | */ |
84 | static struct GNUNET_STATISTICS_GetHandle *gh; | 89 | static struct Node { |
90 | /** | ||
91 | * @brief Index of the node in this array. | ||
92 | */ | ||
93 | unsigned index_node; | ||
94 | |||
95 | /** | ||
96 | * @brief Configuration handle for this node | ||
97 | */ | ||
98 | struct GNUNET_CONFIGURATION_Handle *conf; | ||
99 | |||
100 | /** | ||
101 | * Handle for pending GET operation. | ||
102 | */ | ||
103 | struct GNUNET_STATISTICS_GetHandle *gh; | ||
104 | |||
105 | /** | ||
106 | * @brief Statistics handle nodes. | ||
107 | */ | ||
108 | struct GNUNET_STATISTICS_Handle *handle; | ||
109 | /** | ||
110 | * @brief Identifier for shutdown task for this node. | ||
111 | */ | ||
112 | struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
113 | } *nodes; | ||
85 | 114 | ||
115 | /** | ||
116 | * @brief Number of configurations of all (testbed) nodes. | ||
117 | */ | ||
118 | static unsigned num_nodes; | ||
119 | |||
120 | /** | ||
121 | * @brief Set of values for a combination of subsystem and name. | ||
122 | */ | ||
123 | struct ValueSet | ||
124 | { | ||
125 | /** | ||
126 | * @brief Subsystem of the valueset. | ||
127 | */ | ||
128 | char *subsystem; | ||
129 | |||
130 | /** | ||
131 | * @brief Name of the valueset. | ||
132 | */ | ||
133 | char *name; | ||
134 | |||
135 | /** | ||
136 | * @brief The values. | ||
137 | */ | ||
138 | uint64_t *values; | ||
139 | |||
140 | /** | ||
141 | * @brief Persistence of the values. | ||
142 | */ | ||
143 | int is_persistent; | ||
144 | }; | ||
145 | |||
146 | /** | ||
147 | * @brief Collection of all values (represented with #ValueSet). | ||
148 | */ | ||
149 | static struct GNUNET_CONTAINER_MultiHashMap *values; | ||
150 | |||
151 | /** | ||
152 | * @brief Number of nodes that have their values ready. | ||
153 | */ | ||
154 | static int num_nodes_ready; | ||
155 | |||
156 | /** | ||
157 | * @brief Create a new #ValueSet | ||
158 | * | ||
159 | * @param subsystem Subsystem of the valueset. | ||
160 | * @param name Name of the valueset. | ||
161 | * @param num_values Number of values in valueset - number of peers. | ||
162 | * @param is_persistent Persistence status of values. | ||
163 | * | ||
164 | * @return Newly allocated #ValueSet. | ||
165 | */ | ||
166 | static struct ValueSet * | ||
167 | new_value_set (const char *subsystem, | ||
168 | const char *name, | ||
169 | unsigned num_values, | ||
170 | int is_persistent) | ||
171 | { | ||
172 | struct ValueSet *value_set; | ||
173 | |||
174 | value_set = GNUNET_new (struct ValueSet); | ||
175 | value_set->subsystem = GNUNET_strdup (subsystem); | ||
176 | value_set->name = GNUNET_strdup (name); | ||
177 | value_set->values = GNUNET_new_array (num_values, uint64_t); | ||
178 | value_set->is_persistent = persistent; | ||
179 | return value_set; | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * @brief Print the (collected) values. | ||
184 | * | ||
185 | * Implements #GNUNET_CONTAINER_HashMapIterator. | ||
186 | * | ||
187 | * @param cls Closure - unused | ||
188 | * @param key #GNUNET_HashCode key of #GNUNET_CONTAINER_MultiHashMap iterator - | ||
189 | * unused | ||
190 | * @param value Values represented as #ValueSet. | ||
191 | * | ||
192 | * @return GNUNET_YES - continue iteration. | ||
193 | */ | ||
194 | static int | ||
195 | printer (void *cls, | ||
196 | const struct GNUNET_HashCode *key, | ||
197 | void *value) | ||
198 | { | ||
199 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); | ||
200 | const char *now_str; | ||
201 | struct ValueSet *value_set = value; | ||
202 | |||
203 | if (quiet == GNUNET_NO) | ||
204 | { | ||
205 | if (GNUNET_YES == watch) | ||
206 | { | ||
207 | now_str = GNUNET_STRINGS_absolute_time_to_string (now); | ||
208 | FPRINTF (stdout, | ||
209 | "%24s %s%12s %50s: ", | ||
210 | now_str, | ||
211 | value_set->is_persistent ? "!" : " ", | ||
212 | value_set->subsystem, | ||
213 | _(value_set->name)); | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | FPRINTF (stdout, | ||
218 | "%s%12s %50s: ", | ||
219 | value_set->is_persistent ? "!" : " ", | ||
220 | value_set->subsystem, | ||
221 | _(value_set->name)); | ||
222 | } | ||
223 | } | ||
224 | for (unsigned i = 0; i < num_nodes; i++) | ||
225 | { | ||
226 | FPRINTF (stdout, | ||
227 | "%16llu", | ||
228 | (unsigned long long) value_set->values[i]); | ||
229 | } | ||
230 | FPRINTF (stdout, "\n"); | ||
231 | GNUNET_free (value_set->subsystem); | ||
232 | GNUNET_free (value_set->name); | ||
233 | GNUNET_free (value_set->values); | ||
234 | GNUNET_free (value_set); | ||
235 | return GNUNET_YES; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * @brief Called once all statistic values are available. | ||
240 | * | ||
241 | * Implements #GNUNET_STATISTICS_Callback | ||
242 | * | ||
243 | * @param cls Closure - The index of the node. | ||
244 | * @param succes Whether statistics were obtained successfully. | ||
245 | */ | ||
246 | static void | ||
247 | continuation_print (void *cls, | ||
248 | int success) | ||
249 | { | ||
250 | const unsigned index_node = *(unsigned *) cls; | ||
251 | |||
252 | nodes[index_node].gh = NULL; | ||
253 | if (GNUNET_OK != success) | ||
254 | { | ||
255 | if (NULL == remote_host) | ||
256 | FPRINTF (stderr, | ||
257 | "%s", | ||
258 | _("Failed to obtain statistics.\n")); | ||
259 | else | ||
260 | FPRINTF (stderr, | ||
261 | _("Failed to obtain statistics from host `%s:%llu'\n"), | ||
262 | remote_host, | ||
263 | remote_port); | ||
264 | ret = 1; | ||
265 | } | ||
266 | num_nodes_ready++; | ||
267 | if (num_nodes_ready == num_nodes) | ||
268 | { | ||
269 | GNUNET_CONTAINER_multihashmap_iterate (values, printer, NULL); | ||
270 | GNUNET_SCHEDULER_shutdown(); | ||
271 | } | ||
272 | } | ||
86 | 273 | ||
87 | /** | 274 | /** |
88 | * Callback function to process statistic values. | 275 | * Callback function to process statistic values. |
@@ -95,11 +282,11 @@ static struct GNUNET_STATISTICS_GetHandle *gh; | |||
95 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | 282 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration |
96 | */ | 283 | */ |
97 | static int | 284 | static int |
98 | printer (void *cls, | 285 | printer_watch (void *cls, |
99 | const char *subsystem, | 286 | const char *subsystem, |
100 | const char *name, | 287 | const char *name, |
101 | uint64_t value, | 288 | uint64_t value, |
102 | int is_persistent) | 289 | int is_persistent) |
103 | { | 290 | { |
104 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); | 291 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); |
105 | const char *now_str; | 292 | const char *now_str; |
@@ -135,7 +322,6 @@ printer (void *cls, | |||
135 | return GNUNET_OK; | 322 | return GNUNET_OK; |
136 | } | 323 | } |
137 | 324 | ||
138 | |||
139 | /** | 325 | /** |
140 | * Function called last by the statistics code. | 326 | * Function called last by the statistics code. |
141 | * | 327 | * |
@@ -147,7 +333,10 @@ static void | |||
147 | cleanup (void *cls, | 333 | cleanup (void *cls, |
148 | int success) | 334 | int success) |
149 | { | 335 | { |
150 | gh = NULL; | 336 | for (unsigned i = 0; i < num_nodes; i++) |
337 | { | ||
338 | nodes[i].gh = NULL; | ||
339 | } | ||
151 | if (GNUNET_OK != success) | 340 | if (GNUNET_OK != success) |
152 | { | 341 | { |
153 | if (NULL == remote_host) | 342 | if (NULL == remote_host) |
@@ -164,6 +353,55 @@ cleanup (void *cls, | |||
164 | GNUNET_SCHEDULER_shutdown (); | 353 | GNUNET_SCHEDULER_shutdown (); |
165 | } | 354 | } |
166 | 355 | ||
356 | /** | ||
357 | * @brief Iterate over statistics values and store them in #values. | ||
358 | * They will be printed once all are available. | ||
359 | * | ||
360 | * @param cls Cosure - Node index. | ||
361 | * @param subsystem Subsystem of the value. | ||
362 | * @param name Name of the value. | ||
363 | * @param value Value itself. | ||
364 | * @param is_persistent Persistence. | ||
365 | * | ||
366 | * @return GNUNET_OK - continue. | ||
367 | */ | ||
368 | static int | ||
369 | collector (void *cls, | ||
370 | const char *subsystem, | ||
371 | const char *name, | ||
372 | uint64_t value, | ||
373 | int is_persistent) | ||
374 | { | ||
375 | const unsigned index_node = *(unsigned *) cls; | ||
376 | struct GNUNET_HashCode *key; | ||
377 | struct GNUNET_HashCode hc; | ||
378 | char *subsys_name; | ||
379 | unsigned len_subsys_name; | ||
380 | struct ValueSet *value_set; | ||
381 | |||
382 | len_subsys_name = strlen (subsystem) + 3 + strlen (name) + 1; | ||
383 | subsys_name = GNUNET_malloc (len_subsys_name); | ||
384 | SPRINTF (subsys_name, "%s---%s", subsystem, name); | ||
385 | key = &hc; | ||
386 | GNUNET_CRYPTO_hash (subsys_name, len_subsys_name, key); | ||
387 | GNUNET_free (subsys_name); | ||
388 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (values, key)) | ||
389 | { | ||
390 | // get | ||
391 | value_set = GNUNET_CONTAINER_multihashmap_get (values, key); | ||
392 | } | ||
393 | else | ||
394 | { | ||
395 | // new | ||
396 | value_set = new_value_set (subsystem, name, num_nodes, is_persistent); | ||
397 | } | ||
398 | // write | ||
399 | value_set->values[index_node] = value; | ||
400 | // put | ||
401 | GNUNET_CONTAINER_multihashmap_put (values, key, value_set, | ||
402 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
403 | return GNUNET_OK; | ||
404 | } | ||
167 | 405 | ||
168 | /** | 406 | /** |
169 | * Function run on shutdown to clean up. | 407 | * Function run on shutdown to clean up. |
@@ -173,10 +411,30 @@ cleanup (void *cls, | |||
173 | static void | 411 | static void |
174 | shutdown_task (void *cls) | 412 | shutdown_task (void *cls) |
175 | { | 413 | { |
176 | struct GNUNET_STATISTICS_Handle *h = cls; | 414 | const unsigned index_node = *(unsigned *) cls; |
415 | struct GNUNET_STATISTICS_Handle *h; | ||
416 | struct GNUNET_STATISTICS_GetHandle *gh; | ||
177 | 417 | ||
418 | nodes[index_node].shutdown_task = NULL; | ||
419 | if ( (NULL != path_testbed) && | ||
420 | (NULL != nodes[index_node].conf) ) | ||
421 | { | ||
422 | GNUNET_CONFIGURATION_destroy (nodes[index_node].conf); | ||
423 | nodes[index_node].conf = NULL; | ||
424 | } | ||
425 | |||
426 | h = nodes[index_node].handle; | ||
427 | gh = nodes[index_node].gh; | ||
178 | if (NULL == h) | 428 | if (NULL == h) |
429 | { | ||
430 | num_nodes_ready--; | ||
431 | if (0 == num_nodes_ready) | ||
432 | { | ||
433 | GNUNET_array_grow (nodes, num_nodes, 0); | ||
434 | GNUNET_CONTAINER_multihashmap_destroy (values); | ||
435 | } | ||
179 | return; | 436 | return; |
437 | } | ||
180 | if (NULL != gh) | 438 | if (NULL != gh) |
181 | { | 439 | { |
182 | GNUNET_STATISTICS_get_cancel (gh); | 440 | GNUNET_STATISTICS_get_cancel (gh); |
@@ -186,14 +444,21 @@ shutdown_task (void *cls) | |||
186 | (NULL != subsystem) && | 444 | (NULL != subsystem) && |
187 | (NULL != name) ) | 445 | (NULL != name) ) |
188 | GNUNET_assert (GNUNET_OK == | 446 | GNUNET_assert (GNUNET_OK == |
189 | GNUNET_STATISTICS_watch_cancel (h, | 447 | GNUNET_STATISTICS_watch_cancel (h, |
190 | subsystem, | 448 | subsystem, |
191 | name, | 449 | name, |
192 | &printer, | 450 | &printer_watch, |
193 | h)); | 451 | &nodes[index_node].index_node)); |
194 | GNUNET_STATISTICS_destroy (h, | 452 | GNUNET_STATISTICS_destroy (h, |
195 | GNUNET_NO); | 453 | GNUNET_NO); |
196 | h = NULL; | 454 | h = NULL; |
455 | |||
456 | num_nodes_ready--; | ||
457 | if (0 == num_nodes_ready) | ||
458 | { | ||
459 | GNUNET_array_grow (nodes, num_nodes, 0); | ||
460 | GNUNET_CONTAINER_multihashmap_destroy (values); | ||
461 | } | ||
197 | } | 462 | } |
198 | 463 | ||
199 | 464 | ||
@@ -205,8 +470,8 @@ shutdown_task (void *cls) | |||
205 | static void | 470 | static void |
206 | main_task (void *cls) | 471 | main_task (void *cls) |
207 | { | 472 | { |
208 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | 473 | unsigned index_node = *(unsigned *) cls; |
209 | struct GNUNET_STATISTICS_Handle *h; | 474 | const struct GNUNET_CONFIGURATION_Handle *cfg = nodes[index_node].conf; |
210 | 475 | ||
211 | if (set_value) | 476 | if (set_value) |
212 | { | 477 | { |
@@ -226,23 +491,23 @@ main_task (void *cls) | |||
226 | ret = 1; | 491 | ret = 1; |
227 | return; | 492 | return; |
228 | } | 493 | } |
229 | h = GNUNET_STATISTICS_create (subsystem, | 494 | nodes[index_node].handle = GNUNET_STATISTICS_create (subsystem, |
230 | cfg); | 495 | cfg); |
231 | if (NULL == h) | 496 | if (NULL == nodes[index_node].handle) |
232 | { | 497 | { |
233 | ret = 1; | 498 | ret = 1; |
234 | return; | 499 | return; |
235 | } | 500 | } |
236 | GNUNET_STATISTICS_set (h, | 501 | GNUNET_STATISTICS_set (nodes[index_node].handle, |
237 | name, | 502 | name, |
238 | (uint64_t) set_val, | 503 | (uint64_t) set_val, |
239 | persistent); | 504 | persistent); |
240 | GNUNET_STATISTICS_destroy (h, | 505 | GNUNET_STATISTICS_destroy (nodes[index_node].handle, |
241 | GNUNET_YES); | 506 | GNUNET_YES); |
242 | h = NULL; | 507 | nodes[index_node].handle = NULL; |
243 | return; | 508 | return; |
244 | } | 509 | } |
245 | if (NULL == (h = GNUNET_STATISTICS_create ("gnunet-statistics", | 510 | if (NULL == (nodes[index_node].handle = GNUNET_STATISTICS_create ("gnunet-statistics", |
246 | cfg))) | 511 | cfg))) |
247 | { | 512 | { |
248 | ret = 1; | 513 | ret = 1; |
@@ -251,13 +516,13 @@ main_task (void *cls) | |||
251 | if (GNUNET_NO == watch) | 516 | if (GNUNET_NO == watch) |
252 | { | 517 | { |
253 | if (NULL == | 518 | if (NULL == |
254 | (gh = GNUNET_STATISTICS_get (h, | 519 | (nodes[index_node].gh = GNUNET_STATISTICS_get (nodes[index_node].handle, |
255 | subsystem, | 520 | subsystem, |
256 | name, | 521 | name, |
257 | &cleanup, | 522 | &continuation_print, |
258 | &printer, | 523 | &collector, |
259 | h)) ) | 524 | &nodes[index_node].index_node)) ) |
260 | cleanup (h, | 525 | cleanup (nodes[index_node].handle, |
261 | GNUNET_SYSERR); | 526 | GNUNET_SYSERR); |
262 | } | 527 | } |
263 | else | 528 | else |
@@ -266,30 +531,128 @@ main_task (void *cls) | |||
266 | (NULL == name) ) | 531 | (NULL == name) ) |
267 | { | 532 | { |
268 | printf (_("No subsystem or name given\n")); | 533 | printf (_("No subsystem or name given\n")); |
269 | GNUNET_STATISTICS_destroy (h, | 534 | GNUNET_STATISTICS_destroy (nodes[index_node].handle, |
270 | GNUNET_NO); | 535 | GNUNET_NO); |
271 | h = NULL; | 536 | nodes[index_node].handle = NULL; |
272 | ret = 1; | 537 | ret = 1; |
273 | return; | 538 | return; |
274 | } | 539 | } |
275 | if (GNUNET_OK != | 540 | if (GNUNET_OK != |
276 | GNUNET_STATISTICS_watch (h, | 541 | GNUNET_STATISTICS_watch (nodes[index_node].handle, |
277 | subsystem, | 542 | subsystem, |
278 | name, | 543 | name, |
279 | &printer, | 544 | &printer_watch, |
280 | h)) | 545 | &nodes[index_node].index_node)) |
281 | { | 546 | { |
282 | fprintf (stderr, | 547 | fprintf (stderr, |
283 | _("Failed to initialize watch routine\n")); | 548 | _("Failed to initialize watch routine\n")); |
284 | GNUNET_SCHEDULER_add_now (&shutdown_task, | 549 | nodes[index_node].shutdown_task = |
285 | h); | 550 | GNUNET_SCHEDULER_add_now (&shutdown_task, |
551 | &nodes[index_node].index_node); | ||
286 | return; | 552 | return; |
287 | } | 553 | } |
288 | } | 554 | } |
289 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | 555 | nodes[index_node].shutdown_task = |
290 | h); | 556 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, |
557 | &nodes[index_node].index_node); | ||
291 | } | 558 | } |
292 | 559 | ||
560 | /** | ||
561 | * @brief Iter over content of a node's directory to check for existence of a | ||
562 | * config file. | ||
563 | * | ||
564 | * Implements #GNUNET_FileNameCallback | ||
565 | * | ||
566 | * @param cls pointer to indicate success | ||
567 | * @param filename filename inside the directory of the potential node | ||
568 | * | ||
569 | * @return to continue iteration or not to | ||
570 | */ | ||
571 | static int | ||
572 | iter_check_config (void *cls, | ||
573 | const char *filename) | ||
574 | { | ||
575 | if (0 == strncmp (GNUNET_STRINGS_get_short_name (filename), "config", 6)) | ||
576 | { | ||
577 | /* Found the config - stop iteration successfully */ | ||
578 | GNUNET_array_grow (nodes, num_nodes, num_nodes+1); | ||
579 | nodes[num_nodes-1].conf = GNUNET_CONFIGURATION_create(); | ||
580 | nodes[num_nodes-1].index_node = num_nodes-1; | ||
581 | if (GNUNET_OK != GNUNET_CONFIGURATION_load (nodes[num_nodes-1].conf, filename)) | ||
582 | { | ||
583 | FPRINTF (stderr, "Failed loading config `%s'\n", filename); | ||
584 | return GNUNET_SYSERR; | ||
585 | } | ||
586 | return GNUNET_NO; | ||
587 | } | ||
588 | else | ||
589 | { | ||
590 | /* Continue iteration */ | ||
591 | return GNUNET_OK; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * @brief Iterates over filenames in testbed directory. | ||
597 | * | ||
598 | * Implements #GNUNET_FileNameCallback | ||
599 | * | ||
600 | * Checks if the file is a directory for a testbed node | ||
601 | * and counts the nodes. | ||
602 | * | ||
603 | * @param cls counter of nodes | ||
604 | * @param filename full path of the file in testbed | ||
605 | * | ||
606 | * @return status whether to continue iteration | ||
607 | */ | ||
608 | static int | ||
609 | iter_testbed_path (void *cls, | ||
610 | const char *filename) | ||
611 | { | ||
612 | unsigned index_node; | ||
613 | |||
614 | GNUNET_assert (NULL != filename); | ||
615 | if (1 == SSCANF (GNUNET_STRINGS_get_short_name (filename), | ||
616 | "%u", | ||
617 | &index_node)) | ||
618 | { | ||
619 | if (-1 == GNUNET_DISK_directory_scan (filename, | ||
620 | iter_check_config, | ||
621 | NULL)) | ||
622 | { | ||
623 | /* This is probably no directory for a testbed node | ||
624 | * Go on with iteration */ | ||
625 | return GNUNET_OK; | ||
626 | } | ||
627 | return GNUNET_OK; | ||
628 | } | ||
629 | return GNUNET_OK; | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * @brief Count the number of nodes running in the testbed | ||
634 | * | ||
635 | * @param path_testbed path to the testbed data | ||
636 | * | ||
637 | * @return number of running nodes | ||
638 | */ | ||
639 | static int | ||
640 | discover_testbed_nodes (const char *path_testbed) | ||
641 | { | ||
642 | int num_dir_entries; | ||
643 | |||
644 | num_dir_entries = GNUNET_DISK_directory_scan (path_testbed, | ||
645 | iter_testbed_path, | ||
646 | NULL); | ||
647 | if (-1 == num_dir_entries) | ||
648 | { | ||
649 | FPRINTF (stderr, | ||
650 | "Failure during scanning directory `%s'\n", | ||
651 | path_testbed); | ||
652 | return -1; | ||
653 | } | ||
654 | return 0; | ||
655 | } | ||
293 | 656 | ||
294 | /** | 657 | /** |
295 | * Main function that will be run by the scheduler. | 658 | * Main function that will be run by the scheduler. |
@@ -361,8 +724,34 @@ run (void *cls, | |||
361 | "PORT", | 724 | "PORT", |
362 | remote_port); | 725 | remote_port); |
363 | } | 726 | } |
364 | GNUNET_SCHEDULER_add_now (&main_task, | 727 | if (NULL == path_testbed) |
365 | c); | 728 | { |
729 | values = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
730 | GNUNET_array_grow (nodes, num_nodes, 1); | ||
731 | nodes[0].index_node = 0; | ||
732 | nodes[0].conf = c; | ||
733 | GNUNET_SCHEDULER_add_now (&main_task, &nodes[0].index_node); | ||
734 | } | ||
735 | else | ||
736 | { | ||
737 | if (GNUNET_YES == watch) | ||
738 | { | ||
739 | printf (_("Not able to watch testbed nodes (yet - feel free to implement)\n")); | ||
740 | ret = 1; | ||
741 | return; | ||
742 | } | ||
743 | values = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); | ||
744 | if (-1 == discover_testbed_nodes (path_testbed)) | ||
745 | { | ||
746 | return; | ||
747 | } | ||
748 | /* For each config/node collect statistics */ | ||
749 | for (unsigned i = 0; i < num_nodes; i++) | ||
750 | { | ||
751 | GNUNET_SCHEDULER_add_now (&main_task, | ||
752 | &nodes[i].index_node); | ||
753 | } | ||
754 | } | ||
366 | } | 755 | } |
367 | 756 | ||
368 | 757 | ||
@@ -394,6 +783,12 @@ main (int argc, char *const *argv) | |||
394 | gettext_noop ("limit output to the given SUBSYSTEM"), | 783 | gettext_noop ("limit output to the given SUBSYSTEM"), |
395 | &subsystem), | 784 | &subsystem), |
396 | 785 | ||
786 | GNUNET_GETOPT_option_filename ('t', | ||
787 | "testbed", | ||
788 | "TESTBED", | ||
789 | gettext_noop ("path to the folder containing the testbed data"), | ||
790 | &path_testbed), | ||
791 | |||
397 | GNUNET_GETOPT_option_flag ('q', | 792 | GNUNET_GETOPT_option_flag ('q', |
398 | "quiet", | 793 | "quiet", |
399 | gettext_noop ("just print the statistics value"), | 794 | gettext_noop ("just print the statistics value"), |