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