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