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