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