Added documenting comments
[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 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 static void
422 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
423 {
424   struct Experiment *e = cls;
425   e->experiment_timeout_task = NULL;
426   fprintf (stderr, "Experiment timeout!\n");
427
428   if (NULL != e->episode_timeout_task)
429   {
430     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
431     e->episode_timeout_task = NULL;
432   }
433
434   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
435       GNUNET_SYSERR);
436 }
437
438 static void
439 enforce_start_send (struct GNUNET_ATS_TEST_Operation *op)
440 {
441   /*
442   struct BenchmarkPeer *peer;
443   struct BenchmarkPartner *partner;
444
445   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
446   if (NULL == peer)
447   {
448     GNUNET_break (0);
449     return;
450   }
451
452   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
453   if (NULL == partner)
454   {
455     GNUNET_break (0);
456     return;
457   }
458
459   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
460
461   if (NULL != partner->tg)
462   {
463     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
464     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
465     partner->tg = NULL;
466   }
467
468   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
469       op->tg_type, op->base_rate, op->max_rate, op->period,
470       GNUNET_TIME_UNIT_FOREVER_REL);
471    */
472 }
473
474 static void
475 enforce_stop_send (struct GNUNET_ATS_TEST_Operation *op)
476 {
477   /*
478   struct BenchmarkPartner *p;
479   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
480   if (NULL == p)
481   {
482     GNUNET_break (0);
483     return;
484   }
485
486   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
487
488   if (NULL != p->tg)
489   {
490     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
491         op->src_id, op->dest_id);
492     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
493     p->tg = NULL;
494   }
495   */
496 }
497
498
499 static void
500 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
501 {
502   /*
503   struct BenchmarkPeer *peer;
504   struct BenchmarkPartner *partner;
505
506   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
507   if (NULL == peer)
508   {
509     GNUNET_break (0);
510     return;
511   }
512
513   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
514   if (NULL == partner)
515   {
516     GNUNET_break (0);
517     return;
518   }
519
520   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
521
522   if (NULL != partner->pg)
523   {
524     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
525         op->src_id, op->dest_id);
526     GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
527     partner->pg = NULL;
528   }
529
530   partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
531       op->tg_type, op->base_rate, op->max_rate, op->period, op->frequency,
532       op->pref_type);
533       */
534 }
535
536 static void
537 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
538 {
539   /*
540   struct BenchmarkPartner *p;
541   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
542   if (NULL == p)
543   {
544     GNUNET_break (0);
545     return;
546   }
547
548   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
549
550   if (NULL != p->pg)
551   {
552     fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
553         op->src_id, op->dest_id);
554     GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
555     p->pg = NULL;
556   }
557   */
558 }
559
560 static void enforce_episode (struct Episode *ep)
561 {
562   struct GNUNET_ATS_TEST_Operation *cur;
563   for (cur = ep->head; NULL != cur; cur = cur->next)
564   {
565
566     fprintf (stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n",
567         print_op (cur->type), cur->src_id, cur->dest_id, cur->base_rate);
568     switch (cur->type) {
569       case START_SEND:
570         enforce_start_send (cur);
571         break;
572       case STOP_SEND:
573         enforce_stop_send (cur);
574         break;
575       case START_PREFERENCE:
576         enforce_start_preference (cur);
577         break;
578       case STOP_PREFERENCE:
579         enforce_stop_preference (cur);
580         break;
581       default:
582         break;
583     }
584   }
585 }
586
587 static void
588 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
589 {
590   struct Experiment *e = cls;
591   e->episode_timeout_task = NULL;
592   if (NULL != e->ep_done_cb)
593     e->ep_done_cb (e->cur);
594
595   /* Scheduling next */
596   e->cur = e->cur->next;
597   if (NULL == e->cur)
598   {
599     /* done */
600     fprintf (stderr, "Last episode done!\n");
601     if (NULL != e->experiment_timeout_task)
602     {
603       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
604       e->experiment_timeout_task = NULL;
605     }
606     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
607     return;
608   }
609
610   fprintf (stderr, "Running episode %u with timeout %s\n",
611       e->cur->id,
612       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
613   enforce_episode(e->cur);
614
615   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
616       &timeout_episode, e);
617 }
618
619
620 void
621 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
622     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
623     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
624 {
625   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
626       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
627   e->e_done_cb = e_done_cb;
628   e->ep_done_cb = ep_done_cb;
629   e->start_time = GNUNET_TIME_absolute_get();
630
631   /* Start total time out */
632   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
633       &timeout_experiment, e);
634
635   /* Start */
636   e->cur = e->start;
637   fprintf (stderr, "Running episode %u with timeout %s\n",
638       e->cur->id,
639       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
640   enforce_episode(e->cur);
641   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
642       &timeout_episode, e);
643
644
645 }
646
647
648 struct Experiment *
649 GNUNET_ATS_solvers_experimentation_load (char *filename)
650 {
651   struct Experiment *e;
652   struct GNUNET_CONFIGURATION_Handle *cfg;
653   e = NULL;
654
655   cfg = GNUNET_CONFIGURATION_create();
656   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
657   {
658     fprintf (stderr, "Failed to load `%s'\n", filename);
659     GNUNET_CONFIGURATION_destroy (cfg);
660     return NULL;
661   }
662
663   e = create_experiment ();
664
665   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
666       "name", &e->name))
667   {
668     fprintf (stderr, "Invalid %s", "name");
669     free_experiment (e);
670     return NULL;
671   }
672   else
673     fprintf (stderr, "Experiment name: `%s'\n", e->name);
674
675   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
676       "cfg_file", &e->cfg_file))
677   {
678     fprintf (stderr, "Invalid %s", "cfg_file");
679     free_experiment (e);
680     return NULL;
681   }
682   else
683     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
684
685   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
686       "masters", &e->num_masters))
687   {
688     fprintf (stderr, "Invalid %s", "masters");
689     free_experiment (e);
690     return NULL;
691   }
692   else
693     fprintf (stderr, "Experiment masters: `%llu'\n",
694         e->num_masters);
695
696   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
697       "slaves", &e->num_slaves))
698   {
699     fprintf (stderr, "Invalid %s", "slaves");
700     free_experiment (e);
701     return NULL;
702   }
703   else
704     fprintf (stderr, "Experiment slaves: `%llu'\n",
705         e->num_slaves);
706
707   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
708       "log_freq", &e->log_freq))
709   {
710     fprintf (stderr, "Invalid %s", "log_freq");
711     free_experiment (e);
712     return NULL;
713   }
714   else
715     fprintf (stderr, "Experiment logging frequency: `%s'\n",
716         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
717
718   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
719       "max_duration", &e->max_duration))
720   {
721     fprintf (stderr, "Invalid %s", "max_duration");
722     free_experiment (e);
723     return NULL;
724   }
725   else
726     fprintf (stderr, "Experiment duration: `%s'\n",
727         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
728
729   load_episodes (e, cfg);
730   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
731       e->num_episodes,
732       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
733
734   GNUNET_CONFIGURATION_destroy (cfg);
735   return e;
736 }
737
738 void
739 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
740 {
741   if (NULL != e->experiment_timeout_task)
742   {
743     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
744     e->experiment_timeout_task = NULL;
745   }
746   if (NULL != e->episode_timeout_task)
747   {
748     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
749     e->episode_timeout_task = NULL;
750   }
751   free_experiment (e);
752 }
753
754 /**
755  * Solver
756  */
757
758 struct GNUNET_ATS_TESTING_SolverHandle
759 {
760   char * plugin;
761   struct GNUNET_ATS_PluginEnvironment env;
762   void *solver;
763 };
764
765 enum GNUNET_ATS_Solvers
766 {
767   GNUNET_ATS_SOLVER_PROPORTIONAL,
768   GNUNET_ATS_SOLVER_MLP,
769   GNUNET_ATS_SOLVER_RIL,
770 };
771
772 void
773 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
774 {
775  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
776  GNUNET_free (sh->plugin);
777  GNUNET_free (sh);
778 }
779
780 struct GNUNET_ATS_TESTING_SolverHandle *
781 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
782 {
783   struct GNUNET_ATS_TESTING_SolverHandle *sh;
784   char * solver_str;
785
786   switch (type) {
787     case GNUNET_ATS_SOLVER_PROPORTIONAL:
788       solver_str = "proportional";
789       break;
790     case GNUNET_ATS_SOLVER_MLP:
791       solver_str = "mlp";
792       break;
793     case GNUNET_ATS_SOLVER_RIL:
794       solver_str = "ril";
795       break;
796     default:
797       GNUNET_break (0);
798       return NULL;
799       break;
800   }
801
802   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
803   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
804   //sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
805   if (NULL == sh->solver)
806   {
807     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
808     exit (1);
809   }
810
811   return sh;
812 }
813
814 static struct Experiment *e;
815
816 static struct GNUNET_ATS_TESTING_SolverHandle *sh;
817
818 /**
819  * cmd option -e: experiment file
820  */
821 static char *opt_exp_file;
822
823 static char *opt_solver;
824
825 /**
826  * cmd option -l: enable logging
827  */
828 static int opt_log;
829
830 /**
831  * cmd option -p: enable plots
832  */
833 static int opt_plot;
834
835 /**
836  * cmd option -v: verbose logs
837  */
838 static int opt_verbose;
839
840 static void
841 run (void *cls, char * const *args, const char *cfgfile,
842     const struct GNUNET_CONFIGURATION_Handle *cfg)
843 {
844   enum GNUNET_ATS_Solvers solver;
845
846   if (NULL == opt_exp_file)
847   {
848     fprintf (stderr, "No experiment given ...\n");
849     exit (1);
850   }
851
852   if (NULL == opt_solver)
853   {
854     fprintf (stderr, "No solver given ...\n");
855     exit (1);
856   }
857
858   if (0 == strcmp(opt_solver, "mlp"))
859   {
860     solver = GNUNET_ATS_SOLVER_MLP;
861   }
862   else if (0 == strcmp(opt_solver, "proportional"))
863   {
864     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
865   }
866   else if (0 == strcmp(opt_solver, "ril"))
867   {
868     solver = GNUNET_ATS_SOLVER_RIL;
869   }
870   else
871   {
872     fprintf (stderr, "No solver given ...");
873     return;
874   }
875
876   /* load experiment */
877   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
878   if (NULL == e)
879   {
880     fprintf (stderr, "Failed to load experiment ...\n");
881     return;
882   }
883
884   /* load solver */
885   sh = GNUNET_ATS_solvers_solver_start (solver);
886   if (NULL == sh)
887   {
888     fprintf (stderr, "Failed to start solver ...\n");
889     return;
890   }
891
892   /* start logging */
893
894   /* run experiment */
895
896   /* WAIT */
897 }
898
899
900 /**
901  * Main function of the benchmark
902  *
903  * @param argc argument count
904  * @param argv argument values
905  */
906 int
907 main (int argc, char *argv[])
908 {
909
910   opt_exp_file = NULL;
911   opt_solver = NULL;
912   opt_log = GNUNET_NO;
913   opt_plot = GNUNET_NO;
914
915   static struct GNUNET_GETOPT_CommandLineOption options[] =
916   {
917     { 's', "solver", NULL,
918         gettext_noop ("solver to use"),
919         1, &GNUNET_GETOPT_set_string, &opt_solver},
920     {  'e', "experiment", NULL,
921       gettext_noop ("experiment to use"),
922       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
923     {  'e', "experiment", NULL,
924       gettext_noop ("experiment to use"),
925       1, &GNUNET_GETOPT_set_one, &opt_verbose},
926     GNUNET_GETOPT_OPTION_END
927   };
928
929   GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
930
931   return 0;
932 }
933 /* end of file ats-testing-experiment.c*/
934