improved episode parsing
[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     case SOLVER_OP_START_REQUEST:
620       return "START_REQUEST";
621     case SOLVER_OP_STOP_REQUEST:
622       return "STOP_REQUEST";
623     default:
624       break;
625   }
626   return "";
627 }
628
629 static struct Experiment *
630 create_experiment ()
631 {
632   struct Experiment *e;
633   e = GNUNET_new (struct Experiment);
634   e->name = NULL;
635   e->num_masters = 0;
636   e->num_slaves = 0;
637   e->start = NULL;
638   e->total_duration = GNUNET_TIME_UNIT_ZERO;
639   return e;
640 }
641
642 static void
643 free_experiment (struct Experiment *e)
644 {
645   struct Episode *cur;
646   struct Episode *next;
647   struct GNUNET_ATS_TEST_Operation *cur_o;
648   struct GNUNET_ATS_TEST_Operation *next_o;
649
650   next = e->start;
651   for (cur = next; NULL != cur; cur = next)
652   {
653     next = cur->next;
654
655     next_o = cur->head;
656     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
657     {
658       next_o = cur_o->next;
659       GNUNET_free_non_null (cur_o->address);
660       GNUNET_free_non_null (cur_o->plugin);
661       GNUNET_free (cur_o);
662     }
663     GNUNET_free (cur);
664   }
665
666   GNUNET_free_non_null (e->name);
667   GNUNET_free_non_null (e->cfg_file);
668   GNUNET_free (e);
669 }
670
671
672 static int
673 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
674     struct Episode *e,
675     int op_counter,
676     char *sec_name,
677     const struct GNUNET_CONFIGURATION_Handle *cfg)
678 {
679   char *op_name;
680
681   /* peer id */
682   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
683   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
684       sec_name, op_name, &o->peer_id))
685   {
686     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
687         op_counter, "ADD_ADDRESS", op_name);
688     GNUNET_free (op_name);
689     return GNUNET_SYSERR;
690   }
691   GNUNET_free (op_name);
692
693   /* address id */
694   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
695   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
696       sec_name, op_name, &o->address_id))
697   {
698     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
699         op_counter, "ADD_ADDRESS", op_name);
700     GNUNET_free (op_name);
701     return GNUNET_SYSERR;
702   }
703   GNUNET_free (op_name);
704
705   /* plugin */
706   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
707   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
708       sec_name, op_name, &o->plugin))
709   {
710     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
711         op_counter, "ADD_ADDRESS", op_name);
712     GNUNET_free (op_name);
713     return GNUNET_SYSERR;
714   }
715   GNUNET_free (op_name);
716
717   /* address  */
718   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
719   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
720       sec_name, op_name, &o->address))
721   {
722     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
723         op_counter, "ADD_ADDRESS", op_name);
724     GNUNET_free (op_name);
725     return GNUNET_SYSERR;
726   }
727   GNUNET_free (op_name);
728
729   /* session */
730   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
731   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
732       sec_name, op_name, &o->address_session))
733   {
734     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
735         op_counter, "ADD_ADDRESS", op_name);
736     GNUNET_free (op_name);
737     return GNUNET_SYSERR;
738   }
739   GNUNET_free (op_name);
740
741   /* network */
742   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
743   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
744       sec_name, op_name, &o->address_network))
745   {
746     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
747         op_counter, "ADD_ADDRESS", op_name);
748     GNUNET_free (op_name);
749     return GNUNET_SYSERR;
750   }
751   GNUNET_free (op_name);
752
753   fprintf (stderr,
754       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
755       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
756
757   return GNUNET_OK;
758 }
759
760 static int
761 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
762     struct Episode *e,
763     int op_counter,
764     char *sec_name,
765     const struct GNUNET_CONFIGURATION_Handle *cfg)
766 {
767   char *op_name;
768
769   /* peer id */
770   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
771   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
772       sec_name, op_name, &o->peer_id))
773   {
774     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
775         op_counter, "DEL_ADDRESS", op_name);
776     GNUNET_free (op_name);
777     return GNUNET_SYSERR;
778   }
779   GNUNET_free (op_name);
780
781   /* address id */
782   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
783   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
784       sec_name, op_name, &o->address_id))
785   {
786     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
787         op_counter, "DEL_ADDRESS", op_name);
788     GNUNET_free (op_name);
789     return GNUNET_SYSERR;
790   }
791   GNUNET_free (op_name);
792
793   /* plugin */
794   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
795   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
796       sec_name, op_name, &o->plugin))
797   {
798     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
799         op_counter, "DEL_ADDRESS", op_name);
800     GNUNET_free (op_name);
801     return GNUNET_SYSERR;
802   }
803   GNUNET_free (op_name);
804
805   /* address  */
806   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
807   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
808       sec_name, op_name, &o->address))
809   {
810     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
811         op_counter, "DEL_ADDRESS", op_name);
812     GNUNET_free (op_name);
813     return GNUNET_SYSERR;
814   }
815   GNUNET_free (op_name);
816
817   /* session */
818   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
819   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
820       sec_name, op_name, &o->address_session))
821   {
822     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
823         op_counter, "DEL_ADDRESS", op_name);
824     GNUNET_free (op_name);
825     return GNUNET_SYSERR;
826   }
827   GNUNET_free (op_name);
828
829   /* network */
830   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
831   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
832       sec_name, op_name, &o->address_network))
833   {
834     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
835         op_counter, "DEL_ADDRESS", op_name);
836     GNUNET_free (op_name);
837     return GNUNET_SYSERR;
838   }
839   GNUNET_free (op_name);
840
841   fprintf (stderr,
842       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
843       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
844
845   return GNUNET_OK;
846 }
847
848 static enum GNUNET_ATS_Property
849 parse_preference_string (const char * str)
850 {
851   int c = 0;
852   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
853
854   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
855     if (0 == strcmp(str, props[c]))
856       return c;
857   return 0;
858 };
859
860 static int
861 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
862     struct Episode *e,
863     int op_counter,
864     char *sec_name,
865     const struct GNUNET_CONFIGURATION_Handle *cfg)
866 {
867   char *op_name;
868   char *type;
869   char *pref;
870
871   /* peer id */
872   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
873   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
874       sec_name, op_name, &o->peer_id))
875   {
876     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
877         op_counter, "START_SET_PREFERENCE", op_name);
878     GNUNET_free (op_name);
879     return GNUNET_SYSERR;
880   }
881   GNUNET_free (op_name);
882
883   /* address id */
884   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
885   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
886       sec_name, op_name, &o->address_id))
887   {
888     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
889         op_counter, "START_SET_PREFERENCE", op_name);
890     GNUNET_free (op_name);
891     return GNUNET_SYSERR;
892   }
893   GNUNET_free (op_name);
894
895   /* generator */
896   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
897   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
898           sec_name, op_name, &type)) )
899   {
900     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
901         op_counter, "START_SET_PREFERENCE", op_name);
902     GNUNET_free (op_name);
903     return GNUNET_SYSERR;
904   }
905
906   /* Load arguments for set_rate, start_send, set_preference */
907   if (0 == strcmp (type, "constant"))
908   {
909     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
910   }
911   else if (0 == strcmp (type, "linear"))
912   {
913     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
914   }
915   else if (0 == strcmp (type, "sinus"))
916   {
917     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
918   }
919   else if (0 == strcmp (type, "random"))
920   {
921     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
922   }
923   else
924   {
925     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
926         op_counter, op_name, e->id);
927     GNUNET_free (type);
928     GNUNET_free (op_name);
929     return GNUNET_SYSERR;
930   }
931   GNUNET_free (type);
932   GNUNET_free (op_name);
933
934
935   /* Get base rate */
936   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
937   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
938       sec_name, op_name, &o->base_rate))
939   {
940     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
941         op_counter, op_name, e->id);
942     GNUNET_free (op_name);
943     return GNUNET_SYSERR;
944   }
945   GNUNET_free (op_name);
946
947
948   /* Get max rate */
949   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
950   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
951       sec_name, op_name, &o->max_rate))
952   {
953     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
954         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
955         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
956     {
957       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
958           op_counter, op_name, e->id);
959       GNUNET_free (op_name);
960       return GNUNET_SYSERR;
961     }
962   }
963   GNUNET_free (op_name);
964
965   /* Get period */
966   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
967   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
968       sec_name, op_name, &o->period))
969   {
970     o->period = e->duration;
971   }
972   GNUNET_free (op_name);
973
974   /* Get frequency */
975   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
976   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
977       sec_name, op_name, &o->frequency))
978   {
979       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
980           op_counter, op_name, e->id);
981       GNUNET_free (op_name);
982       return GNUNET_SYSERR;
983   }
984   GNUNET_free (op_name);
985
986   /* Get preference */
987   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
988   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
989       sec_name, op_name, &pref))
990   {
991       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
992           op_counter, op_name, e->id);
993       GNUNET_free (op_name);
994       return GNUNET_SYSERR;
995   }
996
997   if (0 == (o->pref_type = parse_preference_string(pref)))
998   {
999       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1000           op_counter, op_name, e->id);
1001       GNUNET_free (op_name);
1002       GNUNET_free (pref);
1003       return GNUNET_SYSERR;
1004   }
1005   GNUNET_free (pref);
1006   GNUNET_free (op_name);
1007
1008   fprintf (stderr,
1009       "Found operation %s: [%llu:%llu]: %s = %llu\n",
1010       "START_SET_PREFERENCE", o->peer_id, o->address_id,
1011       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
1012
1013   return GNUNET_OK;
1014 }
1015
1016 static int
1017 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1018     struct Episode *e,
1019     int op_counter,
1020     char *sec_name,
1021     const struct GNUNET_CONFIGURATION_Handle *cfg)
1022 {
1023   char *op_name;
1024   char *pref;
1025
1026   /* peer id */
1027   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1028   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1029       sec_name, op_name, &o->peer_id))
1030   {
1031     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1032         op_counter, "STOP_SET_PREFERENCE", op_name);
1033     GNUNET_free (op_name);
1034     return GNUNET_SYSERR;
1035   }
1036   GNUNET_free (op_name);
1037
1038   /* address id */
1039   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1040   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1041       sec_name, op_name, &o->address_id))
1042   {
1043     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1044         op_counter, "STOP_SET_PREFERENCE", op_name);
1045     GNUNET_free (op_name);
1046     return GNUNET_SYSERR;
1047   }
1048   GNUNET_free (op_name);
1049
1050   /* Get preference */
1051   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1052   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1053       sec_name, op_name, &pref))
1054   {
1055     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
1056         op_counter, "STOP_SET_PREFERENCE", op_name);
1057       GNUNET_free (op_name);
1058       return GNUNET_SYSERR;
1059   }
1060
1061   if (0 == (o->pref_type = parse_preference_string(pref)))
1062   {
1063       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1064           op_counter, op_name, e->id);
1065       GNUNET_free (op_name);
1066       GNUNET_free (pref);
1067       return GNUNET_SYSERR;
1068   }
1069   GNUNET_free (pref);
1070   GNUNET_free (op_name);
1071
1072   fprintf (stderr,
1073       "Found operation %s: [%llu:%llu]: %s\n",
1074       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1075       GNUNET_ATS_print_preference_type(o->pref_type));
1076   return GNUNET_OK;
1077 }
1078
1079 static enum GNUNET_ATS_Property
1080 parse_property_string (const char * str)
1081 {
1082   int c = 0;
1083   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
1084
1085   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1086     if (0 == strcmp(str, props[c]))
1087       return c;
1088   return 0;
1089 };
1090
1091 static int
1092 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1093     struct Episode *e,
1094     int op_counter,
1095     char *sec_name,
1096     const struct GNUNET_CONFIGURATION_Handle *cfg)
1097 {
1098   char *op_name;
1099   char *type;
1100   char *prop;
1101
1102   /* peer id */
1103   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1104   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1105       sec_name, op_name, &o->peer_id))
1106   {
1107     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1108         op_counter, "START_SET_PROPERTY", op_name);
1109     GNUNET_free (op_name);
1110     return GNUNET_SYSERR;
1111   }
1112   GNUNET_free (op_name);
1113
1114   /* address id */
1115   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1116   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1117       sec_name, op_name, &o->address_id))
1118   {
1119     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1120         op_counter, "START_SET_PROPERTY", op_name);
1121     GNUNET_free (op_name);
1122     return GNUNET_SYSERR;
1123   }
1124   GNUNET_free (op_name);
1125
1126   /* generator */
1127   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1128   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1129           sec_name, op_name, &type)) )
1130   {
1131     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1132         op_counter, "START_SET_PROPERTY", op_name);
1133     GNUNET_free (op_name);
1134     return GNUNET_SYSERR;
1135   }
1136
1137   /* Load arguments for set_rate, start_send, set_preference */
1138   if (0 == strcmp (type, "constant"))
1139   {
1140     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1141   }
1142   else if (0 == strcmp (type, "linear"))
1143   {
1144     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1145   }
1146   else if (0 == strcmp (type, "sinus"))
1147   {
1148     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1149   }
1150   else if (0 == strcmp (type, "random"))
1151   {
1152     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
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
1317 static int
1318 load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
1319     struct Episode *e,
1320     int op_counter,
1321     char *sec_name,
1322     const struct GNUNET_CONFIGURATION_Handle *cfg)
1323 {
1324   char *op_name;
1325
1326   /* peer id */
1327   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1328   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1329       sec_name, op_name, &o->peer_id))
1330   {
1331     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1332         op_counter, "START_REQUEST", op_name);
1333     GNUNET_free (op_name);
1334     return GNUNET_SYSERR;
1335   }
1336   GNUNET_free (op_name);
1337   return GNUNET_OK;
1338 }
1339
1340 static int
1341 load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
1342     struct Episode *e,
1343     int op_counter,
1344     char *sec_name,
1345     const struct GNUNET_CONFIGURATION_Handle *cfg)
1346 {
1347   char *op_name;
1348
1349   /* peer id */
1350   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1351   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1352       sec_name, op_name, &o->peer_id))
1353   {
1354     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1355         op_counter, "STOP_REQUEST", op_name);
1356     GNUNET_free (op_name);
1357     return GNUNET_SYSERR;
1358   }
1359   GNUNET_free (op_name);
1360   return GNUNET_OK;
1361 }
1362
1363
1364 static int
1365 load_episode (struct Experiment *e, struct Episode *cur,
1366     struct GNUNET_CONFIGURATION_Handle *cfg)
1367 {
1368   struct GNUNET_ATS_TEST_Operation *o;
1369   char *sec_name;
1370   char *op_name;
1371   char *op;
1372   int op_counter = 0;
1373   int res;
1374   fprintf (stderr, "Parsing episode %u\n",cur->id);
1375   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1376
1377   while (1)
1378   {
1379     /* Load operation */
1380     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1381     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1382         sec_name, op_name, &op))
1383     {
1384       GNUNET_free (op_name);
1385       break;
1386     }
1387     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1388     /* operations = set_rate, start_send, stop_send, set_preference */
1389     if (0 == strcmp (op, "address_add"))
1390     {
1391       o->type = SOLVER_OP_ADD_ADDRESS;
1392       res = load_op_add_address (o, cur,
1393           op_counter, sec_name, cfg);
1394     }
1395     else if (0 == strcmp (op, "address_del"))
1396     {
1397       o->type = SOLVER_OP_DEL_ADDRESS;
1398       res = load_op_del_address (o, cur,
1399           op_counter, sec_name, cfg);
1400     }
1401     else if (0 == strcmp (op, "start_set_property"))
1402     {
1403       o->type = SOLVER_OP_START_SET_PROPERTY;
1404       res = load_op_start_set_property (o, cur,
1405           op_counter, sec_name, cfg);
1406     }
1407     else if (0 == strcmp (op, "stop_set_property"))
1408     {
1409       o->type = SOLVER_OP_STOP_SET_PROPERTY;
1410       res = load_op_stop_set_property (o, cur,
1411           op_counter, sec_name, cfg);
1412     }
1413     else if (0 == strcmp (op, "start_set_preference"))
1414     {
1415       o->type = SOLVER_OP_START_SET_PREFERENCE;
1416       res =  load_op_start_set_preference (o, cur,
1417           op_counter, sec_name, cfg);
1418         break;
1419     }
1420     else if (0 == strcmp (op, "stop_set_preference"))
1421     {
1422       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
1423       res =  load_op_stop_set_preference (o, cur,
1424           op_counter, sec_name, cfg);
1425     }
1426     else if (0 == strcmp (op, "start_request"))
1427     {
1428       o->type = SOLVER_OP_START_REQUEST;
1429       res = load_op_start_request (o, cur,
1430           op_counter, sec_name, cfg);
1431     }
1432     else if (0 == strcmp (op, "stop_request"))
1433     {
1434       o->type = SOLVER_OP_STOP_REQUEST;
1435       res = load_op_stop_request(o, cur,
1436           op_counter, sec_name, cfg);
1437     }
1438     else
1439     {
1440       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
1441           op_counter, op, cur->id);
1442       res = GNUNET_SYSERR;
1443     }
1444
1445     GNUNET_free (op);
1446     GNUNET_free (op_name);
1447
1448     if (GNUNET_SYSERR == res)
1449     {
1450       GNUNET_free (o);
1451       GNUNET_free (sec_name);
1452       return GNUNET_SYSERR;
1453     }
1454
1455     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
1456     op_counter++;
1457   }
1458   GNUNET_free (sec_name);
1459
1460
1461 #if 0
1462     /* Get source */
1463     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
1464     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1465         sec_name, op_name, &o->src_id))
1466     {
1467       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1468           op_counter, op, cur->id);
1469       GNUNET_free (op);
1470       GNUNET_free (op_name);
1471       return GNUNET_SYSERR;
1472     }
1473     if (o->src_id > (e->num_masters - 1))
1474     {
1475       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
1476           o->src_id, op_counter, op, cur->id);
1477       GNUNET_free (op);
1478       GNUNET_free (op_name);
1479       return GNUNET_SYSERR;
1480     }
1481     GNUNET_free (op_name);
1482
1483     /* Get destination */
1484     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
1485     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1486         sec_name, op_name, &o->dest_id))
1487     {
1488       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
1489           op_counter, op, cur->id);
1490       GNUNET_free (op);
1491       GNUNET_free (op_name);
1492       return GNUNET_SYSERR;
1493     }
1494     if (o->dest_id > (e->num_slaves - 1))
1495     {
1496       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
1497           o->dest_id, op_counter, op, cur->id);
1498       GNUNET_free (op);
1499       GNUNET_free (op_name);
1500       return GNUNET_SYSERR;
1501     }
1502     GNUNET_free (op_name);
1503
1504     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
1505     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
1506             sec_name, op_name, &type)) &&
1507         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
1508     {
1509       /* Load arguments for set_rate, start_send, set_preference */
1510       if (0 == strcmp (type, "constant"))
1511       {
1512         o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1513       }
1514       else if (0 == strcmp (type, "linear"))
1515       {
1516         o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1517       }
1518       else if (0 == strcmp (type, "sinus"))
1519       {
1520         o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1521       }
1522       else if (0 == strcmp (type, "random"))
1523       {
1524         o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1525       }
1526       else
1527       {
1528         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
1529             op_counter, op, cur->id);
1530         GNUNET_free (type);
1531         GNUNET_free (op);
1532         GNUNET_free (op_name);
1533         return GNUNET_SYSERR;
1534       }
1535       GNUNET_free (op_name);
1536
1537       /* Get base rate */
1538       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1539       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1540           sec_name, op_name, &o->base_rate))
1541       {
1542         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1543             op_counter, op, cur->id);
1544         GNUNET_free (type);
1545         GNUNET_free (op);
1546         GNUNET_free (op_name);
1547         return GNUNET_SYSERR;
1548       }
1549       GNUNET_free (op_name);
1550
1551       /* Get max rate */
1552       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1553       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1554           sec_name, op_name, &o->max_rate))
1555       {
1556         if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1557             (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1558             (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1559         {
1560           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1561               op_counter, op, cur->id);
1562           GNUNET_free (type);
1563           GNUNET_free (op_name);
1564           GNUNET_free (op);
1565           return GNUNET_SYSERR;
1566         }
1567       }
1568       GNUNET_free (op_name);
1569
1570       /* Get period */
1571       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1572       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1573           sec_name, op_name, &o->period))
1574       {
1575         o->period = cur->duration;
1576       }
1577       GNUNET_free (op_name);
1578
1579       if (START_PREFERENCE == o->type)
1580       {
1581           /* Get frequency */
1582           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1583           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1584               sec_name, op_name, &o->frequency))
1585           {
1586               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1587                   op_counter, op, cur->id);
1588               GNUNET_free (type);
1589               GNUNET_free (op_name);
1590               GNUNET_free (op);
1591               return GNUNET_SYSERR;
1592           }
1593           GNUNET_free (op_name);
1594
1595           /* Get preference */
1596           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1597           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1598               sec_name, op_name, &pref))
1599           {
1600               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1601                   op_counter, op, cur->id);
1602               GNUNET_free (type);
1603               GNUNET_free (op_name);
1604               GNUNET_free (op);
1605               GNUNET_free_non_null (pref);
1606               return GNUNET_SYSERR;
1607           }
1608
1609           if (0 == strcmp(pref, "bandwidth"))
1610             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
1611           else if (0 == strcmp(pref, "latency"))
1612             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
1613           else
1614           {
1615               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1616                   op_counter, op, cur->id);
1617               GNUNET_free (type);
1618               GNUNET_free (op_name);
1619               GNUNET_free (op);
1620               GNUNET_free (pref);
1621               GNUNET_free_non_null (pref);
1622               return GNUNET_SYSERR;
1623           }
1624           GNUNET_free (pref);
1625           GNUNET_free (op_name);
1626       }
1627     }
1628
1629     /* Safety checks */
1630     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1631         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1632     {
1633       if ((o->max_rate - o->base_rate) > o->base_rate)
1634       {
1635         /* This will cause an underflow */
1636         GNUNET_break (0);
1637       }
1638       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
1639     }
1640
1641     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
1642       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
1643         op_counter, cur->id, print_op (o->type), o->src_id,
1644         o->dest_id, (NULL != type) ? type : "",
1645         o->base_rate, o->max_rate,
1646         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
1647     else
1648       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
1649         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
1650
1651     GNUNET_free_non_null (type);
1652     GNUNET_free (op);
1653 #endif
1654
1655   return GNUNET_OK;
1656 }
1657
1658 static int
1659 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1660 {
1661   int e_counter = 0;
1662   char *sec_name;
1663   struct GNUNET_TIME_Relative e_duration;
1664   struct Episode *cur;
1665   struct Episode *last;
1666
1667   e_counter = 0;
1668   last = NULL;
1669   while (1)
1670   {
1671     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1672     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1673         sec_name, "duration", &e_duration))
1674     {
1675       GNUNET_free (sec_name);
1676       break;
1677     }
1678
1679     cur = GNUNET_new (struct Episode);
1680     cur->duration = e_duration;
1681     cur->id = e_counter;
1682
1683     if (GNUNET_OK != load_episode (e, cur, cfg))
1684     {
1685       GNUNET_free (sec_name);
1686       GNUNET_free (cur);
1687       return GNUNET_SYSERR;
1688     }
1689
1690     fprintf (stderr, "Found episode %u with duration %s \n",
1691         e_counter,
1692         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1693
1694     /* Update experiment */
1695     e->num_episodes ++;
1696     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1697     /* Put in linked list */
1698     if (NULL == last)
1699       e->start = cur;
1700     else
1701     last->next = cur;
1702
1703     GNUNET_free (sec_name);
1704     e_counter ++;
1705     last = cur;
1706   }
1707   return e_counter;
1708 }
1709
1710 static void
1711 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1712 {
1713   struct Experiment *e = cls;
1714   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1715   fprintf (stderr, "Experiment timeout!\n");
1716
1717   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1718   {
1719     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1720     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1721   }
1722
1723   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
1724       GNUNET_SYSERR);
1725 }
1726
1727 static void
1728 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
1729 {
1730   /*
1731   struct BenchmarkPeer *peer;
1732   struct BenchmarkPartner *partner;
1733
1734   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
1735   if (NULL == peer)
1736   {
1737     GNUNET_break (0);
1738     return;
1739   }
1740
1741   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1742   if (NULL == partner)
1743   {
1744     GNUNET_break (0);
1745     return;
1746   }
1747
1748   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1749
1750   if (NULL != partner->tg)
1751   {
1752     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
1753     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
1754     partner->tg = NULL;
1755   }
1756
1757   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
1758       op->tg_type, op->base_rate, op->max_rate, op->period,
1759       GNUNET_TIME_UNIT_FOREVER_REL);
1760    */
1761 }
1762
1763 static void
1764 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
1765 {
1766   /*
1767   struct BenchmarkPartner *p;
1768   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1769   if (NULL == p)
1770   {
1771     GNUNET_break (0);
1772     return;
1773   }
1774
1775   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1776
1777   if (NULL != p->tg)
1778   {
1779     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
1780         op->src_id, op->dest_id);
1781     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
1782     p->tg = NULL;
1783   }
1784   */
1785 }
1786
1787 static void
1788 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
1789 {
1790   struct PropertyGenerator *pg;
1791   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
1792   {
1793     GNUNET_ATS_solver_generate_property_stop (pg);
1794     GNUNET_free (pg);
1795   }
1796
1797   GNUNET_ATS_solver_generate_property_start (op->peer_id,
1798     op->address_id,
1799     op->gen_type,
1800     op->base_rate,
1801     op->max_rate,
1802     op->period,
1803     op->frequency,
1804     op->prop_type);
1805 }
1806
1807 static void
1808 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
1809 {
1810   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
1811       op->prop_type);
1812   if (NULL != pg)
1813       GNUNET_ATS_solver_generate_property_stop (pg);
1814 }
1815
1816 static void
1817 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
1818 {
1819   struct PreferenceGenerator *pg;
1820   if (NULL != (pg = find_pref_gen (op->peer_id, op->address_id, op->pref_type)))
1821   {
1822     GNUNET_ATS_solver_generate_preferences_stop (pg);
1823     GNUNET_free (pg);
1824   }
1825
1826   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
1827     op->address_id,
1828     op->gen_type,
1829     op->base_rate,
1830     op->max_rate,
1831     op->period,
1832     op->frequency,
1833     op->pref_type);
1834 }
1835
1836 static void
1837 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
1838 {
1839   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id, op->address_id,
1840       op->pref_type);
1841   if (NULL != pg)
1842       GNUNET_ATS_solver_generate_preferences_stop (pg);
1843 }
1844
1845
1846 static void
1847 enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
1848 {
1849   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
1850       op->peer_id);
1851 }
1852
1853 static void
1854 enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
1855 {
1856   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop requesting address for peer %u\n",
1857       op->peer_id);
1858 }
1859
1860 static void enforce_episode (struct Episode *ep)
1861 {
1862   struct GNUNET_ATS_TEST_Operation *cur;
1863   for (cur = ep->head; NULL != cur; cur = cur->next)
1864   {
1865     switch (cur->type) {
1866       case SOLVER_OP_ADD_ADDRESS:
1867         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1868             print_op (cur->type), cur->peer_id, cur->address_id);
1869         enforce_add_address (cur);
1870         break;
1871       case SOLVER_OP_DEL_ADDRESS:
1872         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1873             print_op (cur->type), cur->peer_id, cur->address_id);
1874         enforce_del_address (cur);
1875         break;
1876       case SOLVER_OP_START_SET_PROPERTY:
1877         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1878             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1879         enforce_start_property (cur);
1880         break;
1881       case SOLVER_OP_STOP_SET_PROPERTY:
1882         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1883             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1884         enforce_stop_property (cur);
1885         break;
1886       case SOLVER_OP_START_SET_PREFERENCE:
1887         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1888             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1889         enforce_start_preference (cur);
1890         break;
1891       case SOLVER_OP_STOP_SET_PREFERENCE:
1892         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1893             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1894         enforce_stop_preference (cur);
1895         break;
1896       case SOLVER_OP_START_REQUEST:
1897         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
1898             print_op (cur->type), cur->peer_id);
1899         enforce_start_request (cur);
1900         break;
1901       case SOLVER_OP_STOP_REQUEST:
1902         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
1903             print_op (cur->type), cur->peer_id);
1904         enforce_stop_request (cur);
1905         break;
1906       default:
1907         break;
1908     }
1909   }
1910 }
1911
1912 static void
1913 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1914 {
1915   struct Experiment *e = cls;
1916   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1917   if (NULL != e->ep_done_cb)
1918     e->ep_done_cb (e->cur);
1919
1920   /* Scheduling next */
1921   e->cur = e->cur->next;
1922   if (NULL == e->cur)
1923   {
1924     /* done */
1925     fprintf (stderr, "Last episode done!\n");
1926     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1927     {
1928       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1929       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1930     }
1931     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
1932     return;
1933   }
1934
1935   fprintf (stderr, "Running episode %u with timeout %s\n",
1936       e->cur->id,
1937       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1938   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1939       &timeout_episode, e);
1940   enforce_episode(e->cur);
1941
1942
1943 }
1944
1945
1946 void
1947 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
1948     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
1949     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
1950 {
1951   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
1952       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
1953   e->e_done_cb = e_done_cb;
1954   e->ep_done_cb = ep_done_cb;
1955   e->start_time = GNUNET_TIME_absolute_get();
1956
1957   /* Start total time out */
1958   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
1959       &timeout_experiment, e);
1960
1961
1962   /* Start */
1963   if (NULL == e->start)
1964   {
1965     GNUNET_break (0);
1966     return;
1967   }
1968   e->cur = e->start;
1969   fprintf (stderr, "Running episode %u with timeout %s\n",
1970       e->cur->id,
1971       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1972   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1973       &timeout_episode, e);
1974   enforce_episode(e->cur);
1975
1976 }
1977
1978 void
1979 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
1980 {
1981   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1982   {
1983     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1984     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1985   }
1986   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1987   {
1988     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1989     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1990   }
1991   if (NULL != e->cfg)
1992   {
1993     GNUNET_CONFIGURATION_destroy(e->cfg);
1994     e->cfg = NULL;
1995   }
1996   free_experiment (e);
1997 }
1998
1999
2000 struct Experiment *
2001 GNUNET_ATS_solvers_experimentation_load (char *filename)
2002 {
2003   struct Experiment *e;
2004   struct GNUNET_CONFIGURATION_Handle *cfg;
2005   e = NULL;
2006
2007   cfg = GNUNET_CONFIGURATION_create();
2008   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2009   {
2010     fprintf (stderr, "Failed to load `%s'\n", filename);
2011     GNUNET_CONFIGURATION_destroy (cfg);
2012     return NULL;
2013   }
2014
2015   e = create_experiment ();
2016
2017   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2018       "name", &e->name))
2019   {
2020     fprintf (stderr, "Invalid %s", "name");
2021     free_experiment (e);
2022     return NULL;
2023   }
2024   else
2025     fprintf (stderr, "Experiment name: `%s'\n", e->name);
2026
2027   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2028       "cfg_file", &e->cfg_file))
2029   {
2030     fprintf (stderr, "Invalid %s", "cfg_file");
2031     free_experiment (e);
2032     return NULL;
2033   }
2034   else
2035   {
2036     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
2037     e->cfg = GNUNET_CONFIGURATION_create();
2038     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2039     {
2040       fprintf (stderr, "Invalid configuration %s", "cfg_file");
2041       free_experiment (e);
2042       return NULL;
2043     }
2044
2045   }
2046
2047   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
2048       "masters", &e->num_masters))
2049   {
2050     fprintf (stderr, "Invalid %s", "masters");
2051     free_experiment (e);
2052     return NULL;
2053   }
2054   else
2055     fprintf (stderr, "Experiment masters: `%llu'\n",
2056         e->num_masters);
2057
2058   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
2059       "slaves", &e->num_slaves))
2060   {
2061     fprintf (stderr, "Invalid %s", "slaves");
2062     free_experiment (e);
2063     return NULL;
2064   }
2065   else
2066     fprintf (stderr, "Experiment slaves: `%llu'\n",
2067         e->num_slaves);
2068
2069   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2070       "log_freq", &e->log_freq))
2071   {
2072     fprintf (stderr, "Invalid %s", "log_freq");
2073     free_experiment (e);
2074     return NULL;
2075   }
2076   else
2077     fprintf (stderr, "Experiment logging frequency: `%s'\n",
2078         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2079
2080   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2081       "max_duration", &e->max_duration))
2082   {
2083     fprintf (stderr, "Invalid %s", "max_duration");
2084     free_experiment (e);
2085     return NULL;
2086   }
2087   else
2088     fprintf (stderr, "Experiment duration: `%s'\n",
2089         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2090
2091   if (GNUNET_SYSERR == load_episodes (e, cfg))
2092   {
2093     GNUNET_ATS_solvers_experimentation_stop (e);
2094     GNUNET_CONFIGURATION_destroy (cfg);
2095     e = NULL;
2096     fprintf (stderr, "Failed to load experiment\n");
2097     return NULL;
2098   }
2099   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
2100       e->num_episodes,
2101       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2102
2103   GNUNET_CONFIGURATION_destroy (cfg);
2104   return e;
2105 }
2106
2107 /**
2108  * Solver
2109  */
2110
2111 struct GNUNET_ATS_TESTING_SolverHandle
2112 {
2113   char * plugin;
2114   struct GNUNET_ATS_PluginEnvironment env;
2115   void *solver;
2116   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
2117 };
2118
2119 enum GNUNET_ATS_Solvers
2120 {
2121   GNUNET_ATS_SOLVER_PROPORTIONAL,
2122   GNUNET_ATS_SOLVER_MLP,
2123   GNUNET_ATS_SOLVER_RIL,
2124 };
2125
2126
2127 void
2128 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
2129 {
2130  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2131      GNUNET_NO);
2132  GNUNET_CONTAINER_multipeermap_destroy(sh->env.addresses);
2133  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
2134  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2135  GNUNET_free (sh->plugin);
2136  GNUNET_free (sh);
2137 }
2138
2139 /**
2140  * Load quotas for networks from configuration
2141  *
2142  * @param cfg configuration handle
2143  * @param out_dest where to write outbound quotas
2144  * @param in_dest where to write inbound quotas
2145  * @param dest_length length of inbound and outbound arrays
2146  * @return number of networks loaded
2147  */
2148 unsigned int
2149 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2150                                                  unsigned long long *out_dest,
2151                                                  unsigned long long *in_dest,
2152                                                  int dest_length)
2153 {
2154   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
2155   char * entry_in = NULL;
2156   char * entry_out = NULL;
2157   char * quota_out_str;
2158   char * quota_in_str;
2159   int c;
2160   int res;
2161
2162   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2163   {
2164     in_dest[c] = 0;
2165     out_dest[c] = 0;
2166     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
2167     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
2168
2169     /* quota out */
2170     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2171     {
2172       res = GNUNET_NO;
2173       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2174       {
2175         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2176         res = GNUNET_YES;
2177       }
2178       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2179         res = GNUNET_YES;
2180       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2181          res = GNUNET_YES;
2182
2183       if (GNUNET_NO == res)
2184       {
2185           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2186               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
2187           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2188       }
2189       else
2190       {
2191           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
2192               network_str[c], out_dest[c]);
2193       }
2194       GNUNET_free (quota_out_str);
2195     }
2196     else
2197     {
2198       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2199           network_str[c], GNUNET_ATS_DefaultBandwidth);
2200       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2201     }
2202
2203     /* quota in */
2204     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2205     {
2206       res = GNUNET_NO;
2207       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2208       {
2209         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2210         res = GNUNET_YES;
2211       }
2212       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2213         res = GNUNET_YES;
2214       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2215          res = GNUNET_YES;
2216
2217       if (GNUNET_NO == res)
2218       {
2219           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2220               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
2221           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2222       }
2223       else
2224       {
2225           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
2226               network_str[c], in_dest[c]);
2227       }
2228       GNUNET_free (quota_in_str);
2229     }
2230     else
2231     {
2232       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2233           network_str[c], GNUNET_ATS_DefaultBandwidth);
2234       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2235     }
2236     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]);
2237     GNUNET_free (entry_out);
2238     GNUNET_free (entry_in);
2239   }
2240   return GNUNET_ATS_NetworkTypeCount;
2241 }
2242
2243 /**
2244  * Information callback for the solver
2245  *
2246  * @param op the solver operation
2247  * @param stat status of the solver operation
2248  * @param add additional solver information
2249  */
2250 static void
2251 solver_info_cb (void *cls,
2252     enum GAS_Solver_Operation op,
2253     enum GAS_Solver_Status stat,
2254     enum GAS_Solver_Additional_Information add)
2255 {
2256   char *add_info;
2257   switch (add) {
2258     case GAS_INFO_NONE:
2259       add_info = "GAS_INFO_NONE";
2260       break;
2261     case GAS_INFO_FULL:
2262       add_info = "GAS_INFO_MLP_FULL";
2263       break;
2264     case GAS_INFO_UPDATED:
2265       add_info = "GAS_INFO_MLP_UPDATED";
2266       break;
2267     case GAS_INFO_PROP_ALL:
2268       add_info = "GAS_INFO_PROP_ALL";
2269       break;
2270     case GAS_INFO_PROP_SINGLE:
2271       add_info = "GAS_INFO_PROP_SINGLE";
2272       break;
2273     default:
2274       add_info = "INVALID";
2275       break;
2276   }
2277
2278   switch (op)
2279   {
2280     case GAS_OP_SOLVE_START:
2281       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2282           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2283           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2284       return;
2285     case GAS_OP_SOLVE_STOP:
2286       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2287           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2288           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2289       return;
2290
2291     case GAS_OP_SOLVE_SETUP_START:
2292       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2293           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2294           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2295       return;
2296
2297     case GAS_OP_SOLVE_SETUP_STOP:
2298       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2299           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2300           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2301       return;
2302
2303     case GAS_OP_SOLVE_MLP_LP_START:
2304       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2305           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2306           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2307       return;
2308     case GAS_OP_SOLVE_MLP_LP_STOP:
2309       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2310           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2311           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2312       return;
2313
2314     case GAS_OP_SOLVE_MLP_MLP_START:
2315       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2316           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2317           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2318       return;
2319     case GAS_OP_SOLVE_MLP_MLP_STOP:
2320       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2321           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2322           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2323       return;
2324     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2325       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2326           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2327           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2328       return;
2329     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2330       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2331           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2332           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2333       return;
2334     default:
2335       break;
2336     }
2337 }
2338
2339 static void
2340 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2341 {
2342   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
2343        (0 == ntohl (address->assigned_bw_in.value__)) )
2344     return;
2345
2346   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2347               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2348               GNUNET_i2s (&address->peer),
2349               address,
2350               (unsigned int) ntohl (address->assigned_bw_out.value__),
2351               (unsigned int) ntohl (address->assigned_bw_in.value__));
2352   /*if (GNUNET_YES == ph.bulk_running)
2353     GNUNET_break (0);*/
2354   return;
2355 }
2356
2357 const double *
2358 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
2359 {
2360   return GAS_normalization_get_preferences_by_peer (id);
2361 }
2362
2363
2364 const double *
2365 get_property_cb (void *cls, const struct ATS_Address *address)
2366 {
2367   return GAS_normalization_get_properties ((struct ATS_Address *) address);
2368 }
2369
2370 static void
2371 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
2372     uint32_t type, double prop_rel)
2373 {
2374   /* TODO */
2375 }
2376
2377
2378 struct GNUNET_ATS_TESTING_SolverHandle *
2379 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
2380 {
2381   struct GNUNET_ATS_TESTING_SolverHandle *sh;
2382   char * solver_str;
2383   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
2384   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
2385
2386   switch (type) {
2387     case GNUNET_ATS_SOLVER_PROPORTIONAL:
2388       solver_str = "proportional";
2389       break;
2390     case GNUNET_ATS_SOLVER_MLP:
2391       solver_str = "mlp";
2392       break;
2393     case GNUNET_ATS_SOLVER_RIL:
2394       solver_str = "ril";
2395       break;
2396     default:
2397       GNUNET_break (0);
2398       return NULL;
2399       break;
2400   }
2401
2402   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
2403   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
2404
2405   /* setup environment */
2406   sh->env.cfg = e->cfg;
2407   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
2408   sh->env.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
2409   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
2410   sh->env.get_preferences = &get_preferences_cb;
2411   sh->env.get_property = &get_property_cb;
2412   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
2413   sh->env.info_cb = &solver_info_cb;
2414   sh->env.info_cb_cls = NULL;
2415
2416   /* start normalization */
2417   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
2418
2419   /* load quotas */
2420   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
2421       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
2422   {
2423     GNUNET_break(0);
2424     GNUNET_free (sh->plugin);
2425     GNUNET_free (sh);
2426     end_now ();
2427     return NULL;
2428   }
2429
2430   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
2431   if (NULL == sh->solver)
2432   {
2433     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
2434     GNUNET_break(0);
2435     GNUNET_free (sh->plugin);
2436     GNUNET_free (sh);
2437     end_now ();
2438     return NULL;
2439   }
2440
2441   sh->addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
2442
2443   return sh;
2444 }
2445
2446 static void
2447 done ()
2448 {
2449   /* Clean up experiment */
2450   GNUNET_ATS_solver_generate_preferences_stop_all ();
2451
2452   if (NULL != e)
2453   {
2454     GNUNET_ATS_solvers_experimentation_stop (e);
2455     e = NULL;
2456   }
2457
2458   if (NULL != l)
2459   {
2460     GNUNET_ATS_solver_logging_free (l);
2461     l = NULL;
2462   }
2463
2464   /* Shutdown */
2465   end_now();
2466
2467 }
2468
2469 static void
2470 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
2471 {
2472   if (GNUNET_OK == success)
2473     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
2474         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
2475   else
2476     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
2477
2478   /* Stop logging */
2479   GNUNET_ATS_solver_logging_stop (l);
2480
2481   /* Stop traffic generation */
2482   // GNUNET_ATS_TEST_generate_traffic_stop_all();
2483
2484   /* Stop all preference generations */
2485   GNUNET_ATS_solver_generate_preferences_stop_all ();
2486
2487   /*
2488   evaluate (duration);
2489   if (opt_log)
2490     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
2491
2492   if (NULL != l)
2493   {
2494     GNUNET_ATS_TEST_logging_stop (l);
2495     GNUNET_ATS_TEST_logging_clean_up (l);
2496     l = NULL;
2497   }
2498   */
2499   GNUNET_SCHEDULER_add_now (&done, NULL);
2500 }
2501
2502 static void
2503 episode_done_cb (struct Episode *ep)
2504 {
2505   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
2506 }
2507
2508
2509
2510 /**
2511  * Do shutdown
2512  */
2513 static void
2514 end_now ()
2515 {
2516   if (NULL != e)
2517   {
2518     GNUNET_ATS_solvers_experimentation_stop (e);
2519     e = NULL;
2520   }
2521   if (NULL != sh)
2522   {
2523     GNUNET_ATS_solvers_solver_stop (sh);
2524     sh = NULL;
2525   }
2526 }
2527
2528 static void
2529 run (void *cls, char * const *args, const char *cfgfile,
2530     const struct GNUNET_CONFIGURATION_Handle *cfg)
2531 {
2532   enum GNUNET_ATS_Solvers solver;
2533
2534   if (NULL == opt_exp_file)
2535   {
2536     fprintf (stderr, "No experiment given ...\n");
2537     res = 1;
2538     end_now ();
2539     return;
2540   }
2541
2542   if (NULL == opt_solver)
2543   {
2544     fprintf (stderr, "No solver given ...\n");
2545     res = 1;
2546     end_now ();
2547     return;
2548   }
2549
2550   if (0 == strcmp(opt_solver, "mlp"))
2551   {
2552     solver = GNUNET_ATS_SOLVER_MLP;
2553   }
2554   else if (0 == strcmp(opt_solver, "proportional"))
2555   {
2556     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
2557   }
2558   else if (0 == strcmp(opt_solver, "ril"))
2559   {
2560     solver = GNUNET_ATS_SOLVER_RIL;
2561   }
2562   else
2563   {
2564     fprintf (stderr, "No solver given ...");
2565     res = 1;
2566     end_now ();
2567     return;
2568   }
2569
2570   /* load experiment */
2571   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
2572   if (NULL == e)
2573   {
2574     fprintf (stderr, "Failed to load experiment ...\n");
2575     res = 1;
2576     end_now ();
2577     return;
2578   }
2579
2580   /* load solver */
2581   sh = GNUNET_ATS_solvers_solver_start (solver);
2582   if (NULL == sh)
2583   {
2584     fprintf (stderr, "Failed to start solver ...\n");
2585     end_now ();
2586     res = 1;
2587     return;
2588   }
2589
2590   /* start logging */
2591   l = GNUNET_ATS_solver_logging_start (e->log_freq);
2592
2593   /* run experiment */
2594   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
2595       experiment_done_cb);
2596
2597   /* WAIT */
2598 }
2599
2600
2601 /**
2602  * Main function of the benchmark
2603  *
2604  * @param argc argument count
2605  * @param argv argument values
2606  */
2607 int
2608 main (int argc, char *argv[])
2609 {
2610   opt_exp_file = NULL;
2611   opt_solver = NULL;
2612   opt_log = GNUNET_NO;
2613   opt_plot = GNUNET_NO;
2614
2615   res = 0;
2616
2617   static struct GNUNET_GETOPT_CommandLineOption options[] =
2618   {
2619     { 's', "solver", NULL,
2620         gettext_noop ("solver to use"),
2621         1, &GNUNET_GETOPT_set_string, &opt_solver},
2622     {  'e', "experiment", NULL,
2623       gettext_noop ("experiment to use"),
2624       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
2625     {  'e', "experiment", NULL,
2626       gettext_noop ("experiment to use"),
2627       1, &GNUNET_GETOPT_set_one, &opt_verbose},
2628     GNUNET_GETOPT_OPTION_END
2629   };
2630
2631   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
2632       NULL, options, &run, argv[0]);
2633
2634   return res;
2635 }
2636 /* end of file ats-testing-experiment.c*/
2637