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