988e6e15abeb413fcfd43cfc55f888f2261c226b
[oweals/gnunet.git] / src / nse / gnunet-nse-profiler.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4
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
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file nse/gnunet-nse-profiler.c
22  *
23  * @brief Profiling driver for the network size estimation service.
24  *        Generally, the profiler starts a given number of peers,
25  *        then churns some off, waits a certain amount of time, then
26  *        churns again, and repeats.
27  */
28 #include "platform.h"
29 #include "gnunet_testing_lib.h"
30 #include "gnunet_nse_service.h"
31
32 #define VERBOSE 3
33
34 struct NSEPeer
35 {
36   struct NSEPeer *prev;
37
38   struct NSEPeer *next;
39
40   struct GNUNET_TESTING_Daemon *daemon;
41
42   struct GNUNET_NSE_Handle *nse_handle;
43
44   struct GNUNET_STATISTICS_Handle *stats;
45   
46   GNUNET_SCHEDULER_TaskIdentifier stats_task;
47 };
48
49
50 struct StatsContext
51 {
52   /**
53    * How many messages have peers received during the test.
54    */
55   unsigned long long total_nse_received_messages;
56   /**
57    * How many messages have peers send during the test (should be == received).
58    */
59   unsigned long long total_nse_sent_messages;
60 };
61
62
63 static struct NSEPeer *peer_head;
64
65 static struct NSEPeer *peer_tail;
66
67 /**
68  * How long until we give up on connecting the peers?
69  */
70 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
71
72 static int ok;
73
74 /**
75  * Be verbose
76  */
77 static int verbose;
78
79 /**
80  * Total number of peers in the test.
81  */
82 static unsigned long long num_peers;
83
84 /**
85  * Global configuration file
86  */
87 static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
88
89 /**
90  * Total number of currently running peers.
91  */
92 static unsigned long long peers_running;
93
94 /**
95  * Current round we are in.
96  */
97 static unsigned long long current_round;
98
99 /**
100  * Peers desired in the next round.
101  */
102 static unsigned long long peers_next_round;
103
104 /**
105  * Maximum number of connections to NSE services.
106  */
107 static unsigned long long connection_limit;
108
109 /**
110  * Total number of connections in the whole network.
111  */
112 static unsigned int total_connections;
113
114 /**
115  * The currently running peer group.
116  */
117 static struct GNUNET_TESTING_PeerGroup *pg;
118
119 /**
120  * File to report results to.
121  */
122 static struct GNUNET_DISK_FileHandle *output_file;
123
124 /**
125  * File to log connection info, statistics to.
126  */
127 static struct GNUNET_DISK_FileHandle *data_file;
128
129 /**
130  * How many data points to capture before triggering next round?
131  */
132 static struct GNUNET_TIME_Relative wait_time;
133
134 /**
135  * NSE interval.
136  */
137 static struct GNUNET_TIME_Relative interval;
138
139 /**
140  * Task called to disconnect peers.
141  */
142 static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
143
144 /**
145  * Task called to shutdown test.
146  */
147 static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
148
149 /**
150  * Task used to churn the network.
151  */
152 static GNUNET_SCHEDULER_TaskIdentifier churn_task;
153
154 static char *topology_file;
155
156 /**
157  * Check whether peers successfully shut down.
158  */
159 static void
160 shutdown_callback (void *cls, const char *emsg)
161 {
162   if (emsg != NULL)
163   {
164 #if VERBOSE
165     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
166 #endif
167     if (ok == 0)
168       ok = 666;
169   }
170   else
171   {
172 #if VERBOSE
173     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
174 #endif
175     ok = 0;
176   }
177 }
178
179
180 static void
181 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
182 {
183   struct NSEPeer *pos;
184
185 #if VERBOSE
186   fprintf (stderr, "Ending test.\n");
187 #endif
188
189   if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
190   {
191     GNUNET_SCHEDULER_cancel (disconnect_task);
192     disconnect_task = GNUNET_SCHEDULER_NO_TASK;
193   }
194   while (NULL != (pos = peer_head))
195   {
196     if (pos->nse_handle != NULL)
197       GNUNET_NSE_disconnect (pos->nse_handle);
198     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos);
199     GNUNET_free (pos);
200   }
201
202   if (data_file != NULL)
203     GNUNET_DISK_file_close (data_file);
204   GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
205 }
206
207
208 /**
209  * Callback to call when network size estimate is updated.
210  *
211  * @param cls closure
212  * @param timestamp server timestamp
213  * @param estimate the value of the current network size estimate
214  * @param std_dev standard deviation (rounded down to nearest integer)
215  *                of the size estimation values seen
216  *
217  */
218 static void
219 handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp,
220                  double estimate, double std_dev)
221 {
222   struct NSEPeer *peer = cls;
223   char *output_buffer;
224   size_t size;
225
226   if (output_file != NULL)
227   {
228     size =
229         GNUNET_asprintf (&output_buffer, "%s %llu %llu %f %f %f\n",
230                          GNUNET_i2s (&peer->daemon->id), peers_running,
231                          timestamp.abs_value,
232                          GNUNET_NSE_log_estimate_to_n (estimate), estimate,
233                          std_dev);
234     if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
235       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
236     GNUNET_free (output_buffer);
237   }
238   else
239     fprintf (stderr,
240              "Received network size estimate from peer %s. Size: %f std.dev. %f\n",
241              GNUNET_i2s (&peer->daemon->id), estimate, std_dev);
242
243 }
244
245 /**
246  * Process core statistic values.
247  *
248  * @param cls closure
249  * @param subsystem name of subsystem that created the statistic
250  * @param name the name of the datum
251  * @param value the current value
252  * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
253  * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
254  */
255 static int
256 core_stats_iterator (void *cls, const char *subsystem, const char *name,
257                      uint64_t value, int is_persistent)
258 {
259   struct NSEPeer *peer = cls;
260   char *output_buffer;
261   size_t size;
262
263   if (output_file != NULL)
264   {
265     size =
266         GNUNET_asprintf (&output_buffer, "%s [%s] %s %llu\n",
267                           GNUNET_i2s (&peer->daemon->id),
268                          subsystem, name, value);
269     if (size != GNUNET_DISK_file_write (output_file, output_buffer, size))
270       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n");
271     GNUNET_free (output_buffer);
272   }
273   else
274     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
275                 "%s -> %s [%s]: %llu\n",
276                 GNUNET_i2s (&peer->daemon->id), subsystem, name, value);
277
278   return GNUNET_OK;
279 }
280
281 /**
282  * Continuation called by "get_stats" function.
283  *
284  * @param cls closure
285  * @param success GNUNET_OK if statistics were
286  *        successfully obtained, GNUNET_SYSERR if not.
287  */
288 static void
289 core_stats_cont (void *cls, int success);
290
291 static void
292 core_get_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
293 {
294   struct NSEPeer *peer = cls;
295   
296   peer->stats_task = GNUNET_SCHEDULER_NO_TASK;
297   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
298   {
299     GNUNET_STATISTICS_destroy(peer->stats, GNUNET_NO);
300     peer->stats = NULL;
301   }
302   else
303   {
304     GNUNET_STATISTICS_get(peer->stats, "core", NULL,
305                           GNUNET_TIME_UNIT_FOREVER_REL,
306                           &core_stats_cont, &core_stats_iterator, peer);
307     GNUNET_STATISTICS_get(peer->stats, "transport", NULL,
308                           GNUNET_TIME_UNIT_FOREVER_REL,
309                           NULL, &core_stats_iterator, peer);
310     GNUNET_STATISTICS_get(peer->stats, "nse", NULL,
311                           GNUNET_TIME_UNIT_FOREVER_REL,
312                           NULL, &core_stats_iterator, peer);
313   }
314 }
315
316 /**
317  * Continuation called by "get_stats" function.
318  *
319  * @param cls closure
320  * @param success GNUNET_OK if statistics were
321  *        successfully obtained, GNUNET_SYSERR if not.
322  */
323 static void
324 core_stats_cont (void *cls, int success)
325 {
326   struct NSEPeer *peer = cls;
327   peer->stats_task = GNUNET_SCHEDULER_add_delayed (interval, &core_get_stats,
328                                                    peer);
329 }
330
331
332 /**
333  *
334  */
335 static void
336 connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
337 {
338   struct NSEPeer *current_peer;
339   unsigned int i;
340
341 #if VERBOSE
342   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to nse service of peers\n");
343 #endif
344   for (i = 0; i < num_peers; i++)
345   {
346     if ((connection_limit > 0) && (i % (num_peers / connection_limit) != 0))
347       continue;
348 #if VERBOSE
349     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
350                 "nse-profiler: connecting to nse service of peer %d\n", i);
351 #endif
352     current_peer = GNUNET_malloc (sizeof (struct NSEPeer));
353     current_peer->daemon = GNUNET_TESTING_daemon_get (pg, i);
354     if (GNUNET_YES ==
355         GNUNET_TESTING_test_daemon_running (GNUNET_TESTING_daemon_get (pg, i)))
356     {
357       current_peer->nse_handle =
358           GNUNET_NSE_connect (current_peer->daemon->cfg, &handle_estimate,
359                               current_peer);
360       GNUNET_assert (current_peer->nse_handle != NULL);
361     }
362     current_peer->stats = GNUNET_STATISTICS_create("profiler", current_peer->daemon->cfg);
363     GNUNET_STATISTICS_get(current_peer->stats, "core", NULL,
364                           GNUNET_TIME_UNIT_FOREVER_REL,
365                           &core_stats_cont, &core_stats_iterator, current_peer);
366     GNUNET_STATISTICS_get(current_peer->stats, "transport", NULL,
367                           GNUNET_TIME_UNIT_FOREVER_REL,
368                           NULL, &core_stats_iterator, current_peer);
369     GNUNET_STATISTICS_get(current_peer->stats, "nse", NULL,
370                           GNUNET_TIME_UNIT_FOREVER_REL,
371                           NULL, &core_stats_iterator, current_peer);
372     GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer);
373   }
374 }
375
376
377 static void
378 churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
379
380
381 /**
382  * Continuation called by the "get_all" and "get" functions.
383  *
384  * @param cls struct StatsContext
385  * @param success GNUNET_OK if statistics were
386  *        successfully obtained, GNUNET_SYSERR if not.
387  */
388 static void
389 stats_finished_callback (void *cls, int success)
390 {
391   struct StatsContext *stats_context = cls;
392   char *buf;
393   int buf_len;
394
395   if ((GNUNET_OK == success) && (data_file != NULL))
396   {
397     /* Stats lookup successful, write out data */
398     buf = NULL;
399     buf_len =
400         GNUNET_asprintf (&buf, "TOTAL_NSE_RECEIVED_MESSAGES: %u\n",
401                          stats_context->total_nse_received_messages);
402     if (buf_len > 0)
403     {
404       GNUNET_DISK_file_write (data_file, buf, buf_len);
405     }
406     GNUNET_free_non_null (buf);
407     buf = NULL;
408     buf_len =
409         GNUNET_asprintf (&buf, "TOTAL_NSE_SENT_MESSAGES: %u\n",
410                          stats_context->total_nse_sent_messages);
411     if (buf_len > 0)
412     {
413       GNUNET_DISK_file_write (data_file, buf, buf_len);
414     }
415     GNUNET_free_non_null (buf);
416   }
417
418   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == shutdown_handle);
419   shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
420   GNUNET_free (stats_context);
421 }
422
423
424 /**
425  * Callback function to process statistic values.
426  *
427  * @param cls struct StatsContext
428  * @param peer the peer the statistics belong to
429  * @param subsystem name of subsystem that created the statistic
430  * @param name the name of the datum
431  * @param value the current value
432  * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
433  * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
434  */
435 static int
436 statistics_iterator (void *cls, const struct GNUNET_PeerIdentity *peer,
437                      const char *subsystem, const char *name, uint64_t value,
438                      int is_persistent)
439 {
440   struct StatsContext *stats_context = cls;
441
442   if (0 == strcmp (subsystem, "nse"))
443   {
444     if (0 == strcmp (name, "# flood messages received"))
445     {
446       stats_context->total_nse_received_messages += value;
447 #if VERBOSE
448       if (data_file != NULL)
449       {
450         char *buf;
451         int buf_len;
452
453         buf = NULL;
454         buf_len =
455             GNUNET_asprintf (&buf, "%s %u RECEIVED\n", GNUNET_i2s(peer), value);
456         if (buf_len > 0)
457         {
458           GNUNET_DISK_file_write (data_file, buf, buf_len);
459         }
460         GNUNET_free_non_null (buf);
461       }
462 #endif
463     }
464     if (0 == strcmp (name, "# flood messages sent"))
465     {
466       stats_context->total_nse_sent_messages += value;
467 #if VERBOSE
468       if (data_file != NULL)
469       {
470         char *buf;
471         int buf_len;
472
473         buf = NULL;
474         buf_len =
475             GNUNET_asprintf (&buf, "%s %u SENT\n", GNUNET_i2s(peer), value);
476         if (buf_len > 0)
477         {
478           GNUNET_DISK_file_write (data_file, buf, buf_len);
479         }
480         GNUNET_free_non_null (buf);
481       }
482 #endif
483     }
484   }
485   return GNUNET_OK;
486 }
487
488
489 static void
490 disconnect_nse_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
491 {
492   struct NSEPeer *pos;
493   char *buf;
494   struct StatsContext *stats_context;
495
496   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting nse service of peers\n");
497   disconnect_task = GNUNET_SCHEDULER_NO_TASK;
498   pos = peer_head;
499   while (NULL != (pos = peer_head))
500   {
501     if (pos->nse_handle != NULL)
502     {
503       GNUNET_NSE_disconnect (pos->nse_handle);
504       pos->nse_handle = NULL;
505     }
506     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos);
507     if (NULL != pos->stats)
508       GNUNET_STATISTICS_destroy(pos->stats, GNUNET_NO);
509     if (GNUNET_SCHEDULER_NO_TASK != pos->stats_task)
510       GNUNET_SCHEDULER_cancel (pos->stats_task);
511     GNUNET_free (pos);
512   }
513
514   GNUNET_asprintf (&buf, "round%llu", current_round);
515   if (GNUNET_OK ==
516       GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler", buf,
517                                              &peers_next_round))
518   {
519     current_round++;
520     GNUNET_assert (churn_task == GNUNET_SCHEDULER_NO_TASK);
521     churn_task = GNUNET_SCHEDULER_add_now (&churn_peers, NULL);
522   }
523   else                          /* No more rounds, let's shut it down! */
524   {
525     stats_context = GNUNET_malloc (sizeof (struct StatsContext));
526     GNUNET_SCHEDULER_cancel (shutdown_handle);
527     shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
528     GNUNET_TESTING_get_statistics (pg, &stats_finished_callback,
529                                    &statistics_iterator, stats_context);
530   }
531   GNUNET_free (buf);
532 }
533
534
535 /**
536  * FIXME.
537  *
538  * @param cls unused
539  * @param emsg NULL on success
540  */
541 static void
542 topology_output_callback (void *cls, const char *emsg)
543 {
544   disconnect_task =
545       GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
546   GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
547 }
548
549
550 /**
551  * FIXME.
552  *
553  * @param cls closure
554  * @param emsg NULL on success
555  */
556 static void
557 churn_callback (void *cls, const char *emsg)
558 {
559   char *temp_output_file;
560
561   if (emsg == NULL)             /* Everything is okay! */
562   {
563     peers_running = peers_next_round;
564     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
565                 "Round %llu, churn finished successfully.\n", current_round);
566     GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK);
567     GNUNET_asprintf (&temp_output_file, "%s_%llu.dot", topology_file,
568                      current_round);
569     GNUNET_TESTING_peergroup_topology_to_file (pg, temp_output_file,
570                                                &topology_output_callback, NULL);
571     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Writing topology to file %s\n",
572                 temp_output_file);
573     GNUNET_free (temp_output_file);
574   }
575   else
576   {
577     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %llu, churn FAILED!!\n",
578                 current_round);
579     GNUNET_SCHEDULER_cancel (shutdown_handle);
580     shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
581   }
582 }
583
584
585 static void
586 churn_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
587 {
588   /* peers_running = GNUNET_TESTING_daemons_running(pg); */
589   churn_task = GNUNET_SCHEDULER_NO_TASK;
590   if (peers_next_round == peers_running)
591   {
592     /* Nothing to do... */
593     GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
594     GNUNET_assert (disconnect_task == GNUNET_SCHEDULER_NO_TASK);
595     disconnect_task =
596         GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
597     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Round %lu, doing nothing!\n",
598                 current_round);
599   }
600   else
601   {
602     if (peers_next_round > num_peers)
603     {
604       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605                   "Asked to turn on more peers than we have!!\n");
606       GNUNET_SCHEDULER_cancel (shutdown_handle);
607       GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
608     }
609     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
610                 "Round %llu, turning off %llu peers, turning on %llu peers!\n",
611                 current_round,
612                 (peers_running >
613                  peers_next_round) ? peers_running - peers_next_round : 0,
614                 (peers_next_round >
615                  peers_running) ? peers_next_round - peers_running : 0);
616     GNUNET_TESTING_daemons_churn (pg, "nse",
617                                   (peers_running >
618                                    peers_next_round) ? peers_running -
619                                   peers_next_round : 0,
620                                   (peers_next_round >
621                                    peers_running) ? peers_next_round -
622                                   peers_running : 0, wait_time, &churn_callback,
623                                   NULL);
624   }
625 }
626
627
628 static void
629 nse_started_cb (void *cls, const char *emsg)
630 {
631   GNUNET_SCHEDULER_add_now (&connect_nse_service, NULL);
632   disconnect_task =
633       GNUNET_SCHEDULER_add_delayed (wait_time, &disconnect_nse_peers, NULL);
634 }
635
636
637 static void
638 my_cb (void *cls, const char *emsg)
639 {
640   char *buf;
641   int buf_len;
642
643   if (emsg != NULL)
644   {
645     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
646                 "Peergroup callback called with error, aborting test!\n");
647     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
648     ok = 1;
649     GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
650     return;
651   }
652 #if VERBOSE
653   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
654               "Peer Group started successfully, connecting to NSE service for each peer!\n");
655 #endif
656   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have %u connections\n",
657               total_connections);
658   if (data_file != NULL)
659   {
660     buf = NULL;
661     buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections);
662     if (buf_len > 0)
663       GNUNET_DISK_file_write (data_file, buf, buf_len);
664     GNUNET_free (buf);
665   }
666   peers_running = GNUNET_TESTING_daemons_running (pg);
667   GNUNET_TESTING_daemons_start_service (pg, "nse", wait_time, &nse_started_cb,
668                                         NULL);
669
670 }
671
672
673 /**
674  * Function that will be called whenever two daemons are connected by
675  * the testing library.
676  *
677  * @param cls closure
678  * @param first peer id for first daemon
679  * @param second peer id for the second daemon
680  * @param distance distance between the connected peers
681  * @param first_cfg config for the first daemon
682  * @param second_cfg config for the second daemon
683  * @param first_daemon handle for the first daemon
684  * @param second_daemon handle for the second daemon
685  * @param emsg error message (NULL on success)
686  */
687 static void
688 connect_cb (void *cls, const struct GNUNET_PeerIdentity *first,
689             const struct GNUNET_PeerIdentity *second, uint32_t distance,
690             const struct GNUNET_CONFIGURATION_Handle *first_cfg,
691             const struct GNUNET_CONFIGURATION_Handle *second_cfg,
692             struct GNUNET_TESTING_Daemon *first_daemon,
693             struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
694 {
695   if (emsg == NULL)
696     total_connections++;
697 }
698
699
700 static void
701 run (void *cls, char *const *args, const char *cfgfile,
702      const struct GNUNET_CONFIGURATION_Handle *cfg)
703 {
704   char *temp_str;
705   struct GNUNET_TESTING_Host *hosts;
706   char *data_filename;
707
708   ok = 1;
709   //testing_cfg = GNUNET_CONFIGURATION_create ();
710   testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
711 #if VERBOSE
712   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
713   GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
714                                          "use_progressbars", "YES");
715 #endif
716   if (GNUNET_OK !=
717       GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing",
718                                              "num_peers", &num_peers))
719   {
720     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
721                 "Option TESTING:NUM_PEERS is required!\n");
722     return;
723   }
724
725   if (GNUNET_OK !=
726       GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse-profiler",
727                                            "WAIT_TIME", &wait_time))
728   {
729     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
730                 "Option nse-profiler:wait_time is required!\n");
731     return;
732   }
733
734   if (GNUNET_OK !=
735       GNUNET_CONFIGURATION_get_value_time (testing_cfg, "nse",
736                                            "INTERVAL", &interval))
737   {
738     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
739                 "Option nse:interval is required!\n");
740     return;
741   }
742
743   if (GNUNET_OK !=
744       GNUNET_CONFIGURATION_get_value_number (testing_cfg, "nse-profiler",
745                                              "connection_limit",
746                                              &connection_limit))
747   {
748     connection_limit = 0;
749   }
750
751   if (GNUNET_OK !=
752       GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler",
753                                              "topology_output_file",
754                                              &topology_file))
755   {
756     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757                 "Option nse-profiler:topology_output_file is required!\n");
758     return;
759   }
760
761   if (GNUNET_OK ==
762       GNUNET_CONFIGURATION_get_value_string (testing_cfg, "nse-profiler",
763                                              "data_output_file",
764                                              &data_filename))
765   {
766     data_file =
767         GNUNET_DISK_file_open (data_filename,
768                                GNUNET_DISK_OPEN_READWRITE |
769                                GNUNET_DISK_OPEN_TRUNCATE |
770                                GNUNET_DISK_OPEN_CREATE,
771                                GNUNET_DISK_PERM_USER_READ |
772                                GNUNET_DISK_PERM_USER_WRITE);
773     if (data_file == NULL)
774       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
775                   data_filename);
776     GNUNET_free (data_filename);
777   }
778
779   if (GNUNET_YES ==
780       GNUNET_CONFIGURATION_get_value_string (cfg, "nse-profiler", "output_file",
781                                              &temp_str))
782   {
783     output_file =
784         GNUNET_DISK_file_open (temp_str,
785                                GNUNET_DISK_OPEN_READWRITE |
786                                GNUNET_DISK_OPEN_CREATE,
787                                GNUNET_DISK_PERM_USER_READ |
788                                GNUNET_DISK_PERM_USER_WRITE);
789     if (output_file == NULL)
790       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n",
791                   temp_str);
792   }
793   GNUNET_free_non_null (temp_str);
794
795   hosts = GNUNET_TESTING_hosts_load (testing_cfg);
796
797   pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
798                                        &connect_cb, &my_cb, NULL, hosts);
799   GNUNET_assert (pg != NULL);
800   shutdown_handle =
801       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_get_forever (),
802                                     &shutdown_task, NULL);
803 }
804
805
806
807 /**
808  * nse-profiler command line options
809  */
810 static struct GNUNET_GETOPT_CommandLineOption options[] = {
811   {'V', "verbose", NULL,
812    gettext_noop ("be verbose (print progress information)"),
813    0, &GNUNET_GETOPT_set_one, &verbose},
814   GNUNET_GETOPT_OPTION_END
815 };
816
817
818 int
819 main (int argc, char *argv[])
820 {
821   GNUNET_log_setup ("nse-profiler",
822 #if VERBOSE
823                     "DEBUG",
824 #else
825                     "WARNING",
826 #endif
827                     NULL);
828   GNUNET_PROGRAM_run (argc, argv, "nse-profiler",
829                       gettext_noop
830                       ("Measure quality and performance of the NSE service."),
831                       options, &run, NULL);
832 #if REMOVE_DIR
833   GNUNET_DISK_directory_remove ("/tmp/nse-profiler");
834 #endif
835   return ok;
836 }
837
838 /* end of nse-profiler.c */