uncrustify as demanded.
[oweals/gnunet.git] / src / ats-tests / gnunet-solver-eval.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2010-2013 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file ats-tests/ats-testing-experiment.c
22  * @brief ats benchmark: controlled experiment execution
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_ats_plugin.h"
29 #include "gnunet_ats_service.h"
30 #include "ats-testing.h"
31
32
33 /**
34  * Experiments
35  */
36 const char *
37 print_op(enum OperationType op)
38 {
39   switch (op)
40     {
41     case START_SEND:
42       return "START_SEND";
43
44     case STOP_SEND:
45       return "STOP_SEND";
46
47     case START_PREFERENCE:
48       return "START_PREFERENCE";
49
50     case STOP_PREFERENCE:
51       return "STOP_PREFERENCE";
52
53     default:
54       break;
55     }
56   return "";
57 }
58
59
60 static struct Experiment *
61 create_experiment()
62 {
63   struct Experiment *e;
64
65   e = GNUNET_new(struct Experiment);
66   e->name = NULL;
67   e->num_masters = 0;
68   e->num_slaves = 0;
69   e->start = NULL;
70   e->total_duration = GNUNET_TIME_UNIT_ZERO;
71   return e;
72 }
73
74
75 static void
76 free_experiment(struct Experiment *e)
77 {
78   struct Episode *cur;
79   struct Episode *next;
80   struct GNUNET_ATS_TEST_Operation *cur_o;
81   struct GNUNET_ATS_TEST_Operation *next_o;
82
83   next = e->start;
84   for (cur = next; NULL != cur; cur = next)
85     {
86       next = cur->next;
87
88       next_o = cur->head;
89       for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
90         {
91           next_o = cur_o->next;
92           GNUNET_free(cur_o);
93         }
94       GNUNET_free(cur);
95     }
96
97   GNUNET_free_non_null(e->name);
98   GNUNET_free_non_null(e->cfg_file);
99   GNUNET_free(e);
100 }
101
102
103 static int
104 load_episode(struct Experiment *e,
105              struct Episode *cur,
106              struct GNUNET_CONFIGURATION_Handle *cfg)
107 {
108   struct GNUNET_ATS_TEST_Operation *o;
109   char *sec_name;
110   char *op_name;
111   char *op;
112   char *type;
113   char *pref;
114   int op_counter = 0;
115
116   fprintf(stderr, "Parsing episode %u\n", cur->id);
117   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
118
119   while (1)
120     {
121       /* Load operation */
122       GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
123       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
124                                                                  sec_name, op_name, &op))
125         {
126           GNUNET_free(op_name);
127           break;
128         }
129       o = GNUNET_new(struct GNUNET_ATS_TEST_Operation);
130       /* operations = set_rate, start_send, stop_send, set_preference */
131       if (0 == strcmp(op, "start_send"))
132         {
133           o->type = START_SEND;
134         }
135       else if (0 == strcmp(op, "stop_send"))
136         {
137           o->type = STOP_SEND;
138         }
139       else if (0 == strcmp(op, "start_preference"))
140         {
141           o->type = START_PREFERENCE;
142         }
143       else if (0 == strcmp(op, "stop_preference"))
144         {
145           o->type = STOP_PREFERENCE;
146         }
147       else
148         {
149           fprintf(stderr, "Invalid operation %u `%s' in episode %u\n",
150                   op_counter, op, cur->id);
151           GNUNET_free(op);
152           GNUNET_free(op_name);
153           GNUNET_free(sec_name);
154           GNUNET_free(o);
155           return GNUNET_SYSERR;
156         }
157       GNUNET_free(op_name);
158
159       /* Get source */
160       GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
161       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg,
162                                                                  sec_name, op_name, &o->src_id))
163         {
164           fprintf(stderr, "Missing src in operation %u `%s' in episode %u\n",
165                   op_counter, op, cur->id);
166           GNUNET_free(op);
167           GNUNET_free(op_name);
168           GNUNET_free(sec_name);
169           GNUNET_free(o);
170           return GNUNET_SYSERR;
171         }
172       if (o->src_id > (e->num_masters - 1))
173         {
174           fprintf(stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
175                   o->src_id, op_counter, op, cur->id);
176           GNUNET_free(op);
177           GNUNET_free(op_name);
178           GNUNET_free(sec_name);
179           GNUNET_free(o);
180           return GNUNET_SYSERR;
181         }
182       GNUNET_free(op_name);
183
184       /* Get destination */
185       GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
186       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg,
187                                                                  sec_name, op_name, &o->dest_id))
188         {
189           fprintf(stderr, "Missing src in operation %u `%s' in episode %u\n",
190                   op_counter, op, cur->id);
191           GNUNET_free(op);
192           GNUNET_free(op_name);
193           GNUNET_free(sec_name);
194           GNUNET_free(o);
195           return GNUNET_SYSERR;
196         }
197       if (o->dest_id > (e->num_slaves - 1))
198         {
199           fprintf(stderr,
200                   "Invalid destination %llu in operation %u `%s' in episode %u\n",
201                   o->dest_id,
202                   op_counter,
203                   op,
204                   cur->id);
205           GNUNET_free(op);
206           GNUNET_free(op_name);
207           GNUNET_free(sec_name);
208           GNUNET_free(o);
209           return GNUNET_SYSERR;
210         }
211       GNUNET_free(op_name);
212
213       GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
214       if ((GNUNET_SYSERR !=
215            GNUNET_CONFIGURATION_get_value_string(cfg,
216                                                  sec_name,
217                                                  op_name,
218                                                  &type)) &&
219           (STOP_SEND != o->type) &&
220           (STOP_PREFERENCE != o->type))
221         {
222           /* Load arguments for set_rate, start_send, set_preference */
223           if (0 == strcmp(type, "constant"))
224             {
225               o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
226             }
227           else if (0 == strcmp(type, "linear"))
228             {
229               o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
230             }
231           else if (0 == strcmp(type, "sinus"))
232             {
233               o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
234             }
235           else if (0 == strcmp(type, "random"))
236             {
237               o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
238             }
239           else
240             {
241               fprintf(stderr, "Invalid type %u `%s' in episode %u\n",
242                       op_counter, op, cur->id);
243               GNUNET_free(type);
244               GNUNET_free(op);
245               GNUNET_free(op_name);
246               GNUNET_free(sec_name);
247               GNUNET_free(o);
248               return GNUNET_SYSERR;
249             }
250           GNUNET_free(op_name);
251
252           /* Get base rate */
253           GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
254           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg,
255                                                                      sec_name, op_name, &o->base_rate))
256             {
257               fprintf(stderr, "Missing base rate in operation %u `%s' in episode %u\n",
258                       op_counter, op, cur->id);
259               GNUNET_free(type);
260               GNUNET_free(op);
261               GNUNET_free(op_name);
262               GNUNET_free(sec_name);
263               GNUNET_free(o);
264               return GNUNET_SYSERR;
265             }
266           GNUNET_free(op_name);
267
268           /* Get max rate */
269           GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
270           if (GNUNET_SYSERR ==
271               GNUNET_CONFIGURATION_get_value_number(cfg,
272                                                     sec_name,
273                                                     op_name,
274                                                     &o->max_rate))
275             {
276               if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
277                   (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
278                   (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
279                 {
280                   fprintf(stderr, "Missing max rate in operation %u `%s' in episode %u\n",
281                           op_counter, op, cur->id);
282                   GNUNET_free(type);
283                   GNUNET_free(op_name);
284                   GNUNET_free(op);
285                   GNUNET_free(sec_name);
286                   GNUNET_free(o);
287                   return GNUNET_SYSERR;
288                 }
289             }
290           GNUNET_free(op_name);
291
292           /* Get period */
293           GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
294           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
295                                                                    sec_name, op_name, &o->period))
296             {
297               o->period = cur->duration;
298             }
299           GNUNET_free(op_name);
300
301           if (START_PREFERENCE == o->type)
302             {
303               /* Get frequency */
304               GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
305               if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
306                                                                        sec_name, op_name, &o->frequency))
307                 {
308                   fprintf(stderr, "Missing frequency in operation %u `%s' in episode %u\n",
309                           op_counter, op, cur->id);
310                   GNUNET_free(type);
311                   GNUNET_free(op_name);
312                   GNUNET_free(op);
313                   GNUNET_free(sec_name);
314                   GNUNET_free(o);
315                   return GNUNET_SYSERR;
316                 }
317               GNUNET_free(op_name);
318
319               /* Get preference */
320               GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
321               if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
322                                                                          sec_name, op_name, &pref))
323                 {
324                   fprintf(stderr, "Missing preference in operation %u `%s' in episode %u\n",
325                           op_counter, op, cur->id);
326                   GNUNET_free(type);
327                   GNUNET_free(op_name);
328                   GNUNET_free(op);
329                   GNUNET_free(sec_name);
330                   GNUNET_free_non_null(pref);
331                   GNUNET_free(o);
332                   return GNUNET_SYSERR;
333                 }
334
335               if (0 == strcmp(pref, "bandwidth"))
336                 o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
337               else if (0 == strcmp(pref, "latency"))
338                 o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
339               else
340                 {
341                   fprintf(stderr,
342                           "Invalid preference in operation %u `%s' in episode %u\n",
343                           op_counter,
344                           op,
345                           cur->id);
346                   GNUNET_free(type);
347                   GNUNET_free(op_name);
348                   GNUNET_free(op);
349                   GNUNET_free(sec_name);
350                   GNUNET_free_non_null(pref);
351                   GNUNET_free(o);
352                   return GNUNET_SYSERR;
353                 }
354               GNUNET_free(pref);
355               GNUNET_free(op_name);
356             }
357         }
358
359       /* Safety checks */
360       if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
361           (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
362         {
363           if ((o->max_rate - o->base_rate) > o->base_rate)
364             {
365               /* This will cause an underflow */
366               GNUNET_break(0);
367             }
368           fprintf(stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
369         }
370
371       if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
372         fprintf(stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
373                 op_counter, cur->id, print_op(o->type), o->src_id,
374                 o->dest_id, (NULL != type) ? type : "",
375                 o->base_rate, o->max_rate,
376                 GNUNET_STRINGS_relative_time_to_string(o->period, GNUNET_YES));
377       else
378         fprintf(stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
379                 op_counter, cur->id, print_op(o->type), o->src_id, o->dest_id);
380
381       GNUNET_free_non_null(type);
382       GNUNET_free(op);
383
384       GNUNET_CONTAINER_DLL_insert(cur->head, cur->tail, o);
385       op_counter++;
386     }
387   GNUNET_free(sec_name);
388
389   return GNUNET_OK;
390 }
391
392 static int
393 load_episodes(struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
394 {
395   int e_counter = 0;
396   char *sec_name;
397   struct GNUNET_TIME_Relative e_duration;
398   struct Episode *cur;
399   struct Episode *last;
400
401   e_counter = 0;
402   last = NULL;
403   while (1)
404     {
405       GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
406       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
407                                                                sec_name, "duration", &e_duration))
408         {
409           GNUNET_free(sec_name);
410           break;
411         }
412
413       cur = GNUNET_new(struct Episode);
414       cur->duration = e_duration;
415       cur->id = e_counter;
416
417       if (GNUNET_OK != load_episode(e, cur, cfg))
418         {
419           GNUNET_free(sec_name);
420           GNUNET_free(cur);
421           return GNUNET_SYSERR;
422         }
423
424       fprintf(stderr, "Found episode %u with duration %s \n",
425               e_counter,
426               GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
427
428       /* Update experiment */
429       e->num_episodes++;
430       e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
431       /* Put in linked list */
432       if (NULL == last)
433         e->start = cur;
434       else
435         last->next = cur;
436
437       GNUNET_free(sec_name);
438       e_counter++;
439       last = cur;
440     }
441   return e_counter;
442 }
443
444
445 static void
446 timeout_experiment(void *cls)
447 {
448   struct Experiment *e = cls;
449
450   e->experiment_timeout_task = NULL;
451   fprintf(stderr, "Experiment timeout!\n");
452
453   if (NULL != e->episode_timeout_task)
454     {
455       GNUNET_SCHEDULER_cancel(e->episode_timeout_task);
456       e->episode_timeout_task = NULL;
457     }
458
459   e->e_done_cb(e, GNUNET_TIME_absolute_get_duration(e->start_time),
460                GNUNET_SYSERR);
461 }
462
463
464 static void
465 enforce_start_send(struct GNUNET_ATS_TEST_Operation *op)
466 {
467   /*
468      struct BenchmarkPeer *peer;
469      struct BenchmarkPartner *partner;
470
471      peer = GNUNET_ATS_TEST_get_peer (op->src_id);
472      if (NULL == peer)
473      {
474      GNUNET_break (0);
475      return;
476      }
477
478      partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
479      if (NULL == partner)
480      {
481      GNUNET_break (0);
482      return;
483      }
484
485      fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
486
487      if (NULL != partner->tg)
488      {
489      fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
490      GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
491      partner->tg = NULL;
492      }
493
494      partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
495       op->tg_type, op->base_rate, op->max_rate, op->period,
496       GNUNET_TIME_UNIT_FOREVER_REL);
497    */
498 }
499
500 static void
501 enforce_stop_send(struct GNUNET_ATS_TEST_Operation *op)
502 {
503   /*
504      struct BenchmarkPartner *p;
505      p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
506      if (NULL == p)
507      {
508      GNUNET_break (0);
509      return;
510      }
511
512      fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
513
514      if (NULL != p->tg)
515      {
516      fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
517         op->src_id, op->dest_id);
518      GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
519      p->tg = NULL;
520      }
521    */
522 }
523
524
525 static void
526 enforce_start_preference(struct GNUNET_ATS_TEST_Operation *op)
527 {
528   /*
529      struct BenchmarkPeer *peer;
530      struct BenchmarkPartner *partner;
531
532      peer = GNUNET_ATS_TEST_get_peer (op->src_id);
533      if (NULL == peer)
534      {
535      GNUNET_break (0);
536      return;
537      }
538
539      partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
540      if (NULL == partner)
541      {
542      GNUNET_break (0);
543      return;
544      }
545
546      fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
547
548      if (NULL != partner->pg)
549      {
550      fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
551         op->src_id, op->dest_id);
552      GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
553      partner->pg = NULL;
554      }
555
556      partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
557       op->tg_type, op->base_rate, op->max_rate, op->period, op->frequency,
558       op->pref_type);
559    */
560 }
561
562 static void
563 enforce_stop_preference(struct GNUNET_ATS_TEST_Operation *op)
564 {
565   /*
566      struct BenchmarkPartner *p;
567      p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
568      if (NULL == p)
569      {
570      GNUNET_break (0);
571      return;
572      }
573
574      fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
575
576      if (NULL != p->pg)
577      {
578      fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
579         op->src_id, op->dest_id);
580      GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
581      p->pg = NULL;
582      }
583    */
584 }
585
586 static void enforce_episode(struct Episode *ep)
587 {
588   struct GNUNET_ATS_TEST_Operation *cur;
589
590   for (cur = ep->head; NULL != cur; cur = cur->next)
591     {
592       fprintf(stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n",
593               print_op(cur->type), cur->src_id, cur->dest_id, cur->base_rate);
594       switch (cur->type)
595         {
596         case START_SEND:
597           enforce_start_send(cur);
598           break;
599
600         case STOP_SEND:
601           enforce_stop_send(cur);
602           break;
603
604         case START_PREFERENCE:
605           enforce_start_preference(cur);
606           break;
607
608         case STOP_PREFERENCE:
609           enforce_stop_preference(cur);
610           break;
611
612         default:
613           break;
614         }
615     }
616 }
617
618
619 static void
620 timeout_episode(void *cls)
621 {
622   struct Experiment *e = cls;
623
624   e->episode_timeout_task = NULL;
625   if (NULL != e->ep_done_cb)
626     e->ep_done_cb(e->cur);
627
628   /* Scheduling next */
629   e->cur = e->cur->next;
630   if (NULL == e->cur)
631     {
632       /* done */
633       fprintf(stderr, "Last episode done!\n");
634       if (NULL != e->experiment_timeout_task)
635         {
636           GNUNET_SCHEDULER_cancel(e->experiment_timeout_task);
637           e->experiment_timeout_task = NULL;
638         }
639       e->e_done_cb(e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
640       return;
641     }
642
643   fprintf(stderr, "Running episode %u with timeout %s\n",
644           e->cur->id,
645           GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
646   enforce_episode(e->cur);
647
648   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed(e->cur->duration,
649                                                          &timeout_episode, e);
650 }
651
652
653 void
654 GNUNET_ATS_solvers_experimentation_run(struct Experiment *e,
655                                        GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
656                                        GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
657 {
658   fprintf(stderr, "Running experiment `%s'  with timeout %s\n", e->name,
659           GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
660   e->e_done_cb = e_done_cb;
661   e->ep_done_cb = ep_done_cb;
662   e->start_time = GNUNET_TIME_absolute_get();
663
664   /* Start total time out */
665   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed(e->max_duration,
666                                                             &timeout_experiment, e);
667
668   /* Start */
669   e->cur = e->start;
670   fprintf(stderr, "Running episode %u with timeout %s\n",
671           e->cur->id,
672           GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
673   enforce_episode(e->cur);
674   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed(e->cur->duration,
675                                                          &timeout_episode, e);
676 }
677
678
679 struct Experiment *
680 GNUNET_ATS_solvers_experimentation_load(char *filename)
681 {
682   struct Experiment *e;
683   struct GNUNET_CONFIGURATION_Handle *cfg;
684
685   e = NULL;
686
687   cfg = GNUNET_CONFIGURATION_create();
688   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, filename))
689     {
690       fprintf(stderr, "Failed to load `%s'\n", filename);
691       GNUNET_CONFIGURATION_destroy(cfg);
692       return NULL;
693     }
694
695   e = create_experiment();
696
697   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
698                                                              "name", &e->name))
699     {
700       fprintf(stderr, "Invalid %s", "name");
701       free_experiment(e);
702       return NULL;
703     }
704   else
705     fprintf(stderr, "Experiment name: `%s'\n", e->name);
706
707   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename(cfg, "experiment",
708                                                                "cfg_file", &e->cfg_file))
709     {
710       fprintf(stderr, "Invalid %s", "cfg_file");
711       free_experiment(e);
712       return NULL;
713     }
714   else
715     fprintf(stderr, "Experiment name: `%s'\n", e->cfg_file);
716
717   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
718                                                              "masters", &e->num_masters))
719     {
720       fprintf(stderr, "Invalid %s", "masters");
721       free_experiment(e);
722       return NULL;
723     }
724   else
725     fprintf(stderr, "Experiment masters: `%llu'\n",
726             e->num_masters);
727
728   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
729                                                              "slaves", &e->num_slaves))
730     {
731       fprintf(stderr, "Invalid %s", "slaves");
732       free_experiment(e);
733       return NULL;
734     }
735   else
736     fprintf(stderr, "Experiment slaves: `%llu'\n",
737             e->num_slaves);
738
739   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
740                                                            "log_freq", &e->log_freq))
741     {
742       fprintf(stderr, "Invalid %s", "log_freq");
743       free_experiment(e);
744       return NULL;
745     }
746   else
747     fprintf(stderr, "Experiment logging frequency: `%s'\n",
748             GNUNET_STRINGS_relative_time_to_string(e->log_freq, GNUNET_YES));
749
750   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
751                                                            "max_duration", &e->max_duration))
752     {
753       fprintf(stderr, "Invalid %s", "max_duration");
754       free_experiment(e);
755       return NULL;
756     }
757   else
758     fprintf(stderr, "Experiment duration: `%s'\n",
759             GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
760
761   load_episodes(e, cfg);
762   fprintf(stderr, "Loaded %u episodes with total duration %s\n",
763           e->num_episodes,
764           GNUNET_STRINGS_relative_time_to_string(e->total_duration, GNUNET_YES));
765
766   GNUNET_CONFIGURATION_destroy(cfg);
767   return e;
768 }
769
770 void
771 GNUNET_ATS_solvers_experimentation_stop(struct Experiment *e)
772 {
773   if (NULL != e->experiment_timeout_task)
774     {
775       GNUNET_SCHEDULER_cancel(e->experiment_timeout_task);
776       e->experiment_timeout_task = NULL;
777     }
778   if (NULL != e->episode_timeout_task)
779     {
780       GNUNET_SCHEDULER_cancel(e->episode_timeout_task);
781       e->episode_timeout_task = NULL;
782     }
783   free_experiment(e);
784 }
785
786 /**
787  * Solver
788  */
789
790 struct GNUNET_ATS_TESTING_SolverHandle {
791   char * plugin;
792   struct GNUNET_ATS_PluginEnvironment env;
793   void *solver;
794 };
795
796 enum GNUNET_ATS_Solvers {
797   GNUNET_ATS_SOLVER_PROPORTIONAL,
798   GNUNET_ATS_SOLVER_MLP,
799   GNUNET_ATS_SOLVER_RIL,
800 };
801
802 void
803 GNUNET_ATS_solvers_solver_stop(struct GNUNET_ATS_TESTING_SolverHandle *sh)
804 {
805   GNUNET_PLUGIN_unload(sh->plugin, sh->solver);
806   GNUNET_free(sh->plugin);
807   GNUNET_free(sh);
808 }
809
810 struct GNUNET_ATS_TESTING_SolverHandle *
811 GNUNET_ATS_solvers_solver_start(enum GNUNET_ATS_Solvers type)
812 {
813   struct GNUNET_ATS_TESTING_SolverHandle *sh;
814   char * solver_str;
815
816   switch (type)
817     {
818     case GNUNET_ATS_SOLVER_PROPORTIONAL:
819       solver_str = "proportional";
820       break;
821
822     case GNUNET_ATS_SOLVER_MLP:
823       solver_str = "mlp";
824       break;
825
826     case GNUNET_ATS_SOLVER_RIL:
827       solver_str = "ril";
828       break;
829
830     default:
831       GNUNET_break(0);
832       return NULL;
833       break;
834     }
835
836   sh = GNUNET_new(struct GNUNET_ATS_TESTING_SolverHandle);
837   GNUNET_asprintf(&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
838   //sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
839   if (NULL == sh->solver)
840     {
841       fprintf(stderr, "Failed to load solver `%s'\n", sh->plugin);
842       exit(1);
843     }
844
845   return sh;
846 }
847
848 static struct Experiment *e;
849
850 static struct GNUNET_ATS_TESTING_SolverHandle *sh;
851
852 /**
853  * cmd option -e: experiment file
854  */
855 static char *opt_exp_file;
856
857 static char *opt_solver;
858
859 /**
860  * cmd option -l: enable logging
861  */
862 static int opt_log;
863
864 /**
865  * cmd option -p: enable plots
866  */
867 static int opt_plot;
868
869 /**
870  * cmd option -v: verbose logs
871  */
872 static int opt_verbose;
873
874 static void
875 run(void *cls, char * const *args, const char *cfgfile,
876     const struct GNUNET_CONFIGURATION_Handle *cfg)
877 {
878   enum GNUNET_ATS_Solvers solver;
879
880   if (NULL == opt_exp_file)
881     {
882       fprintf(stderr, "No experiment given ...\n");
883       exit(1);
884     }
885
886   if (NULL == opt_solver)
887     {
888       fprintf(stderr, "No solver given ...\n");
889       exit(1);
890     }
891
892   if (0 == strcmp(opt_solver, "mlp"))
893     {
894       solver = GNUNET_ATS_SOLVER_MLP;
895     }
896   else if (0 == strcmp(opt_solver, "proportional"))
897     {
898       solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
899     }
900   else if (0 == strcmp(opt_solver, "ril"))
901     {
902       solver = GNUNET_ATS_SOLVER_RIL;
903     }
904   else
905     {
906       fprintf(stderr, "No solver given ...");
907       return;
908     }
909
910   /* load experiment */
911   e = GNUNET_ATS_solvers_experimentation_load(opt_exp_file);
912   if (NULL == e)
913     {
914       fprintf(stderr, "Failed to load experiment ...\n");
915       return;
916     }
917
918   /* load solver */
919   sh = GNUNET_ATS_solvers_solver_start(solver);
920   if (NULL == sh)
921     {
922       fprintf(stderr, "Failed to start solver ...\n");
923       return;
924     }
925
926   /* start logging */
927
928   /* run experiment */
929
930   /* WAIT */
931 }
932
933
934 /**
935  * Main function of the benchmark
936  *
937  * @param argc argument count
938  * @param argv argument values
939  */
940 int
941 main(int argc, char *argv[])
942 {
943   opt_exp_file = NULL;
944   opt_solver = NULL;
945   opt_log = GNUNET_NO;
946   opt_plot = GNUNET_NO;
947
948   struct GNUNET_GETOPT_CommandLineOption options[] =
949   {
950     GNUNET_GETOPT_option_string('s',
951                                 "solver",
952                                 NULL,
953                                 gettext_noop("solver to use"),
954                                 &opt_solver),
955
956     GNUNET_GETOPT_option_string('e',
957                                 "experiment",
958                                 NULL,
959                                 gettext_noop("experiment to use"),
960                                 &opt_exp_file),
961
962     GNUNET_GETOPT_option_flag('e',
963                               "experiment",
964                               gettext_noop("experiment to use"),
965                               &opt_verbose),
966     GNUNET_GETOPT_OPTION_END
967   };
968
969   if (GNUNET_OK !=
970       GNUNET_PROGRAM_run(argc,
971                          argv, argv[0],
972                          NULL,
973                          options,
974                          &run, argv[0]))
975     return 1;
976
977   return 0;
978 }
979 /* end of file gnunet-solver-eval.c*/