logging task
[oweals/gnunet.git] / src / ats / gnunet-ats-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-solver-eval.h"
29
30
31 #define BIG_M_STRING "unlimited"
32
33 static struct Experiment *e;
34
35 static struct LoggingHandle *l;
36
37 static struct GNUNET_ATS_TESTING_SolverHandle *sh;
38
39 /**
40  * cmd option -e: experiment file
41  */
42 static char *opt_exp_file;
43
44 static char *opt_solver;
45
46 /**
47  * cmd option -l: enable logging
48  */
49 static int opt_log;
50
51 /**
52  * cmd option -p: enable plots
53  */
54 static int opt_plot;
55
56 /**
57  * cmd option -v: verbose logs
58  */
59 static int opt_verbose;
60
61 static int res;
62
63 static void
64 end_now ();
65
66 static char *
67 print_generator_type (enum GeneratorType g)
68 {
69   switch (g) {
70     case GNUNET_ATS_TEST_TG_CONSTANT:
71       return "CONSTANT";
72     case GNUNET_ATS_TEST_TG_LINEAR:
73       return "LINEAR";
74     case GNUNET_ATS_TEST_TG_RANDOM:
75       return "RANDOM";
76     case GNUNET_ATS_TEST_TG_SINUS:
77       return "SINUS";
78     default:
79       return "INVALID";
80       break;
81   }
82 }
83
84 /**
85  * Logging
86  */
87
88 static void
89 logging_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
90 {
91   struct LoggingHandle *l = cls;
92
93   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
94
95   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging\n");
96
97   l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq, &logging_task, l);
98
99 }
100
101 struct LoggingHandle *
102 GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
103 {
104   struct LoggingHandle *l;
105   l = GNUNET_new (struct LoggingHandle);
106
107   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every  %s\n",
108       GNUNET_STRINGS_relative_time_to_string(freq, GNUNET_NO));
109
110   /* Iterate over peers */
111
112   l->log_freq = freq;
113   l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
114
115   return l;
116 }
117
118 void
119 GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
120 {
121   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging\n");
122 }
123
124 void
125 GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
126 {
127   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
128     GNUNET_SCHEDULER_cancel (l->logging_task);
129
130   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
131
132   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
133 }
134
135 void
136 GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
137 {
138
139 }
140
141 void
142 GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
143 {
144   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
145     GNUNET_SCHEDULER_cancel (l->logging_task);
146   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
147   GNUNET_free (l);
148 }
149
150 /**
151  * Property Generators
152  */
153
154 static struct PropertyGenerator *prop_gen_head;
155 static struct PropertyGenerator *prop_gen_tail;
156
157 static double
158 get_property (struct PropertyGenerator *pg)
159 {
160   struct GNUNET_TIME_Relative time_delta;
161   double delta_value;
162   double pref_value;
163
164   /* Calculate the current preference value */
165   switch (pg->type) {
166     case GNUNET_ATS_TEST_TG_CONSTANT:
167       pref_value = pg->base_value;
168       break;
169     case GNUNET_ATS_TEST_TG_LINEAR:
170       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
171       /* Calculate point of time in the current period */
172       time_delta.rel_value_us = time_delta.rel_value_us %
173           pg->duration_period.rel_value_us;
174       delta_value = ((double) time_delta.rel_value_us  /
175           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
176       if ((pg->max_value < pg->base_value) &&
177           ((pg->max_value - pg->base_value) > pg->base_value))
178       {
179         /* This will cause an underflow */
180         GNUNET_break (0);
181       }
182       pref_value = pg->base_value + delta_value;
183       break;
184     case GNUNET_ATS_TEST_TG_RANDOM:
185       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
186           10000 * (pg->max_value - pg->base_value)) / 10000;
187       pref_value = pg->base_value + delta_value;
188       break;
189     case GNUNET_ATS_TEST_TG_SINUS:
190       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
191       /* Calculate point of time in the current period */
192       time_delta.rel_value_us = time_delta.rel_value_us %
193           pg->duration_period.rel_value_us;
194       if ((pg->max_value - pg->base_value) > pg->base_value)
195       {
196         /* This will cause an underflow for second half of sinus period,
197          * will be detected in general when experiments are loaded */
198         GNUNET_break (0);
199       }
200       delta_value = (pg->max_value - pg->base_value) *
201           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
202               time_delta.rel_value_us);
203       pref_value = pg->base_value + delta_value;
204       break;
205     default:
206       pref_value = 0.0;
207       break;
208   }
209   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
210       pref_value);
211   return pref_value;
212 }
213
214
215 static void
216 set_prop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
217 {
218   struct PropertyGenerator *pg = cls;
219   double pref_value;
220   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
221
222   pref_value = get_property (pg);
223
224   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
225       "Setting property for peer [%u] address [%u] for %s to %f\n",
226       pg->peer, pg->address_id,
227       GNUNET_ATS_print_property_type (pg->ats_property), pref_value);
228
229   /* set performance here!
230   GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle,
231       &p->dest->id, p->pg->kind, pref_value, GNUNET_ATS_PREFERENCE_END);
232 */
233
234   switch (pg->ats_property) {
235     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
236       //p->pref_bandwidth = pref_value;
237       break;
238     case GNUNET_ATS_PREFERENCE_LATENCY:
239       //p->pref_delay = pref_value;
240       break;
241     default:
242       break;
243   }
244
245   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
246       &set_prop_task, pg);
247
248 }
249
250 static struct PropertyGenerator *
251 find_prop_gen (unsigned int peer, unsigned int address,
252     uint32_t ats_property)
253 {
254   struct PropertyGenerator *cur;
255   for (cur = prop_gen_head; NULL != cur; cur = cur->next)
256     if ((cur->peer == peer) && (cur->address_id == address) &&
257         (cur->ats_property == ats_property))
258       return cur;
259   return NULL;
260 }
261
262 void
263 GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
264 {
265   GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
266
267   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
268   {
269     GNUNET_SCHEDULER_cancel (pg->set_task);
270     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
271   }
272   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
273       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
274       pg->peer, pg->address_id,
275       GNUNET_ATS_print_property_type(pg->ats_property));
276
277   GNUNET_free (pg);
278 }
279
280
281 /**
282  * Generate between the source master and the partner and set preferences with a
283  * value depending on the generator.
284  *
285  * @param src source
286  * @param dest partner
287  * @param type type of preferences to generate
288  * @param base_rate traffic base rate to send data with
289  * @param max_rate  traffic maximum rate to send data with
290  * @param period duration of a period of traffic generation (~ 1/frequency)
291  * @param duration how long to generate traffic
292  * @return the traffic generator
293  */
294 struct PropertyGenerator *
295 GNUNET_ATS_solver_generate_property_start (unsigned int peer,
296     unsigned int address_id,
297     enum GeneratorType type,
298     long int base_value,
299     long int value_rate,
300     struct GNUNET_TIME_Relative period,
301     struct GNUNET_TIME_Relative frequency,
302     uint32_t ats_property)
303 {
304   struct PropertyGenerator *pg;
305
306   pg = GNUNET_new (struct PropertyGenerator);
307   GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
308   pg->type = type;
309   pg->peer = peer;
310   pg->address_id = address_id;
311   pg->ats_property = ats_property;
312   pg->base_value = base_value;
313   pg->max_value = value_rate;
314   pg->duration_period = period;
315   pg->frequency = frequency;
316   pg->time_start = GNUNET_TIME_absolute_get();
317
318   switch (type) {
319     case GNUNET_ATS_TEST_TG_CONSTANT:
320       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
321           "Setting up constant property generator peer [%u] address [%u] `%s' max %u Bips\n",
322           pg->peer, pg->address_id,  GNUNET_ATS_print_property_type (ats_property),
323           base_value);
324       break;
325     case GNUNET_ATS_TEST_TG_LINEAR:
326       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
327           "Setting up linear property generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n",
328           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
329           base_value, value_rate);
330       break;
331     case GNUNET_ATS_TEST_TG_SINUS:
332       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
333           "Setting up sinus property generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
334           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
335           base_value, value_rate);
336
337       break;
338     case GNUNET_ATS_TEST_TG_RANDOM:
339       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
340           "Setting up random property generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n",
341           pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property),
342           base_value, value_rate);
343       break;
344     default:
345       break;
346   }
347
348   pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
349   return pg;
350 }
351
352
353
354 /**
355  * Stop all preferences generators
356  */
357 void
358 GNUNET_ATS_solver_generate_property_stop_all ()
359 {
360   struct PropertyGenerator *cur;
361   struct PropertyGenerator *next;
362   next = prop_gen_head;
363   for (cur = next; NULL != cur; cur = next)
364   {
365       next = cur->next;
366       GNUNET_ATS_solver_generate_property_stop (cur);
367   }
368 }
369
370
371 /**
372  * Preference Generators
373  */
374
375 static struct PreferenceGenerator *pref_gen_head;
376 static struct PreferenceGenerator *pref_gen_tail;
377
378 static double
379 get_preference (struct PreferenceGenerator *pg)
380 {
381   struct GNUNET_TIME_Relative time_delta;
382   double delta_value;
383   double pref_value;
384
385   /* Calculate the current preference value */
386   switch (pg->type) {
387     case GNUNET_ATS_TEST_TG_CONSTANT:
388       pref_value = pg->base_value;
389       break;
390     case GNUNET_ATS_TEST_TG_LINEAR:
391       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
392       /* Calculate point of time in the current period */
393       time_delta.rel_value_us = time_delta.rel_value_us %
394           pg->duration_period.rel_value_us;
395       delta_value = ((double) time_delta.rel_value_us  /
396           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
397       if ((pg->max_value < pg->base_value) &&
398           ((pg->max_value - pg->base_value) > pg->base_value))
399       {
400         /* This will cause an underflow */
401         GNUNET_break (0);
402       }
403       pref_value = pg->base_value + delta_value;
404       break;
405     case GNUNET_ATS_TEST_TG_RANDOM:
406       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
407           10000 * (pg->max_value - pg->base_value)) / 10000;
408       pref_value = pg->base_value + delta_value;
409       break;
410     case GNUNET_ATS_TEST_TG_SINUS:
411       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
412       /* Calculate point of time in the current period */
413       time_delta.rel_value_us = time_delta.rel_value_us %
414           pg->duration_period.rel_value_us;
415       if ((pg->max_value - pg->base_value) > pg->base_value)
416       {
417         /* This will cause an underflow for second half of sinus period,
418          * will be detected in general when experiments are loaded */
419         GNUNET_break (0);
420       }
421       delta_value = (pg->max_value - pg->base_value) *
422           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
423               time_delta.rel_value_us);
424       pref_value = pg->base_value + delta_value;
425       break;
426     default:
427       pref_value = 0.0;
428       break;
429   }
430   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
431       pref_value);
432   return pref_value;
433 }
434
435
436 static void
437 set_pref_task (void *cls,
438                     const struct GNUNET_SCHEDULER_TaskContext *tc)
439 {
440   struct PreferenceGenerator *pg = cls;
441   double pref_value;
442   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
443
444   pref_value = get_preference (pg);
445
446   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
447       "Setting preference for peer [%u] address [%u] for %s to %f\n",
448       pg->peer, pg->address_id,
449       GNUNET_ATS_print_preference_type (pg->kind), pref_value);
450
451   /* set performance here!
452   GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle,
453       &p->dest->id, p->pg->kind, pref_value, GNUNET_ATS_PREFERENCE_END);
454 */
455
456   switch (pg->kind) {
457     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
458       //p->pref_bandwidth = pref_value;
459       break;
460     case GNUNET_ATS_PREFERENCE_LATENCY:
461       //p->pref_delay = pref_value;
462       break;
463     default:
464       break;
465   }
466
467   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
468       set_pref_task, pg);
469
470 }
471
472 static struct PreferenceGenerator *
473 find_pref_gen (unsigned int peer, unsigned int address,
474     enum GNUNET_ATS_PreferenceKind kind)
475 {
476   struct PreferenceGenerator *cur;
477   for (cur = pref_gen_head; NULL != cur; cur = cur->next)
478     if ((cur->peer == peer) && (cur->address_id == address) && (cur->kind == kind))
479       return cur;
480   return NULL;
481 }
482
483 void
484 GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
485 {
486   GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
487
488   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
489   {
490     GNUNET_SCHEDULER_cancel (pg->set_task);
491     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
492   }
493   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
494       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
495       pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(pg->kind));
496
497   GNUNET_free (pg);
498 }
499
500
501 /**
502  * Generate between the source master and the partner and set preferences with a
503  * value depending on the generator.
504  *
505  * @param src source
506  * @param dest partner
507  * @param type type of preferences to generate
508  * @param base_rate traffic base rate to send data with
509  * @param max_rate  traffic maximum rate to send data with
510  * @param period duration of a period of traffic generation (~ 1/frequency)
511  * @param duration how long to generate traffic
512  * @return the traffic generator
513  */
514 struct PreferenceGenerator *
515 GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
516     unsigned int address_id,
517     enum GeneratorType type,
518     long int base_value,
519     long int value_rate,
520     struct GNUNET_TIME_Relative period,
521     struct GNUNET_TIME_Relative frequency,
522     enum GNUNET_ATS_PreferenceKind kind)
523 {
524   struct PreferenceGenerator *pg;
525
526   pg = GNUNET_new (struct PreferenceGenerator);
527   GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
528   pg->type = type;
529   pg->peer = peer;
530   pg->address_id = address_id;
531   pg->kind = kind;
532   pg->base_value = base_value;
533   pg->max_value = value_rate;
534   pg->duration_period = period;
535   pg->frequency = frequency;
536   pg->time_start = GNUNET_TIME_absolute_get();
537
538   switch (type) {
539     case GNUNET_ATS_TEST_TG_CONSTANT:
540       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
541           "Setting up %s preference generator peer [%u] address [%u] `%s' max %u Bips\n",
542           print_generator_type (type), pg->peer, pg->address_id,
543           GNUNET_ATS_print_preference_type(kind),
544           base_value);
545       break;
546     case GNUNET_ATS_TEST_TG_LINEAR:
547       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
548           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n",
549           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
550           base_value, value_rate);
551       break;
552     case GNUNET_ATS_TEST_TG_SINUS:
553       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
554           "Setting up %s preference generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
555           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
556           base_value, value_rate);
557       break;
558     case GNUNET_ATS_TEST_TG_RANDOM:
559       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n",
561           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
562           base_value, value_rate);
563       break;
564     default:
565       break;
566   }
567
568   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
569   return pg;
570 }
571
572
573
574 /**
575  * Stop all preferences generators
576  */
577 void
578 GNUNET_ATS_solver_generate_preferences_stop_all ()
579 {
580   struct PreferenceGenerator *cur;
581   struct PreferenceGenerator *next;
582   next = pref_gen_head;
583   for (cur = next; NULL != cur; cur = next)
584   {
585       next = cur->next;
586       GNUNET_ATS_solver_generate_preferences_stop(cur);
587   }
588 }
589
590
591
592 /**
593  * Experiments
594  */
595
596 const char *
597 print_op (enum OperationType op)
598 {
599   switch (op) {
600     case SOLVER_OP_ADD_ADDRESS:
601       return "ADD_ADDRESS";
602     case SOLVER_OP_DEL_ADDRESS:
603       return "DEL_ADDRESS";
604     case SOLVER_OP_START_SET_PREFERENCE:
605       return "START_SET_PREFERENCE";
606     case SOLVER_OP_STOP_SET_PREFERENCE:
607       return "STOP_STOP_PREFERENCE";
608     case SOLVER_OP_START_SET_PROPERTY:
609           return "START_SET_PROPERTY";
610     case SOLVER_OP_STOP_SET_PROPERTY:
611       return "STOP_SET_PROPERTY";
612     default:
613       break;
614   }
615   return "";
616 }
617
618 static struct Experiment *
619 create_experiment ()
620 {
621   struct Experiment *e;
622   e = GNUNET_new (struct Experiment);
623   e->name = NULL;
624   e->num_masters = 0;
625   e->num_slaves = 0;
626   e->start = NULL;
627   e->total_duration = GNUNET_TIME_UNIT_ZERO;
628   return e;
629 }
630
631 static void
632 free_experiment (struct Experiment *e)
633 {
634   struct Episode *cur;
635   struct Episode *next;
636   struct GNUNET_ATS_TEST_Operation *cur_o;
637   struct GNUNET_ATS_TEST_Operation *next_o;
638
639   next = e->start;
640   for (cur = next; NULL != cur; cur = next)
641   {
642     next = cur->next;
643
644     next_o = cur->head;
645     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
646     {
647       next_o = cur_o->next;
648       GNUNET_free_non_null (cur_o->address);
649       GNUNET_free_non_null (cur_o->plugin);
650       GNUNET_free (cur_o);
651     }
652     GNUNET_free (cur);
653   }
654
655   GNUNET_free_non_null (e->name);
656   GNUNET_free_non_null (e->cfg_file);
657   GNUNET_free (e);
658 }
659
660
661 static int
662 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
663     struct Episode *e,
664     int op_counter,
665     char *sec_name,
666     const struct GNUNET_CONFIGURATION_Handle *cfg)
667 {
668   char *op_name;
669
670   /* peer id */
671   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
672   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
673       sec_name, op_name, &o->peer_id))
674   {
675     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
676         op_counter, "ADD_ADDRESS", op_name);
677     GNUNET_free (op_name);
678     return GNUNET_SYSERR;
679   }
680   GNUNET_free (op_name);
681
682   /* address id */
683   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
684   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
685       sec_name, op_name, &o->address_id))
686   {
687     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
688         op_counter, "ADD_ADDRESS", op_name);
689     GNUNET_free (op_name);
690     return GNUNET_SYSERR;
691   }
692   GNUNET_free (op_name);
693
694   /* plugin */
695   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
696   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
697       sec_name, op_name, &o->plugin))
698   {
699     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
700         op_counter, "ADD_ADDRESS", op_name);
701     GNUNET_free (op_name);
702     return GNUNET_SYSERR;
703   }
704   GNUNET_free (op_name);
705
706   /* address  */
707   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
708   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
709       sec_name, op_name, &o->address))
710   {
711     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
712         op_counter, "ADD_ADDRESS", op_name);
713     GNUNET_free (op_name);
714     return GNUNET_SYSERR;
715   }
716   GNUNET_free (op_name);
717
718   /* session */
719   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
720   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
721       sec_name, op_name, &o->address_session))
722   {
723     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
724         op_counter, "ADD_ADDRESS", op_name);
725     GNUNET_free (op_name);
726     return GNUNET_SYSERR;
727   }
728   GNUNET_free (op_name);
729
730   /* network */
731   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
732   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
733       sec_name, op_name, &o->address_network))
734   {
735     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
736         op_counter, "ADD_ADDRESS", op_name);
737     GNUNET_free (op_name);
738     return GNUNET_SYSERR;
739   }
740   GNUNET_free (op_name);
741
742   fprintf (stderr,
743       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
744       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
745
746   return GNUNET_OK;
747 }
748
749 static int
750 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
751     struct Episode *e,
752     int op_counter,
753     char *sec_name,
754     const struct GNUNET_CONFIGURATION_Handle *cfg)
755 {
756   char *op_name;
757
758   /* peer id */
759   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
760   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
761       sec_name, op_name, &o->peer_id))
762   {
763     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
764         op_counter, "DEL_ADDRESS", op_name);
765     GNUNET_free (op_name);
766     return GNUNET_SYSERR;
767   }
768   GNUNET_free (op_name);
769
770   /* address id */
771   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
772   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
773       sec_name, op_name, &o->address_id))
774   {
775     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
776         op_counter, "DEL_ADDRESS", op_name);
777     GNUNET_free (op_name);
778     return GNUNET_SYSERR;
779   }
780   GNUNET_free (op_name);
781
782   /* plugin */
783   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
784   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
785       sec_name, op_name, &o->plugin))
786   {
787     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
788         op_counter, "DEL_ADDRESS", op_name);
789     GNUNET_free (op_name);
790     return GNUNET_SYSERR;
791   }
792   GNUNET_free (op_name);
793
794   /* address  */
795   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
796   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
797       sec_name, op_name, &o->address))
798   {
799     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
800         op_counter, "DEL_ADDRESS", op_name);
801     GNUNET_free (op_name);
802     return GNUNET_SYSERR;
803   }
804   GNUNET_free (op_name);
805
806   /* session */
807   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
808   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
809       sec_name, op_name, &o->address_session))
810   {
811     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
812         op_counter, "DEL_ADDRESS", op_name);
813     GNUNET_free (op_name);
814     return GNUNET_SYSERR;
815   }
816   GNUNET_free (op_name);
817
818   /* network */
819   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
820   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
821       sec_name, op_name, &o->address_network))
822   {
823     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
824         op_counter, "DEL_ADDRESS", op_name);
825     GNUNET_free (op_name);
826     return GNUNET_SYSERR;
827   }
828   GNUNET_free (op_name);
829
830   fprintf (stderr,
831       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
832       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
833
834   return GNUNET_OK;
835 }
836
837 static enum GNUNET_ATS_Property
838 parse_preference_string (const char * str)
839 {
840   int c = 0;
841   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
842
843   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
844     if (0 == strcmp(str, props[c]))
845       return c;
846   return 0;
847 };
848
849 static int
850 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
851     struct Episode *e,
852     int op_counter,
853     char *sec_name,
854     const struct GNUNET_CONFIGURATION_Handle *cfg)
855 {
856   char *op_name;
857   char *type;
858   char *pref;
859
860   /* peer id */
861   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
862   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
863       sec_name, op_name, &o->peer_id))
864   {
865     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
866         op_counter, "START_SET_PREFERENCE", op_name);
867     GNUNET_free (op_name);
868     return GNUNET_SYSERR;
869   }
870   GNUNET_free (op_name);
871
872   /* address id */
873   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
874   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
875       sec_name, op_name, &o->address_id))
876   {
877     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
878         op_counter, "START_SET_PREFERENCE", op_name);
879     GNUNET_free (op_name);
880     return GNUNET_SYSERR;
881   }
882   GNUNET_free (op_name);
883
884   /* generator */
885   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
886   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
887           sec_name, op_name, &type)) )
888   {
889     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
890         op_counter, "START_SET_PREFERENCE", op_name);
891     GNUNET_free (op_name);
892     return GNUNET_SYSERR;
893   }
894
895   /* Load arguments for set_rate, start_send, set_preference */
896   if (0 == strcmp (type, "constant"))
897   {
898     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
899   }
900   else if (0 == strcmp (type, "linear"))
901   {
902     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
903   }
904   else if (0 == strcmp (type, "sinus"))
905   {
906     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
907   }
908   else if (0 == strcmp (type, "random"))
909   {
910     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
911   }
912   else
913   {
914     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
915         op_counter, op_name, e->id);
916     GNUNET_free (type);
917     GNUNET_free (op_name);
918     return GNUNET_SYSERR;
919   }
920   GNUNET_free (type);
921   GNUNET_free (op_name);
922
923
924   /* Get base rate */
925   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
926   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
927       sec_name, op_name, &o->base_rate))
928   {
929     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
930         op_counter, op_name, e->id);
931     GNUNET_free (op_name);
932     return GNUNET_SYSERR;
933   }
934   GNUNET_free (op_name);
935
936
937   /* Get max rate */
938   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
939   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
940       sec_name, op_name, &o->max_rate))
941   {
942     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
943         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
944         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
945     {
946       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
947           op_counter, op_name, e->id);
948       GNUNET_free (op_name);
949       return GNUNET_SYSERR;
950     }
951   }
952   GNUNET_free (op_name);
953
954   /* Get period */
955   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
956   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
957       sec_name, op_name, &o->period))
958   {
959     o->period = e->duration;
960   }
961   GNUNET_free (op_name);
962
963   /* Get frequency */
964   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
965   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
966       sec_name, op_name, &o->frequency))
967   {
968       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
969           op_counter, op_name, e->id);
970       GNUNET_free (op_name);
971       return GNUNET_SYSERR;
972   }
973   GNUNET_free (op_name);
974
975   /* Get preference */
976   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
977   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
978       sec_name, op_name, &pref))
979   {
980       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
981           op_counter, op_name, e->id);
982       GNUNET_free (op_name);
983       return GNUNET_SYSERR;
984   }
985
986   if (0 == (o->pref_type = parse_preference_string(pref)))
987   {
988       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
989           op_counter, op_name, e->id);
990       GNUNET_free (op_name);
991       GNUNET_free (pref);
992       return GNUNET_SYSERR;
993   }
994   GNUNET_free (pref);
995   GNUNET_free (op_name);
996
997   fprintf (stderr,
998       "Found operation %s: [%llu:%llu]: %s = %llu\n",
999       "START_SET_PREFERENCE", o->peer_id, o->address_id,
1000       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
1001
1002   return GNUNET_OK;
1003 }
1004
1005 static int
1006 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1007     struct Episode *e,
1008     int op_counter,
1009     char *sec_name,
1010     const struct GNUNET_CONFIGURATION_Handle *cfg)
1011 {
1012   char *op_name;
1013   char *pref;
1014
1015   /* peer id */
1016   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1017   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1018       sec_name, op_name, &o->peer_id))
1019   {
1020     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1021         op_counter, "STOP_SET_PREFERENCE", op_name);
1022     GNUNET_free (op_name);
1023     return GNUNET_SYSERR;
1024   }
1025   GNUNET_free (op_name);
1026
1027   /* address id */
1028   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1029   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1030       sec_name, op_name, &o->address_id))
1031   {
1032     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1033         op_counter, "STOP_SET_PREFERENCE", op_name);
1034     GNUNET_free (op_name);
1035     return GNUNET_SYSERR;
1036   }
1037   GNUNET_free (op_name);
1038
1039   /* Get preference */
1040   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1041   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1042       sec_name, op_name, &pref))
1043   {
1044     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
1045         op_counter, "STOP_SET_PREFERENCE", op_name);
1046       GNUNET_free (op_name);
1047       return GNUNET_SYSERR;
1048   }
1049
1050   if (0 == (o->pref_type = parse_preference_string(pref)))
1051   {
1052       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1053           op_counter, op_name, e->id);
1054       GNUNET_free (op_name);
1055       GNUNET_free (pref);
1056       return GNUNET_SYSERR;
1057   }
1058   GNUNET_free (pref);
1059   GNUNET_free (op_name);
1060
1061   fprintf (stderr,
1062       "Found operation %s: [%llu:%llu]: %s\n",
1063       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1064       GNUNET_ATS_print_preference_type(o->pref_type));
1065   return GNUNET_OK;
1066 }
1067
1068 static enum GNUNET_ATS_Property
1069 parse_property_string (const char * str)
1070 {
1071   int c = 0;
1072   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
1073
1074   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1075     if (0 == strcmp(str, props[c]))
1076       return c;
1077   return 0;
1078 };
1079
1080 static int
1081 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1082     struct Episode *e,
1083     int op_counter,
1084     char *sec_name,
1085     const struct GNUNET_CONFIGURATION_Handle *cfg)
1086 {
1087   char *op_name;
1088   char *type;
1089   char *prop;
1090
1091   /* peer id */
1092   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1093   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1094       sec_name, op_name, &o->peer_id))
1095   {
1096     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1097         op_counter, "START_SET_PROPERTY", op_name);
1098     GNUNET_free (op_name);
1099     return GNUNET_SYSERR;
1100   }
1101   GNUNET_free (op_name);
1102
1103   /* address id */
1104   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1105   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1106       sec_name, op_name, &o->address_id))
1107   {
1108     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1109         op_counter, "START_SET_PROPERTY", op_name);
1110     GNUNET_free (op_name);
1111     return GNUNET_SYSERR;
1112   }
1113   GNUNET_free (op_name);
1114
1115   /* generator */
1116   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1117   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1118           sec_name, op_name, &type)) )
1119   {
1120     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1121         op_counter, "START_SET_PROPERTY", op_name);
1122     GNUNET_free (op_name);
1123     return GNUNET_SYSERR;
1124   }
1125
1126   /* Load arguments for set_rate, start_send, set_preference */
1127   if (0 == strcmp (type, "constant"))
1128   {
1129     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1130     GNUNET_break (0);
1131   }
1132   else if (0 == strcmp (type, "linear"))
1133   {
1134     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1135     GNUNET_break (0);
1136   }
1137   else if (0 == strcmp (type, "sinus"))
1138   {
1139     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1140     GNUNET_break (0);
1141   }
1142   else if (0 == strcmp (type, "random"))
1143   {
1144     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1145     GNUNET_break (0);
1146   }
1147   else
1148   {
1149     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1150         op_counter, op_name, e->id);
1151     GNUNET_free (type);
1152     GNUNET_free (op_name);
1153     return GNUNET_SYSERR;
1154   }
1155   GNUNET_free (type);
1156   GNUNET_free (op_name);
1157
1158
1159   /* Get base rate */
1160   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1161   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1162       sec_name, op_name, &o->base_rate))
1163   {
1164     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1165         op_counter, op_name, e->id);
1166     GNUNET_free (op_name);
1167     return GNUNET_SYSERR;
1168   }
1169   GNUNET_free (op_name);
1170
1171
1172   /* Get max rate */
1173   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1174   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1175       sec_name, op_name, &o->max_rate))
1176   {
1177     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1178         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1179         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1180     {
1181       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1182           op_counter, op_name, e->id);
1183       GNUNET_free (op_name);
1184       return GNUNET_SYSERR;
1185     }
1186   }
1187   GNUNET_free (op_name);
1188
1189   /* Get period */
1190   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1191   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1192       sec_name, op_name, &o->period))
1193   {
1194     o->period = e->duration;
1195   }
1196   GNUNET_free (op_name);
1197
1198   /* Get frequency */
1199   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1200   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1201       sec_name, op_name, &o->frequency))
1202   {
1203       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1204           op_counter, op_name, e->id);
1205       GNUNET_free (op_name);
1206       return GNUNET_SYSERR;
1207   }
1208   GNUNET_free (op_name);
1209
1210   /* Get preference */
1211   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1212   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1213       sec_name, op_name, &prop))
1214   {
1215       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1216           op_counter, op_name, e->id);
1217       GNUNET_free (op_name);
1218       GNUNET_free_non_null (prop);
1219       return GNUNET_SYSERR;
1220   }
1221
1222   if (0 == (o->prop_type = parse_property_string(prop)))
1223   {
1224       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1225           op_counter, op_name, e->id);
1226       GNUNET_free (op_name);
1227       GNUNET_free (prop);
1228       return GNUNET_SYSERR;
1229   }
1230
1231   GNUNET_free (prop);
1232   GNUNET_free (op_name);
1233
1234   fprintf (stderr,
1235       "Found operation %s: [%llu:%llu] %s = %llu\n",
1236       "START_SET_PROPERTY", o->peer_id, o->address_id,
1237       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1238
1239   return GNUNET_OK;
1240 }
1241
1242 static int
1243 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1244     struct Episode *e,
1245     int op_counter,
1246     char *sec_name,
1247     const struct GNUNET_CONFIGURATION_Handle *cfg)
1248 {
1249   char *op_name;
1250   char *pref;
1251
1252   /* peer id */
1253   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1254   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1255       sec_name, op_name, &o->peer_id))
1256   {
1257     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1258         op_counter, "STOP_SET_PROPERTY", op_name);
1259     GNUNET_free (op_name);
1260     return GNUNET_SYSERR;
1261   }
1262   GNUNET_free (op_name);
1263
1264   /* address id */
1265   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1266   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1267       sec_name, op_name, &o->address_id))
1268   {
1269     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1270         op_counter, "STOP_SET_PROPERTY", op_name);
1271     GNUNET_free (op_name);
1272     return GNUNET_SYSERR;
1273   }
1274   GNUNET_free (op_name);
1275
1276   /* Get property */
1277   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1278   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1279       sec_name, op_name, &pref))
1280   {
1281     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
1282         op_counter, "STOP_SET_PROPERTY", op_name);
1283       GNUNET_free (op_name);
1284       GNUNET_free_non_null (pref);
1285       return GNUNET_SYSERR;
1286   }
1287
1288   if (0 == (o->prop_type = parse_property_string(pref)))
1289   {
1290       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1291           op_counter, op_name, e->id);
1292       GNUNET_free (op_name);
1293       GNUNET_free (pref);
1294       GNUNET_free_non_null (pref);
1295       return GNUNET_SYSERR;
1296   }
1297
1298   GNUNET_free (pref);
1299   GNUNET_free (op_name);
1300
1301   fprintf (stderr,
1302       "Found operation %s: [%llu:%llu] %s\n",
1303       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
1304       GNUNET_ATS_print_property_type (o->prop_type));
1305
1306   return GNUNET_OK;
1307 }
1308
1309 static int
1310 load_episode (struct Experiment *e, struct Episode *cur,
1311     struct GNUNET_CONFIGURATION_Handle *cfg)
1312 {
1313   struct GNUNET_ATS_TEST_Operation *o;
1314   char *sec_name;
1315   char *op_name;
1316   char *op;
1317   int op_counter = 0;
1318   fprintf (stderr, "Parsing episode %u\n",cur->id);
1319   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1320
1321   while (1)
1322   {
1323     /* Load operation */
1324     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1325     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1326         sec_name, op_name, &op))
1327     {
1328       GNUNET_free (op_name);
1329       break;
1330     }
1331     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1332     /* operations = set_rate, start_send, stop_send, set_preference */
1333     if (0 == strcmp (op, "address_add"))
1334     {
1335       o->type = SOLVER_OP_ADD_ADDRESS;
1336       if (GNUNET_SYSERR == load_op_add_address (o, cur,
1337           op_counter, sec_name, cfg))
1338       {
1339         GNUNET_free (o);
1340         GNUNET_free (op);
1341         GNUNET_free (op_name);
1342         GNUNET_free (sec_name);
1343         return GNUNET_SYSERR;
1344       }
1345     }
1346     else if (0 == strcmp (op, "address_del"))
1347     {
1348       o->type = SOLVER_OP_DEL_ADDRESS;
1349       if (GNUNET_SYSERR == load_op_del_address (o, cur,
1350           op_counter, sec_name, cfg))
1351       {
1352         GNUNET_free (o);
1353         GNUNET_free (op);
1354         GNUNET_free (op_name);
1355         GNUNET_free (sec_name);
1356         return GNUNET_SYSERR;
1357       }
1358     }
1359     else if (0 == strcmp (op, "start_set_property"))
1360     {
1361       o->type = SOLVER_OP_START_SET_PROPERTY;
1362       if (GNUNET_SYSERR == load_op_start_set_property (o, cur,
1363           op_counter, sec_name, cfg))
1364       {
1365         GNUNET_free (o);
1366         GNUNET_free (op);
1367         GNUNET_free (op_name);
1368         GNUNET_free (sec_name);
1369         return GNUNET_SYSERR;
1370       }
1371     }
1372     else if (0 == strcmp (op, "stop_set_property"))
1373     {
1374       o->type = SOLVER_OP_STOP_SET_PROPERTY;
1375       if (GNUNET_SYSERR == load_op_stop_set_property (o, cur,
1376           op_counter, sec_name, cfg))
1377       {
1378         GNUNET_free (o);
1379         GNUNET_free (op);
1380         GNUNET_free (op_name);
1381         GNUNET_free (sec_name);
1382         return GNUNET_SYSERR;
1383       }
1384     }
1385     else if (0 == strcmp (op, "start_set_preference"))
1386     {
1387       o->type = SOLVER_OP_START_SET_PREFERENCE;
1388       if (GNUNET_SYSERR == load_op_start_set_preference (o, cur,
1389           op_counter, sec_name, cfg))
1390       {
1391         GNUNET_free (o);
1392         GNUNET_free (op);
1393         GNUNET_free (op_name);
1394         GNUNET_free (sec_name);
1395         return GNUNET_SYSERR;
1396       }
1397     }
1398     else if (0 == strcmp (op, "stop_set_preference"))
1399     {
1400       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
1401       if (GNUNET_SYSERR == load_op_stop_set_preference (o, cur,
1402           op_counter, sec_name, cfg))
1403       {
1404         GNUNET_free (o);
1405         GNUNET_free (op);
1406         GNUNET_free (op_name);
1407         GNUNET_free (sec_name);
1408         return GNUNET_SYSERR;
1409       }
1410     }
1411     else
1412     {
1413       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
1414           op_counter, op, cur->id);
1415       GNUNET_free (o);
1416       GNUNET_free (op);
1417       GNUNET_free (op_name);
1418       GNUNET_free (sec_name);
1419       return GNUNET_SYSERR;
1420     }
1421     GNUNET_free (op);
1422     GNUNET_free (op_name);
1423
1424     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
1425     op_counter++;
1426   }
1427   GNUNET_free (sec_name);
1428
1429
1430 #if 0
1431     /* Get source */
1432     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
1433     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1434         sec_name, op_name, &o->src_id))
1435     {
1436       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1437           op_counter, op, cur->id);
1438       GNUNET_free (op);
1439       GNUNET_free (op_name);
1440       return GNUNET_SYSERR;
1441     }
1442     if (o->src_id > (e->num_masters - 1))
1443     {
1444       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
1445           o->src_id, op_counter, op, cur->id);
1446       GNUNET_free (op);
1447       GNUNET_free (op_name);
1448       return GNUNET_SYSERR;
1449     }
1450     GNUNET_free (op_name);
1451
1452     /* Get destination */
1453     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
1454     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1455         sec_name, op_name, &o->dest_id))
1456     {
1457       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1458           op_counter, op, cur->id);
1459       GNUNET_free (op);
1460       GNUNET_free (op_name);
1461       return GNUNET_SYSERR;
1462     }
1463     if (o->dest_id > (e->num_slaves - 1))
1464     {
1465       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
1466           o->dest_id, op_counter, op, cur->id);
1467       GNUNET_free (op);
1468       GNUNET_free (op_name);
1469       return GNUNET_SYSERR;
1470     }
1471     GNUNET_free (op_name);
1472
1473     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
1474     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
1475             sec_name, op_name, &type)) &&
1476         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
1477     {
1478       /* Load arguments for set_rate, start_send, set_preference */
1479       if (0 == strcmp (type, "constant"))
1480       {
1481         o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1482       }
1483       else if (0 == strcmp (type, "linear"))
1484       {
1485         o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1486       }
1487       else if (0 == strcmp (type, "sinus"))
1488       {
1489         o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1490       }
1491       else if (0 == strcmp (type, "random"))
1492       {
1493         o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1494       }
1495       else
1496       {
1497         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
1498             op_counter, op, cur->id);
1499         GNUNET_free (type);
1500         GNUNET_free (op);
1501         GNUNET_free (op_name);
1502         return GNUNET_SYSERR;
1503       }
1504       GNUNET_free (op_name);
1505
1506       /* Get base rate */
1507       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1508       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1509           sec_name, op_name, &o->base_rate))
1510       {
1511         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1512             op_counter, op, cur->id);
1513         GNUNET_free (type);
1514         GNUNET_free (op);
1515         GNUNET_free (op_name);
1516         return GNUNET_SYSERR;
1517       }
1518       GNUNET_free (op_name);
1519
1520       /* Get max rate */
1521       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1522       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1523           sec_name, op_name, &o->max_rate))
1524       {
1525         if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1526             (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1527             (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1528         {
1529           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1530               op_counter, op, cur->id);
1531           GNUNET_free (type);
1532           GNUNET_free (op_name);
1533           GNUNET_free (op);
1534           return GNUNET_SYSERR;
1535         }
1536       }
1537       GNUNET_free (op_name);
1538
1539       /* Get period */
1540       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1541       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1542           sec_name, op_name, &o->period))
1543       {
1544         o->period = cur->duration;
1545       }
1546       GNUNET_free (op_name);
1547
1548       if (START_PREFERENCE == o->type)
1549       {
1550           /* Get frequency */
1551           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1552           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1553               sec_name, op_name, &o->frequency))
1554           {
1555               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1556                   op_counter, op, cur->id);
1557               GNUNET_free (type);
1558               GNUNET_free (op_name);
1559               GNUNET_free (op);
1560               return GNUNET_SYSERR;
1561           }
1562           GNUNET_free (op_name);
1563
1564           /* Get preference */
1565           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1566           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1567               sec_name, op_name, &pref))
1568           {
1569               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1570                   op_counter, op, cur->id);
1571               GNUNET_free (type);
1572               GNUNET_free (op_name);
1573               GNUNET_free (op);
1574               GNUNET_free_non_null (pref);
1575               return GNUNET_SYSERR;
1576           }
1577
1578           if (0 == strcmp(pref, "bandwidth"))
1579             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
1580           else if (0 == strcmp(pref, "latency"))
1581             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
1582           else
1583           {
1584               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1585                   op_counter, op, cur->id);
1586               GNUNET_free (type);
1587               GNUNET_free (op_name);
1588               GNUNET_free (op);
1589               GNUNET_free (pref);
1590               GNUNET_free_non_null (pref);
1591               return GNUNET_SYSERR;
1592           }
1593           GNUNET_free (pref);
1594           GNUNET_free (op_name);
1595       }
1596     }
1597
1598     /* Safety checks */
1599     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1600         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1601     {
1602       if ((o->max_rate - o->base_rate) > o->base_rate)
1603       {
1604         /* This will cause an underflow */
1605         GNUNET_break (0);
1606       }
1607       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
1608     }
1609
1610     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
1611       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
1612         op_counter, cur->id, print_op (o->type), o->src_id,
1613         o->dest_id, (NULL != type) ? type : "",
1614         o->base_rate, o->max_rate,
1615         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
1616     else
1617       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
1618         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
1619
1620     GNUNET_free_non_null (type);
1621     GNUNET_free (op);
1622 #endif
1623
1624   return GNUNET_OK;
1625 }
1626
1627 static int
1628 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1629 {
1630   int e_counter = 0;
1631   char *sec_name;
1632   struct GNUNET_TIME_Relative e_duration;
1633   struct Episode *cur;
1634   struct Episode *last;
1635
1636   e_counter = 0;
1637   last = NULL;
1638   while (1)
1639   {
1640     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1641     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1642         sec_name, "duration", &e_duration))
1643     {
1644       GNUNET_free (sec_name);
1645       break;
1646     }
1647
1648     cur = GNUNET_new (struct Episode);
1649     cur->duration = e_duration;
1650     cur->id = e_counter;
1651
1652     if (GNUNET_OK != load_episode (e, cur, cfg))
1653     {
1654       GNUNET_free (sec_name);
1655       GNUNET_free (cur);
1656       return GNUNET_SYSERR;
1657     }
1658
1659     fprintf (stderr, "Found episode %u with duration %s \n",
1660         e_counter,
1661         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1662
1663     /* Update experiment */
1664     e->num_episodes ++;
1665     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1666     /* Put in linked list */
1667     if (NULL == last)
1668       e->start = cur;
1669     else
1670     last->next = cur;
1671
1672     GNUNET_free (sec_name);
1673     e_counter ++;
1674     last = cur;
1675   }
1676   return e_counter;
1677 }
1678
1679 static void
1680 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1681 {
1682   struct Experiment *e = cls;
1683   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1684   fprintf (stderr, "Experiment timeout!\n");
1685
1686   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1687   {
1688     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1689     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1690   }
1691
1692   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
1693       GNUNET_SYSERR);
1694 }
1695
1696 static void
1697 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
1698 {
1699   /*
1700   struct BenchmarkPeer *peer;
1701   struct BenchmarkPartner *partner;
1702
1703   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
1704   if (NULL == peer)
1705   {
1706     GNUNET_break (0);
1707     return;
1708   }
1709
1710   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1711   if (NULL == partner)
1712   {
1713     GNUNET_break (0);
1714     return;
1715   }
1716
1717   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1718
1719   if (NULL != partner->tg)
1720   {
1721     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
1722     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
1723     partner->tg = NULL;
1724   }
1725
1726   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
1727       op->tg_type, op->base_rate, op->max_rate, op->period,
1728       GNUNET_TIME_UNIT_FOREVER_REL);
1729    */
1730 }
1731
1732 static void
1733 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
1734 {
1735   /*
1736   struct BenchmarkPartner *p;
1737   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1738   if (NULL == p)
1739   {
1740     GNUNET_break (0);
1741     return;
1742   }
1743
1744   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1745
1746   if (NULL != p->tg)
1747   {
1748     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
1749         op->src_id, op->dest_id);
1750     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
1751     p->tg = NULL;
1752   }
1753   */
1754 }
1755
1756 static void
1757 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
1758 {
1759   struct PropertyGenerator *pg;
1760   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
1761   {
1762     GNUNET_ATS_solver_generate_property_stop (pg);
1763     GNUNET_free (pg);
1764   }
1765
1766   GNUNET_ATS_solver_generate_property_start (op->peer_id,
1767     op->address_id,
1768     op->type,
1769     op->base_rate,
1770     op->max_rate,
1771     op->period,
1772     op->frequency,
1773     op->prop_type);
1774 }
1775
1776 static void
1777 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
1778 {
1779   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
1780       op->prop_type);
1781   if (NULL != pg)
1782       GNUNET_ATS_solver_generate_property_stop (pg);
1783 }
1784
1785 static void
1786 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
1787 {
1788   struct PreferenceGenerator *pg;
1789   if (NULL != (pg = find_pref_gen (op->peer_id, op->address_id, op->pref_type)))
1790   {
1791     GNUNET_ATS_solver_generate_preferences_stop (pg);
1792     GNUNET_free (pg);
1793   }
1794
1795   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
1796     op->address_id,
1797     op->gen_type,
1798     op->base_rate,
1799     op->max_rate,
1800     op->period,
1801     op->frequency,
1802     op->pref_type);
1803 }
1804
1805 static void
1806 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
1807 {
1808   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id, op->address_id,
1809       op->pref_type);
1810   if (NULL != pg)
1811       GNUNET_ATS_solver_generate_preferences_stop (pg);
1812 }
1813
1814 static void enforce_episode (struct Episode *ep)
1815 {
1816   struct GNUNET_ATS_TEST_Operation *cur;
1817   for (cur = ep->head; NULL != cur; cur = cur->next)
1818   {
1819     switch (cur->type) {
1820       case SOLVER_OP_ADD_ADDRESS:
1821         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1822             print_op (cur->type), cur->peer_id, cur->address_id);
1823         enforce_add_address (cur);
1824         break;
1825       case SOLVER_OP_DEL_ADDRESS:
1826         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1827             print_op (cur->type), cur->peer_id, cur->address_id);
1828         enforce_del_address (cur);
1829         break;
1830       case SOLVER_OP_START_SET_PROPERTY:
1831         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1832             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1833         enforce_start_property (cur);
1834         break;
1835       case SOLVER_OP_STOP_SET_PROPERTY:
1836         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1837             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1838         enforce_stop_property (cur);
1839         break;
1840       case SOLVER_OP_START_SET_PREFERENCE:
1841         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1842             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1843         enforce_start_preference (cur);
1844         break;
1845       case SOLVER_OP_STOP_SET_PREFERENCE:
1846         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1847             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1848         enforce_stop_preference (cur);
1849         break;
1850       default:
1851         break;
1852     }
1853   }
1854 }
1855
1856 static void
1857 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1858 {
1859   struct Experiment *e = cls;
1860   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1861   if (NULL != e->ep_done_cb)
1862     e->ep_done_cb (e->cur);
1863
1864   /* Scheduling next */
1865   e->cur = e->cur->next;
1866   if (NULL == e->cur)
1867   {
1868     /* done */
1869     fprintf (stderr, "Last episode done!\n");
1870     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1871     {
1872       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1873       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1874     }
1875     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
1876     return;
1877   }
1878
1879   fprintf (stderr, "Running episode %u with timeout %s\n",
1880       e->cur->id,
1881       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1882   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1883       &timeout_episode, e);
1884   enforce_episode(e->cur);
1885
1886
1887 }
1888
1889
1890 void
1891 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
1892     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
1893     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
1894 {
1895   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
1896       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
1897   e->e_done_cb = e_done_cb;
1898   e->ep_done_cb = ep_done_cb;
1899   e->start_time = GNUNET_TIME_absolute_get();
1900
1901   /* Start total time out */
1902   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
1903       &timeout_experiment, e);
1904
1905
1906   /* Start */
1907   if (NULL == e->start)
1908   {
1909     GNUNET_break (0);
1910     return;
1911   }
1912   e->cur = e->start;
1913   fprintf (stderr, "Running episode %u with timeout %s\n",
1914       e->cur->id,
1915       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1916   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1917       &timeout_episode, e);
1918   enforce_episode(e->cur);
1919
1920 }
1921
1922 void
1923 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
1924 {
1925   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1926   {
1927     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1928     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1929   }
1930   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1931   {
1932     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1933     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1934   }
1935   if (NULL != e->cfg)
1936   {
1937     GNUNET_CONFIGURATION_destroy(e->cfg);
1938     e->cfg = NULL;
1939   }
1940   free_experiment (e);
1941 }
1942
1943
1944 struct Experiment *
1945 GNUNET_ATS_solvers_experimentation_load (char *filename)
1946 {
1947   struct Experiment *e;
1948   struct GNUNET_CONFIGURATION_Handle *cfg;
1949   e = NULL;
1950
1951   cfg = GNUNET_CONFIGURATION_create();
1952   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
1953   {
1954     fprintf (stderr, "Failed to load `%s'\n", filename);
1955     GNUNET_CONFIGURATION_destroy (cfg);
1956     return NULL;
1957   }
1958
1959   e = create_experiment ();
1960
1961   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
1962       "name", &e->name))
1963   {
1964     fprintf (stderr, "Invalid %s", "name");
1965     free_experiment (e);
1966     return NULL;
1967   }
1968   else
1969     fprintf (stderr, "Experiment name: `%s'\n", e->name);
1970
1971   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
1972       "cfg_file", &e->cfg_file))
1973   {
1974     fprintf (stderr, "Invalid %s", "cfg_file");
1975     free_experiment (e);
1976     return NULL;
1977   }
1978   else
1979   {
1980     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
1981     e->cfg = GNUNET_CONFIGURATION_create();
1982     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
1983     {
1984       fprintf (stderr, "Invalid configuration %s", "cfg_file");
1985       free_experiment (e);
1986       return NULL;
1987     }
1988
1989   }
1990
1991   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
1992       "masters", &e->num_masters))
1993   {
1994     fprintf (stderr, "Invalid %s", "masters");
1995     free_experiment (e);
1996     return NULL;
1997   }
1998   else
1999     fprintf (stderr, "Experiment masters: `%llu'\n",
2000         e->num_masters);
2001
2002   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
2003       "slaves", &e->num_slaves))
2004   {
2005     fprintf (stderr, "Invalid %s", "slaves");
2006     free_experiment (e);
2007     return NULL;
2008   }
2009   else
2010     fprintf (stderr, "Experiment slaves: `%llu'\n",
2011         e->num_slaves);
2012
2013   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2014       "log_freq", &e->log_freq))
2015   {
2016     fprintf (stderr, "Invalid %s", "log_freq");
2017     free_experiment (e);
2018     return NULL;
2019   }
2020   else
2021     fprintf (stderr, "Experiment logging frequency: `%s'\n",
2022         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2023
2024   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2025       "max_duration", &e->max_duration))
2026   {
2027     fprintf (stderr, "Invalid %s", "max_duration");
2028     free_experiment (e);
2029     return NULL;
2030   }
2031   else
2032     fprintf (stderr, "Experiment duration: `%s'\n",
2033         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2034
2035   if (GNUNET_SYSERR == load_episodes (e, cfg))
2036   {
2037     GNUNET_ATS_solvers_experimentation_stop (e);
2038     GNUNET_CONFIGURATION_destroy (cfg);
2039     e = NULL;
2040     fprintf (stderr, "Failed to load experiment\n");
2041     return NULL;
2042   }
2043   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
2044       e->num_episodes,
2045       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2046
2047   GNUNET_CONFIGURATION_destroy (cfg);
2048   return e;
2049 }
2050
2051 /**
2052  * Logging
2053  */
2054
2055
2056 /**
2057  * Solver
2058  */
2059
2060 struct GNUNET_ATS_TESTING_SolverHandle
2061 {
2062   char * plugin;
2063   struct GNUNET_ATS_PluginEnvironment env;
2064   void *solver;
2065   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
2066 };
2067
2068 enum GNUNET_ATS_Solvers
2069 {
2070   GNUNET_ATS_SOLVER_PROPORTIONAL,
2071   GNUNET_ATS_SOLVER_MLP,
2072   GNUNET_ATS_SOLVER_RIL,
2073 };
2074
2075
2076 void
2077 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
2078 {
2079  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2080      GNUNET_NO);
2081  GNUNET_CONTAINER_multipeermap_destroy(sh->env.addresses);
2082  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
2083  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2084  GNUNET_free (sh->plugin);
2085  GNUNET_free (sh);
2086 }
2087
2088 /**
2089  * Load quotas for networks from configuration
2090  *
2091  * @param cfg configuration handle
2092  * @param out_dest where to write outbound quotas
2093  * @param in_dest where to write inbound quotas
2094  * @param dest_length length of inbound and outbound arrays
2095  * @return number of networks loaded
2096  */
2097 unsigned int
2098 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2099                                                  unsigned long long *out_dest,
2100                                                  unsigned long long *in_dest,
2101                                                  int dest_length)
2102 {
2103   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
2104   char * entry_in = NULL;
2105   char * entry_out = NULL;
2106   char * quota_out_str;
2107   char * quota_in_str;
2108   int c;
2109   int res;
2110
2111   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2112   {
2113     in_dest[c] = 0;
2114     out_dest[c] = 0;
2115     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
2116     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
2117
2118     /* quota out */
2119     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2120     {
2121       res = GNUNET_NO;
2122       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2123       {
2124         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2125         res = GNUNET_YES;
2126       }
2127       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2128         res = GNUNET_YES;
2129       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2130          res = GNUNET_YES;
2131
2132       if (GNUNET_NO == res)
2133       {
2134           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2135               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
2136           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2137       }
2138       else
2139       {
2140           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
2141               network_str[c], out_dest[c]);
2142       }
2143       GNUNET_free (quota_out_str);
2144     }
2145     else
2146     {
2147       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2148           network_str[c], GNUNET_ATS_DefaultBandwidth);
2149       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2150     }
2151
2152     /* quota in */
2153     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2154     {
2155       res = GNUNET_NO;
2156       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2157       {
2158         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2159         res = GNUNET_YES;
2160       }
2161       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2162         res = GNUNET_YES;
2163       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2164          res = GNUNET_YES;
2165
2166       if (GNUNET_NO == res)
2167       {
2168           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2169               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
2170           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2171       }
2172       else
2173       {
2174           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
2175               network_str[c], in_dest[c]);
2176       }
2177       GNUNET_free (quota_in_str);
2178     }
2179     else
2180     {
2181       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2182           network_str[c], GNUNET_ATS_DefaultBandwidth);
2183       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2184     }
2185     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]);
2186     GNUNET_free (entry_out);
2187     GNUNET_free (entry_in);
2188   }
2189   return GNUNET_ATS_NetworkTypeCount;
2190 }
2191
2192 /**
2193  * Information callback for the solver
2194  *
2195  * @param op the solver operation
2196  * @param stat status of the solver operation
2197  * @param add additional solver information
2198  */
2199 static void
2200 solver_info_cb (void *cls,
2201     enum GAS_Solver_Operation op,
2202     enum GAS_Solver_Status stat,
2203     enum GAS_Solver_Additional_Information add)
2204 {
2205   char *add_info;
2206   switch (add) {
2207     case GAS_INFO_NONE:
2208       add_info = "GAS_INFO_NONE";
2209       break;
2210     case GAS_INFO_FULL:
2211       add_info = "GAS_INFO_MLP_FULL";
2212       break;
2213     case GAS_INFO_UPDATED:
2214       add_info = "GAS_INFO_MLP_UPDATED";
2215       break;
2216     case GAS_INFO_PROP_ALL:
2217       add_info = "GAS_INFO_PROP_ALL";
2218       break;
2219     case GAS_INFO_PROP_SINGLE:
2220       add_info = "GAS_INFO_PROP_SINGLE";
2221       break;
2222     default:
2223       add_info = "INVALID";
2224       break;
2225   }
2226
2227   switch (op)
2228   {
2229     case GAS_OP_SOLVE_START:
2230       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2231           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2232           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2233       return;
2234     case GAS_OP_SOLVE_STOP:
2235       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2236           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2237           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2238       return;
2239
2240     case GAS_OP_SOLVE_SETUP_START:
2241       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2242           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2243           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2244       return;
2245
2246     case GAS_OP_SOLVE_SETUP_STOP:
2247       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2248           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2249           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2250       return;
2251
2252     case GAS_OP_SOLVE_MLP_LP_START:
2253       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2254           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2255           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2256       return;
2257     case GAS_OP_SOLVE_MLP_LP_STOP:
2258       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2259           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2260           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2261       return;
2262
2263     case GAS_OP_SOLVE_MLP_MLP_START:
2264       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2265           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2266           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2267       return;
2268     case GAS_OP_SOLVE_MLP_MLP_STOP:
2269       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2270           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2271           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2272       return;
2273     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2274       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2275           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2276           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2277       return;
2278     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2279       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2280           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2281           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2282       return;
2283     default:
2284       break;
2285     }
2286 }
2287
2288 static void
2289 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2290 {
2291   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
2292        (0 == ntohl (address->assigned_bw_in.value__)) )
2293     return;
2294
2295   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2296               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2297               GNUNET_i2s (&address->peer),
2298               address,
2299               (unsigned int) ntohl (address->assigned_bw_out.value__),
2300               (unsigned int) ntohl (address->assigned_bw_in.value__));
2301   /*if (GNUNET_YES == ph.bulk_running)
2302     GNUNET_break (0);*/
2303   return;
2304 }
2305
2306 const double *
2307 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
2308 {
2309   return GAS_normalization_get_preferences_by_peer (id);
2310 }
2311
2312
2313 const double *
2314 get_property_cb (void *cls, const struct ATS_Address *address)
2315 {
2316   return GAS_normalization_get_properties ((struct ATS_Address *) address);
2317 }
2318
2319 static void
2320 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
2321     uint32_t type, double prop_rel)
2322 {
2323   /* TODO */
2324 }
2325
2326
2327 struct GNUNET_ATS_TESTING_SolverHandle *
2328 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
2329 {
2330   struct GNUNET_ATS_TESTING_SolverHandle *sh;
2331   char * solver_str;
2332   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
2333   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
2334
2335   switch (type) {
2336     case GNUNET_ATS_SOLVER_PROPORTIONAL:
2337       solver_str = "proportional";
2338       break;
2339     case GNUNET_ATS_SOLVER_MLP:
2340       solver_str = "mlp";
2341       break;
2342     case GNUNET_ATS_SOLVER_RIL:
2343       solver_str = "ril";
2344       break;
2345     default:
2346       GNUNET_break (0);
2347       return NULL;
2348       break;
2349   }
2350
2351   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
2352   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
2353
2354   /* setup environment */
2355   sh->env.cfg = e->cfg;
2356   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
2357   sh->env.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
2358   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
2359   sh->env.get_preferences = &get_preferences_cb;
2360   sh->env.get_property = &get_property_cb;
2361   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
2362   sh->env.info_cb = &solver_info_cb;
2363   sh->env.info_cb_cls = NULL;
2364
2365   /* start normalization */
2366   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
2367
2368   /* load quotas */
2369   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
2370       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
2371   {
2372     GNUNET_break(0);
2373     GNUNET_free (sh->plugin);
2374     GNUNET_free (sh);
2375     end_now ();
2376     return NULL;
2377   }
2378
2379   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
2380   if (NULL == sh->solver)
2381   {
2382     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
2383     GNUNET_break(0);
2384     GNUNET_free (sh->plugin);
2385     GNUNET_free (sh);
2386     end_now ();
2387     return NULL;
2388   }
2389
2390   sh->addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
2391
2392   return sh;
2393 }
2394
2395 static void
2396 done ()
2397 {
2398   /* Clean up experiment */
2399   GNUNET_ATS_solver_generate_preferences_stop_all ();
2400
2401   if (NULL != e)
2402   {
2403     GNUNET_ATS_solvers_experimentation_stop (e);
2404     e = NULL;
2405   }
2406
2407   if (NULL != l)
2408   {
2409     GNUNET_ATS_solver_logging_free (l);
2410     l = NULL;
2411   }
2412
2413   /* Shutdown */
2414   end_now();
2415
2416 }
2417
2418 static void
2419 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
2420 {
2421   if (GNUNET_OK == success)
2422     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
2423         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
2424   else
2425     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
2426
2427   /* Stop logging */
2428   GNUNET_ATS_solver_logging_stop (l);
2429
2430   /* Stop traffic generation */
2431   // GNUNET_ATS_TEST_generate_traffic_stop_all();
2432
2433   /* Stop all preference generations */
2434   GNUNET_ATS_solver_generate_preferences_stop_all ();
2435
2436   /*
2437   evaluate (duration);
2438   if (opt_log)
2439     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
2440
2441   if (NULL != l)
2442   {
2443     GNUNET_ATS_TEST_logging_stop (l);
2444     GNUNET_ATS_TEST_logging_clean_up (l);
2445     l = NULL;
2446   }
2447   */
2448   GNUNET_SCHEDULER_add_now (&done, NULL);
2449 }
2450
2451 static void
2452 episode_done_cb (struct Episode *ep)
2453 {
2454   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
2455 }
2456
2457
2458
2459 /**
2460  * Do shutdown
2461  */
2462 static void
2463 end_now ()
2464 {
2465   if (NULL != e)
2466   {
2467     GNUNET_ATS_solvers_experimentation_stop (e);
2468     e = NULL;
2469   }
2470   if (NULL != sh)
2471   {
2472     GNUNET_ATS_solvers_solver_stop (sh);
2473     sh = NULL;
2474   }
2475 }
2476
2477 static void
2478 run (void *cls, char * const *args, const char *cfgfile,
2479     const struct GNUNET_CONFIGURATION_Handle *cfg)
2480 {
2481   enum GNUNET_ATS_Solvers solver;
2482
2483   if (NULL == opt_exp_file)
2484   {
2485     fprintf (stderr, "No experiment given ...\n");
2486     res = 1;
2487     end_now ();
2488     return;
2489   }
2490
2491   if (NULL == opt_solver)
2492   {
2493     fprintf (stderr, "No solver given ...\n");
2494     res = 1;
2495     end_now ();
2496     return;
2497   }
2498
2499   if (0 == strcmp(opt_solver, "mlp"))
2500   {
2501     solver = GNUNET_ATS_SOLVER_MLP;
2502   }
2503   else if (0 == strcmp(opt_solver, "proportional"))
2504   {
2505     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
2506   }
2507   else if (0 == strcmp(opt_solver, "ril"))
2508   {
2509     solver = GNUNET_ATS_SOLVER_RIL;
2510   }
2511   else
2512   {
2513     fprintf (stderr, "No solver given ...");
2514     res = 1;
2515     end_now ();
2516     return;
2517   }
2518
2519   /* load experiment */
2520   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
2521   if (NULL == e)
2522   {
2523     fprintf (stderr, "Failed to load experiment ...\n");
2524     res = 1;
2525     end_now ();
2526     return;
2527   }
2528
2529   /* load solver */
2530   sh = GNUNET_ATS_solvers_solver_start (solver);
2531   if (NULL == sh)
2532   {
2533     fprintf (stderr, "Failed to start solver ...\n");
2534     end_now ();
2535     res = 1;
2536     return;
2537   }
2538
2539   /* start logging */
2540   l = GNUNET_ATS_solver_logging_start (e->log_freq);
2541
2542   /* run experiment */
2543   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
2544       experiment_done_cb);
2545
2546   /* WAIT */
2547 }
2548
2549
2550 /**
2551  * Main function of the benchmark
2552  *
2553  * @param argc argument count
2554  * @param argv argument values
2555  */
2556 int
2557 main (int argc, char *argv[])
2558 {
2559   opt_exp_file = NULL;
2560   opt_solver = NULL;
2561   opt_log = GNUNET_NO;
2562   opt_plot = GNUNET_NO;
2563
2564   res = 0;
2565
2566   static struct GNUNET_GETOPT_CommandLineOption options[] =
2567   {
2568     { 's', "solver", NULL,
2569         gettext_noop ("solver to use"),
2570         1, &GNUNET_GETOPT_set_string, &opt_solver},
2571     {  'e', "experiment", NULL,
2572       gettext_noop ("experiment to use"),
2573       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
2574     {  'e', "experiment", NULL,
2575       gettext_noop ("experiment to use"),
2576       1, &GNUNET_GETOPT_set_one, &opt_verbose},
2577     GNUNET_GETOPT_OPTION_END
2578   };
2579
2580   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
2581       NULL, options, &run, argv[0]);
2582
2583   return res;
2584 }
2585 /* end of file ats-testing-experiment.c*/
2586