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