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