example experiment
[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 GNUNET_ATS_TESTING_SolverHandle *sh;
36
37 /**
38  * cmd option -e: experiment file
39  */
40 static char *opt_exp_file;
41
42 static char *opt_solver;
43
44 /**
45  * cmd option -l: enable logging
46  */
47 static int opt_log;
48
49 /**
50  * cmd option -p: enable plots
51  */
52 static int opt_plot;
53
54 /**
55  * cmd option -v: verbose logs
56  */
57 static int opt_verbose;
58
59 static int res;
60
61 static void
62 end_now ();
63
64 /**
65  * Experiments
66  */
67
68 const char *
69 print_op (enum OperationType op)
70 {
71   switch (op) {
72     case SOLVER_OP_ADD_ADDRESS:
73       return "ADD_ADDRESS";
74     case SOLVER_OP_DEL_ADDRESS:
75       return "DEL_ADDRESS";
76     case SOLVER_OP_START_SET_PREFERENCE:
77       return "START_SET_PREFERENCE";
78     case SOLVER_OP_STOP_SET_PREFERENCE:
79       return "STOP_STOP_PREFERENCE";
80     case SOLVER_OP_START_SET_PROPERTY:
81           return "START_SET_PROPERTY";
82     case SOLVER_OP_STOP_SET_PROPERTY:
83       return "STOP_SET_PROPERTY";
84     default:
85       break;
86   }
87   return "";
88 }
89
90
91 static struct Experiment *
92 create_experiment ()
93 {
94   struct Experiment *e;
95   e = GNUNET_new (struct Experiment);
96   e->name = NULL;
97   e->num_masters = 0;
98   e->num_slaves = 0;
99   e->start = NULL;
100   e->total_duration = GNUNET_TIME_UNIT_ZERO;
101   return e;
102 }
103
104 static void
105 free_experiment (struct Experiment *e)
106 {
107   struct Episode *cur;
108   struct Episode *next;
109   struct GNUNET_ATS_TEST_Operation *cur_o;
110   struct GNUNET_ATS_TEST_Operation *next_o;
111
112   next = e->start;
113   for (cur = next; NULL != cur; cur = next)
114   {
115     next = cur->next;
116
117     next_o = cur->head;
118     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
119     {
120       next_o = cur_o->next;
121       GNUNET_free_non_null (cur_o->address);
122       GNUNET_free_non_null (cur_o->plugin);
123       GNUNET_free (cur_o);
124     }
125     GNUNET_free (cur);
126   }
127
128   GNUNET_free_non_null (e->name);
129   GNUNET_free_non_null (e->cfg_file);
130   GNUNET_free (e);
131 }
132
133
134 static int
135 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
136     struct Episode *e,
137     int op_counter,
138     char *sec_name,
139     const struct GNUNET_CONFIGURATION_Handle *cfg)
140 {
141   char *op_name;
142
143   /* peer id */
144   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
145   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
146       sec_name, op_name, &o->peer_id))
147   {
148     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
149         op_counter, "ADD_ADDRESS", op_name);
150     GNUNET_free (op_name);
151     return GNUNET_SYSERR;
152   }
153   GNUNET_free (op_name);
154
155   /* address id */
156   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
157   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
158       sec_name, op_name, &o->address_id))
159   {
160     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
161         op_counter, "ADD_ADDRESS", op_name);
162     GNUNET_free (op_name);
163     return GNUNET_SYSERR;
164   }
165   GNUNET_free (op_name);
166
167   /* plugin */
168   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
169   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
170       sec_name, op_name, &o->plugin))
171   {
172     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
173         op_counter, "ADD_ADDRESS", op_name);
174     GNUNET_free (op_name);
175     return GNUNET_SYSERR;
176   }
177   GNUNET_free (op_name);
178
179   /* address  */
180   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
181   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
182       sec_name, op_name, &o->address))
183   {
184     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
185         op_counter, "ADD_ADDRESS", op_name);
186     GNUNET_free (op_name);
187     return GNUNET_SYSERR;
188   }
189   GNUNET_free (op_name);
190
191   /* session */
192   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
193   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
194       sec_name, op_name, &o->address_session))
195   {
196     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
197         op_counter, "ADD_ADDRESS", op_name);
198     GNUNET_free (op_name);
199     return GNUNET_SYSERR;
200   }
201   GNUNET_free (op_name);
202
203   /* network */
204   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
205   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
206       sec_name, op_name, &o->address_network))
207   {
208     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
209         op_counter, "ADD_ADDRESS", op_name);
210     GNUNET_free (op_name);
211     return GNUNET_SYSERR;
212   }
213   GNUNET_free (op_name);
214
215   fprintf (stderr,
216       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
217       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
218
219   return GNUNET_OK;
220 }
221
222 static int
223 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
224     struct Episode *e,
225     int op_counter,
226     char *sec_name,
227     const struct GNUNET_CONFIGURATION_Handle *cfg)
228 {
229   char *op_name;
230
231   /* peer id */
232   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
233   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
234       sec_name, op_name, &o->peer_id))
235   {
236     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
237         op_counter, "DEL_ADDRESS", op_name);
238     GNUNET_free (op_name);
239     return GNUNET_SYSERR;
240   }
241   GNUNET_free (op_name);
242
243   /* address id */
244   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
245   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
246       sec_name, op_name, &o->address_id))
247   {
248     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
249         op_counter, "DEL_ADDRESS", op_name);
250     GNUNET_free (op_name);
251     return GNUNET_SYSERR;
252   }
253   GNUNET_free (op_name);
254
255   /* plugin */
256   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
257   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
258       sec_name, op_name, &o->plugin))
259   {
260     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
261         op_counter, "DEL_ADDRESS", op_name);
262     GNUNET_free (op_name);
263     return GNUNET_SYSERR;
264   }
265   GNUNET_free (op_name);
266
267   /* address  */
268   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
269   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
270       sec_name, op_name, &o->address))
271   {
272     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
273         op_counter, "DEL_ADDRESS", op_name);
274     GNUNET_free (op_name);
275     return GNUNET_SYSERR;
276   }
277   GNUNET_free (op_name);
278
279   /* session */
280   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
281   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
282       sec_name, op_name, &o->address_session))
283   {
284     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
285         op_counter, "DEL_ADDRESS", op_name);
286     GNUNET_free (op_name);
287     return GNUNET_SYSERR;
288   }
289   GNUNET_free (op_name);
290
291   /* network */
292   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
293   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
294       sec_name, op_name, &o->address_network))
295   {
296     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
297         op_counter, "DEL_ADDRESS", op_name);
298     GNUNET_free (op_name);
299     return GNUNET_SYSERR;
300   }
301   GNUNET_free (op_name);
302
303   fprintf (stderr,
304       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
305       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
306
307   return GNUNET_OK;
308 }
309
310 static enum GNUNET_ATS_Property
311 parse_preference_string (const char * str)
312 {
313   int c = 0;
314   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
315
316   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
317     if (0 == strcmp(str, props[c]))
318       return c;
319   return 0;
320 };
321
322 static int
323 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
324     struct Episode *e,
325     int op_counter,
326     char *sec_name,
327     const struct GNUNET_CONFIGURATION_Handle *cfg)
328 {
329   char *op_name;
330   char *type;
331   char *pref;
332
333   /* peer id */
334   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
335   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
336       sec_name, op_name, &o->peer_id))
337   {
338     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
339         op_counter, "START_SET_PREFERENCE", op_name);
340     GNUNET_free (op_name);
341     return GNUNET_SYSERR;
342   }
343   GNUNET_free (op_name);
344
345   /* address id */
346   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
347   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
348       sec_name, op_name, &o->address_id))
349   {
350     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
351         op_counter, "START_SET_PREFERENCE", op_name);
352     GNUNET_free (op_name);
353     return GNUNET_SYSERR;
354   }
355   GNUNET_free (op_name);
356
357   /* generator */
358   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
359   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
360           sec_name, op_name, &type)) )
361   {
362     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
363         op_counter, "START_SET_PREFERENCE", op_name);
364     GNUNET_free (op_name);
365     return GNUNET_SYSERR;
366   }
367
368   /* Load arguments for set_rate, start_send, set_preference */
369   if (0 == strcmp (type, "constant"))
370   {
371     o->tg_type = GNUNET_ATS_TEST_TG_CONSTANT;
372   }
373   else if (0 == strcmp (type, "linear"))
374   {
375     o->tg_type = GNUNET_ATS_TEST_TG_LINEAR;
376   }
377   else if (0 == strcmp (type, "sinus"))
378   {
379     o->tg_type = GNUNET_ATS_TEST_TG_SINUS;
380   }
381   else if (0 == strcmp (type, "random"))
382   {
383     o->tg_type = GNUNET_ATS_TEST_TG_RANDOM;
384   }
385   else
386   {
387     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
388         op_counter, op_name, e->id);
389     GNUNET_free (type);
390     GNUNET_free (op_name);
391     return GNUNET_SYSERR;
392   }
393   GNUNET_free (type);
394   GNUNET_free (op_name);
395
396
397   /* Get base rate */
398   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
399   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
400       sec_name, op_name, &o->base_rate))
401   {
402     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
403         op_counter, op_name, e->id);
404     GNUNET_free (op_name);
405     return GNUNET_SYSERR;
406   }
407   GNUNET_free (op_name);
408
409
410   /* Get max rate */
411   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
412   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
413       sec_name, op_name, &o->max_rate))
414   {
415     if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
416         (GNUNET_ATS_TEST_TG_RANDOM == o->tg_type) ||
417         (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
418     {
419       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
420           op_counter, op_name, e->id);
421       GNUNET_free (op_name);
422       return GNUNET_SYSERR;
423     }
424   }
425   GNUNET_free (op_name);
426
427   /* Get period */
428   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
429   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
430       sec_name, op_name, &o->period))
431   {
432     o->period = e->duration;
433   }
434   GNUNET_free (op_name);
435
436   /* Get frequency */
437   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
438   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
439       sec_name, op_name, &o->frequency))
440   {
441       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
442           op_counter, op_name, e->id);
443       GNUNET_free (op_name);
444       return GNUNET_SYSERR;
445   }
446   GNUNET_free (op_name);
447
448   /* Get preference */
449   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
450   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
451       sec_name, op_name, &pref))
452   {
453       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
454           op_counter, op_name, e->id);
455       GNUNET_free (op_name);
456       return GNUNET_SYSERR;
457   }
458
459   if (0 == (o->pref_type = parse_preference_string(pref)))
460   {
461       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
462           op_counter, op_name, e->id);
463       GNUNET_free (op_name);
464       GNUNET_free (pref);
465       return GNUNET_SYSERR;
466   }
467   GNUNET_free (pref);
468   GNUNET_free (op_name);
469
470   fprintf (stderr,
471       "Found operation %s: [%llu:%llu]: %s = %llu\n",
472       "START_SET_PREFERENCE", o->peer_id, o->address_id,
473       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
474
475   return GNUNET_OK;
476 }
477
478 static int
479 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
480     struct Episode *e,
481     int op_counter,
482     char *sec_name,
483     const struct GNUNET_CONFIGURATION_Handle *cfg)
484 {
485   char *op_name;
486   char *pref;
487
488   /* peer id */
489   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
490   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
491       sec_name, op_name, &o->peer_id))
492   {
493     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
494         op_counter, "STOP_SET_PREFERENCE", op_name);
495     GNUNET_free (op_name);
496     return GNUNET_SYSERR;
497   }
498   GNUNET_free (op_name);
499
500   /* address id */
501   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
502   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
503       sec_name, op_name, &o->address_id))
504   {
505     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
506         op_counter, "STOP_SET_PREFERENCE", op_name);
507     GNUNET_free (op_name);
508     return GNUNET_SYSERR;
509   }
510   GNUNET_free (op_name);
511
512   /* Get preference */
513   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
514   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
515       sec_name, op_name, &pref))
516   {
517     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
518         op_counter, "STOP_SET_PREFERENCE", op_name);
519       GNUNET_free (op_name);
520       return GNUNET_SYSERR;
521   }
522
523   if (0 == (o->pref_type = parse_preference_string(pref)))
524   {
525       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
526           op_counter, op_name, e->id);
527       GNUNET_free (op_name);
528       GNUNET_free (pref);
529       return GNUNET_SYSERR;
530   }
531   GNUNET_free (pref);
532   GNUNET_free (op_name);
533
534   fprintf (stderr,
535       "Found operation %s: [%llu:%llu]: %s\n",
536       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
537       GNUNET_ATS_print_preference_type(o->pref_type));
538   return GNUNET_OK;
539 }
540
541 static enum GNUNET_ATS_Property
542 parse_property_string (const char * str)
543 {
544   int c = 0;
545   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
546
547   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
548     if (0 == strcmp(str, props[c]))
549       return c;
550   return 0;
551 };
552
553 static int
554 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
555     struct Episode *e,
556     int op_counter,
557     char *sec_name,
558     const struct GNUNET_CONFIGURATION_Handle *cfg)
559 {
560   char *op_name;
561   char *type;
562   char *prop;
563
564   /* peer id */
565   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
566   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
567       sec_name, op_name, &o->peer_id))
568   {
569     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
570         op_counter, "START_SET_PROPERTY", op_name);
571     GNUNET_free (op_name);
572     return GNUNET_SYSERR;
573   }
574   GNUNET_free (op_name);
575
576   /* address id */
577   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
578   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
579       sec_name, op_name, &o->address_id))
580   {
581     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
582         op_counter, "START_SET_PROPERTY", op_name);
583     GNUNET_free (op_name);
584     return GNUNET_SYSERR;
585   }
586   GNUNET_free (op_name);
587
588   /* generator */
589   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
590   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
591           sec_name, op_name, &type)) )
592   {
593     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
594         op_counter, "START_SET_PROPERTY", op_name);
595     GNUNET_free (op_name);
596     return GNUNET_SYSERR;
597   }
598
599   /* Load arguments for set_rate, start_send, set_preference */
600   if (0 == strcmp (type, "constant"))
601   {
602     o->tg_type = GNUNET_ATS_TEST_TG_CONSTANT;
603   }
604   else if (0 == strcmp (type, "linear"))
605   {
606     o->tg_type = GNUNET_ATS_TEST_TG_LINEAR;
607   }
608   else if (0 == strcmp (type, "sinus"))
609   {
610     o->tg_type = GNUNET_ATS_TEST_TG_SINUS;
611   }
612   else if (0 == strcmp (type, "random"))
613   {
614     o->tg_type = GNUNET_ATS_TEST_TG_RANDOM;
615   }
616   else
617   {
618     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
619         op_counter, op_name, e->id);
620     GNUNET_free (type);
621     GNUNET_free (op_name);
622     return GNUNET_SYSERR;
623   }
624   GNUNET_free (type);
625   GNUNET_free (op_name);
626
627
628   /* Get base rate */
629   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
630   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
631       sec_name, op_name, &o->base_rate))
632   {
633     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
634         op_counter, op_name, e->id);
635     GNUNET_free (op_name);
636     return GNUNET_SYSERR;
637   }
638   GNUNET_free (op_name);
639
640
641   /* Get max rate */
642   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
643   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
644       sec_name, op_name, &o->max_rate))
645   {
646     if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
647         (GNUNET_ATS_TEST_TG_RANDOM == o->tg_type) ||
648         (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
649     {
650       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
651           op_counter, op_name, e->id);
652       GNUNET_free (op_name);
653       return GNUNET_SYSERR;
654     }
655   }
656   GNUNET_free (op_name);
657
658   /* Get period */
659   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
660   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
661       sec_name, op_name, &o->period))
662   {
663     o->period = e->duration;
664   }
665   GNUNET_free (op_name);
666
667   /* Get frequency */
668   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
669   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
670       sec_name, op_name, &o->frequency))
671   {
672       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
673           op_counter, op_name, e->id);
674       GNUNET_free (op_name);
675       return GNUNET_SYSERR;
676   }
677   GNUNET_free (op_name);
678
679   /* Get preference */
680   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
681   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
682       sec_name, op_name, &prop))
683   {
684       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
685           op_counter, op_name, e->id);
686       GNUNET_free (op_name);
687       GNUNET_free_non_null (prop);
688       return GNUNET_SYSERR;
689   }
690
691   if (0 == (o->prop_type = parse_property_string(prop)))
692   {
693       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
694           op_counter, op_name, e->id);
695       GNUNET_free (op_name);
696       GNUNET_free (prop);
697       return GNUNET_SYSERR;
698   }
699
700   GNUNET_free (prop);
701   GNUNET_free (op_name);
702
703   fprintf (stderr,
704       "Found operation %s: [%llu:%llu] %s = %llu\n",
705       "START_SET_PROPERTY", o->peer_id, o->address_id,
706       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
707
708   return GNUNET_OK;
709 }
710
711 static int
712 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
713     struct Episode *e,
714     int op_counter,
715     char *sec_name,
716     const struct GNUNET_CONFIGURATION_Handle *cfg)
717 {
718   char *op_name;
719   char *pref;
720
721   /* peer id */
722   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
723   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
724       sec_name, op_name, &o->peer_id))
725   {
726     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
727         op_counter, "STOP_SET_PROPERTY", op_name);
728     GNUNET_free (op_name);
729     return GNUNET_SYSERR;
730   }
731   GNUNET_free (op_name);
732
733   /* address id */
734   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
735   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
736       sec_name, op_name, &o->address_id))
737   {
738     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
739         op_counter, "STOP_SET_PROPERTY", op_name);
740     GNUNET_free (op_name);
741     return GNUNET_SYSERR;
742   }
743   GNUNET_free (op_name);
744
745   /* Get property */
746   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
747   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
748       sec_name, op_name, &pref))
749   {
750     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
751         op_counter, "STOP_SET_PROPERTY", op_name);
752       GNUNET_free (op_name);
753       GNUNET_free_non_null (pref);
754       return GNUNET_SYSERR;
755   }
756
757   if (0 == (o->prop_type = parse_property_string(pref)))
758   {
759       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
760           op_counter, op_name, e->id);
761       GNUNET_free (op_name);
762       GNUNET_free (pref);
763       GNUNET_free_non_null (pref);
764       return GNUNET_SYSERR;
765   }
766
767   GNUNET_free (pref);
768   GNUNET_free (op_name);
769
770   fprintf (stderr,
771       "Found operation %s: [%llu:%llu] %s\n",
772       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
773       GNUNET_ATS_print_property_type (o->prop_type));
774
775   return GNUNET_OK;
776 }
777
778 static int
779 load_episode (struct Experiment *e, struct Episode *cur,
780     struct GNUNET_CONFIGURATION_Handle *cfg)
781 {
782   struct GNUNET_ATS_TEST_Operation *o;
783   char *sec_name;
784   char *op_name;
785   char *op;
786   int op_counter = 0;
787   fprintf (stderr, "Parsing episode %u\n",cur->id);
788   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
789
790   while (1)
791   {
792     /* Load operation */
793     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
794     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
795         sec_name, op_name, &op))
796     {
797       GNUNET_free (op_name);
798       break;
799     }
800     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
801     /* operations = set_rate, start_send, stop_send, set_preference */
802     if (0 == strcmp (op, "address_add"))
803     {
804       o->type = SOLVER_OP_ADD_ADDRESS;
805       if (GNUNET_SYSERR == load_op_add_address (o, cur,
806           op_counter, sec_name, cfg))
807       {
808         GNUNET_free (o);
809         GNUNET_free (op);
810         GNUNET_free (op_name);
811         GNUNET_free (sec_name);
812         return GNUNET_SYSERR;
813       }
814     }
815     else if (0 == strcmp (op, "address_del"))
816     {
817       o->type = SOLVER_OP_DEL_ADDRESS;
818       if (GNUNET_SYSERR == load_op_del_address (o, cur,
819           op_counter, sec_name, cfg))
820       {
821         GNUNET_free (o);
822         GNUNET_free (op);
823         GNUNET_free (op_name);
824         GNUNET_free (sec_name);
825         return GNUNET_SYSERR;
826       }
827     }
828     else if (0 == strcmp (op, "start_set_property"))
829     {
830       o->type = SOLVER_OP_START_SET_PROPERTY;
831       if (GNUNET_SYSERR == load_op_start_set_property (o, cur,
832           op_counter, sec_name, cfg))
833       {
834         GNUNET_free (o);
835         GNUNET_free (op);
836         GNUNET_free (op_name);
837         GNUNET_free (sec_name);
838         return GNUNET_SYSERR;
839       }
840     }
841     else if (0 == strcmp (op, "stop_set_property"))
842     {
843       o->type = SOLVER_OP_STOP_SET_PROPERTY;
844       if (GNUNET_SYSERR == load_op_stop_set_property (o, cur,
845           op_counter, sec_name, cfg))
846       {
847         GNUNET_free (o);
848         GNUNET_free (op);
849         GNUNET_free (op_name);
850         GNUNET_free (sec_name);
851         return GNUNET_SYSERR;
852       }
853     }
854     else if (0 == strcmp (op, "start_set_preference"))
855     {
856       o->type = SOLVER_OP_START_SET_PREFERENCE;
857       if (GNUNET_SYSERR == load_op_start_set_preference (o, cur,
858           op_counter, sec_name, cfg))
859       {
860         GNUNET_free (o);
861         GNUNET_free (op);
862         GNUNET_free (op_name);
863         GNUNET_free (sec_name);
864         return GNUNET_SYSERR;
865       }
866     }
867     else if (0 == strcmp (op, "stop_set_preference"))
868     {
869       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
870       if (GNUNET_SYSERR == load_op_stop_set_preference (o, cur,
871           op_counter, sec_name, cfg))
872       {
873         GNUNET_free (o);
874         GNUNET_free (op);
875         GNUNET_free (op_name);
876         GNUNET_free (sec_name);
877         return GNUNET_SYSERR;
878       }
879     }
880     else
881     {
882       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
883           op_counter, op, cur->id);
884       GNUNET_free (o);
885       GNUNET_free (op);
886       GNUNET_free (op_name);
887       GNUNET_free (sec_name);
888       return GNUNET_SYSERR;
889     }
890     GNUNET_free (op);
891     GNUNET_free (op_name);
892
893     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
894     op_counter++;
895   }
896   GNUNET_free (sec_name);
897
898
899 #if 0
900     /* Get source */
901     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
902     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
903         sec_name, op_name, &o->src_id))
904     {
905       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
906           op_counter, op, cur->id);
907       GNUNET_free (op);
908       GNUNET_free (op_name);
909       return GNUNET_SYSERR;
910     }
911     if (o->src_id > (e->num_masters - 1))
912     {
913       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
914           o->src_id, op_counter, op, cur->id);
915       GNUNET_free (op);
916       GNUNET_free (op_name);
917       return GNUNET_SYSERR;
918     }
919     GNUNET_free (op_name);
920
921     /* Get destination */
922     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
923     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
924         sec_name, op_name, &o->dest_id))
925     {
926       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
927           op_counter, op, cur->id);
928       GNUNET_free (op);
929       GNUNET_free (op_name);
930       return GNUNET_SYSERR;
931     }
932     if (o->dest_id > (e->num_slaves - 1))
933     {
934       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
935           o->dest_id, op_counter, op, cur->id);
936       GNUNET_free (op);
937       GNUNET_free (op_name);
938       return GNUNET_SYSERR;
939     }
940     GNUNET_free (op_name);
941
942     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
943     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
944             sec_name, op_name, &type)) &&
945         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
946     {
947       /* Load arguments for set_rate, start_send, set_preference */
948       if (0 == strcmp (type, "constant"))
949       {
950         o->tg_type = GNUNET_ATS_TEST_TG_CONSTANT;
951       }
952       else if (0 == strcmp (type, "linear"))
953       {
954         o->tg_type = GNUNET_ATS_TEST_TG_LINEAR;
955       }
956       else if (0 == strcmp (type, "sinus"))
957       {
958         o->tg_type = GNUNET_ATS_TEST_TG_SINUS;
959       }
960       else if (0 == strcmp (type, "random"))
961       {
962         o->tg_type = GNUNET_ATS_TEST_TG_RANDOM;
963       }
964       else
965       {
966         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
967             op_counter, op, cur->id);
968         GNUNET_free (type);
969         GNUNET_free (op);
970         GNUNET_free (op_name);
971         return GNUNET_SYSERR;
972       }
973       GNUNET_free (op_name);
974
975       /* Get base rate */
976       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
977       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
978           sec_name, op_name, &o->base_rate))
979       {
980         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
981             op_counter, op, cur->id);
982         GNUNET_free (type);
983         GNUNET_free (op);
984         GNUNET_free (op_name);
985         return GNUNET_SYSERR;
986       }
987       GNUNET_free (op_name);
988
989       /* Get max rate */
990       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
991       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
992           sec_name, op_name, &o->max_rate))
993       {
994         if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
995             (GNUNET_ATS_TEST_TG_RANDOM == o->tg_type) ||
996             (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
997         {
998           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
999               op_counter, op, cur->id);
1000           GNUNET_free (type);
1001           GNUNET_free (op_name);
1002           GNUNET_free (op);
1003           return GNUNET_SYSERR;
1004         }
1005       }
1006       GNUNET_free (op_name);
1007
1008       /* Get period */
1009       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1010       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1011           sec_name, op_name, &o->period))
1012       {
1013         o->period = cur->duration;
1014       }
1015       GNUNET_free (op_name);
1016
1017       if (START_PREFERENCE == o->type)
1018       {
1019           /* Get frequency */
1020           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1021           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1022               sec_name, op_name, &o->frequency))
1023           {
1024               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1025                   op_counter, op, cur->id);
1026               GNUNET_free (type);
1027               GNUNET_free (op_name);
1028               GNUNET_free (op);
1029               return GNUNET_SYSERR;
1030           }
1031           GNUNET_free (op_name);
1032
1033           /* Get preference */
1034           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1035           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1036               sec_name, op_name, &pref))
1037           {
1038               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1039                   op_counter, op, cur->id);
1040               GNUNET_free (type);
1041               GNUNET_free (op_name);
1042               GNUNET_free (op);
1043               GNUNET_free_non_null (pref);
1044               return GNUNET_SYSERR;
1045           }
1046
1047           if (0 == strcmp(pref, "bandwidth"))
1048             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
1049           else if (0 == strcmp(pref, "latency"))
1050             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
1051           else
1052           {
1053               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1054                   op_counter, op, cur->id);
1055               GNUNET_free (type);
1056               GNUNET_free (op_name);
1057               GNUNET_free (op);
1058               GNUNET_free (pref);
1059               GNUNET_free_non_null (pref);
1060               return GNUNET_SYSERR;
1061           }
1062           GNUNET_free (pref);
1063           GNUNET_free (op_name);
1064       }
1065     }
1066
1067     /* Safety checks */
1068     if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
1069         (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
1070     {
1071       if ((o->max_rate - o->base_rate) > o->base_rate)
1072       {
1073         /* This will cause an underflow */
1074         GNUNET_break (0);
1075       }
1076       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
1077     }
1078
1079     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
1080       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
1081         op_counter, cur->id, print_op (o->type), o->src_id,
1082         o->dest_id, (NULL != type) ? type : "",
1083         o->base_rate, o->max_rate,
1084         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
1085     else
1086       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
1087         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
1088
1089     GNUNET_free_non_null (type);
1090     GNUNET_free (op);
1091 #endif
1092
1093   return GNUNET_OK;
1094 }
1095
1096 static int
1097 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1098 {
1099   int e_counter = 0;
1100   char *sec_name;
1101   struct GNUNET_TIME_Relative e_duration;
1102   struct Episode *cur;
1103   struct Episode *last;
1104
1105   e_counter = 0;
1106   last = NULL;
1107   while (1)
1108   {
1109     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1110     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1111         sec_name, "duration", &e_duration))
1112     {
1113       GNUNET_free (sec_name);
1114       break;
1115     }
1116
1117     cur = GNUNET_new (struct Episode);
1118     cur->duration = e_duration;
1119     cur->id = e_counter;
1120
1121     if (GNUNET_OK != load_episode (e, cur, cfg))
1122     {
1123       GNUNET_free (sec_name);
1124       GNUNET_free (cur);
1125       return GNUNET_SYSERR;
1126     }
1127
1128     fprintf (stderr, "Found episode %u with duration %s \n",
1129         e_counter,
1130         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1131
1132     /* Update experiment */
1133     e->num_episodes ++;
1134     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1135     /* Put in linked list */
1136     if (NULL == last)
1137       e->start = cur;
1138     else
1139     last->next = cur;
1140
1141     GNUNET_free (sec_name);
1142     e_counter ++;
1143     last = cur;
1144   }
1145   return e_counter;
1146 }
1147
1148 static void
1149 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1150 {
1151   struct Experiment *e = cls;
1152   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1153   fprintf (stderr, "Experiment timeout!\n");
1154
1155   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1156   {
1157     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1158     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1159   }
1160
1161   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
1162       GNUNET_SYSERR);
1163 }
1164
1165 static void
1166 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
1167 {
1168   /*
1169   struct BenchmarkPeer *peer;
1170   struct BenchmarkPartner *partner;
1171
1172   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
1173   if (NULL == peer)
1174   {
1175     GNUNET_break (0);
1176     return;
1177   }
1178
1179   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1180   if (NULL == partner)
1181   {
1182     GNUNET_break (0);
1183     return;
1184   }
1185
1186   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1187
1188   if (NULL != partner->tg)
1189   {
1190     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
1191     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
1192     partner->tg = NULL;
1193   }
1194
1195   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
1196       op->tg_type, op->base_rate, op->max_rate, op->period,
1197       GNUNET_TIME_UNIT_FOREVER_REL);
1198    */
1199 }
1200
1201 static void
1202 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
1203 {
1204   /*
1205   struct BenchmarkPartner *p;
1206   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1207   if (NULL == p)
1208   {
1209     GNUNET_break (0);
1210     return;
1211   }
1212
1213   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1214
1215   if (NULL != p->tg)
1216   {
1217     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
1218         op->src_id, op->dest_id);
1219     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
1220     p->tg = NULL;
1221   }
1222   */
1223 }
1224
1225 static void
1226 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
1227 {
1228
1229 }
1230
1231 static void
1232 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
1233 {
1234
1235 }
1236
1237 static void
1238 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
1239 {
1240   /*
1241   struct BenchmarkPeer *peer;
1242   struct BenchmarkPartner *partner;
1243
1244   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
1245   if (NULL == peer)
1246   {
1247     GNUNET_break (0);
1248     return;
1249   }
1250
1251   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1252   if (NULL == partner)
1253   {
1254     GNUNET_break (0);
1255     return;
1256   }
1257
1258   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1259
1260   if (NULL != partner->pg)
1261   {
1262     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
1263         op->src_id, op->dest_id);
1264     GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
1265     partner->pg = NULL;
1266   }
1267
1268   partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
1269       op->tg_type, op->base_rate, op->max_rate, op->period, op->frequency,
1270       op->pref_type);
1271       */
1272 }
1273
1274 static void
1275 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
1276 {
1277   /*
1278   struct BenchmarkPartner *p;
1279   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
1280   if (NULL == p)
1281   {
1282     GNUNET_break (0);
1283     return;
1284   }
1285
1286   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
1287
1288   if (NULL != p->pg)
1289   {
1290     fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
1291         op->src_id, op->dest_id);
1292     GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
1293     p->pg = NULL;
1294   }
1295   */
1296 }
1297
1298 static void enforce_episode (struct Episode *ep)
1299 {
1300   struct GNUNET_ATS_TEST_Operation *cur;
1301   for (cur = ep->head; NULL != cur; cur = cur->next)
1302   {
1303     switch (cur->type) {
1304       case SOLVER_OP_ADD_ADDRESS:
1305         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1306             print_op (cur->type), cur->peer_id, cur->address_id);
1307         enforce_add_address (cur);
1308         break;
1309       case SOLVER_OP_DEL_ADDRESS:
1310         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1311             print_op (cur->type), cur->peer_id, cur->address_id);
1312         enforce_del_address (cur);
1313         break;
1314       case SOLVER_OP_START_SET_PROPERTY:
1315         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1316             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1317         enforce_start_property (cur);
1318         break;
1319       case SOLVER_OP_STOP_SET_PROPERTY:
1320         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1321             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1322         enforce_stop_property (cur);
1323         break;
1324       case SOLVER_OP_START_SET_PREFERENCE:
1325         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1326             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1327         enforce_start_preference (cur);
1328         break;
1329       case SOLVER_OP_STOP_SET_PREFERENCE:
1330         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1331             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1332         enforce_stop_preference (cur);
1333         break;
1334       default:
1335         break;
1336     }
1337   }
1338 }
1339
1340 static void
1341 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1342 {
1343   struct Experiment *e = cls;
1344   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1345   if (NULL != e->ep_done_cb)
1346     e->ep_done_cb (e->cur);
1347
1348   /* Scheduling next */
1349   e->cur = e->cur->next;
1350   if (NULL == e->cur)
1351   {
1352     /* done */
1353     fprintf (stderr, "Last episode done!\n");
1354     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1355     {
1356       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1357       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1358     }
1359     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
1360     return;
1361   }
1362
1363   fprintf (stderr, "Running episode %u with timeout %s\n",
1364       e->cur->id,
1365       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1366   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1367       &timeout_episode, e);
1368   enforce_episode(e->cur);
1369
1370
1371 }
1372
1373
1374 void
1375 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
1376     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
1377     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
1378 {
1379   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
1380       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
1381   e->e_done_cb = e_done_cb;
1382   e->ep_done_cb = ep_done_cb;
1383   e->start_time = GNUNET_TIME_absolute_get();
1384
1385   /* Start total time out */
1386   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
1387       &timeout_experiment, e);
1388
1389
1390   /* Start */
1391   if (NULL == e->start)
1392   {
1393     GNUNET_break (0);
1394     return;
1395   }
1396   e->cur = e->start;
1397   fprintf (stderr, "Running episode %u with timeout %s\n",
1398       e->cur->id,
1399       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1400   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1401       &timeout_episode, e);
1402   enforce_episode(e->cur);
1403
1404 }
1405
1406 void
1407 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
1408 {
1409   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1410   {
1411     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1412     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1413   }
1414   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1415   {
1416     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1417     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1418   }
1419   if (NULL != e->cfg)
1420   {
1421     GNUNET_CONFIGURATION_destroy(e->cfg);
1422     e->cfg = NULL;
1423   }
1424   free_experiment (e);
1425 }
1426
1427
1428 struct Experiment *
1429 GNUNET_ATS_solvers_experimentation_load (char *filename)
1430 {
1431   struct Experiment *e;
1432   struct GNUNET_CONFIGURATION_Handle *cfg;
1433   e = NULL;
1434
1435   cfg = GNUNET_CONFIGURATION_create();
1436   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
1437   {
1438     fprintf (stderr, "Failed to load `%s'\n", filename);
1439     GNUNET_CONFIGURATION_destroy (cfg);
1440     return NULL;
1441   }
1442
1443   e = create_experiment ();
1444
1445   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
1446       "name", &e->name))
1447   {
1448     fprintf (stderr, "Invalid %s", "name");
1449     free_experiment (e);
1450     return NULL;
1451   }
1452   else
1453     fprintf (stderr, "Experiment name: `%s'\n", e->name);
1454
1455   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
1456       "cfg_file", &e->cfg_file))
1457   {
1458     fprintf (stderr, "Invalid %s", "cfg_file");
1459     free_experiment (e);
1460     return NULL;
1461   }
1462   else
1463   {
1464     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
1465     e->cfg = GNUNET_CONFIGURATION_create();
1466     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
1467     {
1468       fprintf (stderr, "Invalid configuration %s", "cfg_file");
1469       free_experiment (e);
1470       return NULL;
1471     }
1472
1473   }
1474
1475   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
1476       "masters", &e->num_masters))
1477   {
1478     fprintf (stderr, "Invalid %s", "masters");
1479     free_experiment (e);
1480     return NULL;
1481   }
1482   else
1483     fprintf (stderr, "Experiment masters: `%llu'\n",
1484         e->num_masters);
1485
1486   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
1487       "slaves", &e->num_slaves))
1488   {
1489     fprintf (stderr, "Invalid %s", "slaves");
1490     free_experiment (e);
1491     return NULL;
1492   }
1493   else
1494     fprintf (stderr, "Experiment slaves: `%llu'\n",
1495         e->num_slaves);
1496
1497   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
1498       "log_freq", &e->log_freq))
1499   {
1500     fprintf (stderr, "Invalid %s", "log_freq");
1501     free_experiment (e);
1502     return NULL;
1503   }
1504   else
1505     fprintf (stderr, "Experiment logging frequency: `%s'\n",
1506         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
1507
1508   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
1509       "max_duration", &e->max_duration))
1510   {
1511     fprintf (stderr, "Invalid %s", "max_duration");
1512     free_experiment (e);
1513     return NULL;
1514   }
1515   else
1516     fprintf (stderr, "Experiment duration: `%s'\n",
1517         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
1518
1519   if (GNUNET_SYSERR == load_episodes (e, cfg))
1520   {
1521     GNUNET_ATS_solvers_experimentation_stop (e);
1522     GNUNET_CONFIGURATION_destroy (cfg);
1523     e = NULL;
1524     fprintf (stderr, "Failed to load experiment\n");
1525     return NULL;
1526   }
1527   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
1528       e->num_episodes,
1529       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
1530
1531   GNUNET_CONFIGURATION_destroy (cfg);
1532   return e;
1533 }
1534
1535 /**
1536  * Logging
1537  */
1538
1539
1540 /**
1541  * Solver
1542  */
1543
1544 struct GNUNET_ATS_TESTING_SolverHandle
1545 {
1546   char * plugin;
1547   struct GNUNET_ATS_PluginEnvironment env;
1548   void *solver;
1549   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
1550 };
1551
1552 enum GNUNET_ATS_Solvers
1553 {
1554   GNUNET_ATS_SOLVER_PROPORTIONAL,
1555   GNUNET_ATS_SOLVER_MLP,
1556   GNUNET_ATS_SOLVER_RIL,
1557 };
1558
1559 void
1560 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
1561 {
1562  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
1563      GNUNET_NO);
1564  GNUNET_CONTAINER_multipeermap_destroy(sh->env.addresses);
1565  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
1566  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
1567  GNUNET_free (sh->plugin);
1568  GNUNET_free (sh);
1569 }
1570
1571 /**
1572  * Load quotas for networks from configuration
1573  *
1574  * @param cfg configuration handle
1575  * @param out_dest where to write outbound quotas
1576  * @param in_dest where to write inbound quotas
1577  * @param dest_length length of inbound and outbound arrays
1578  * @return number of networks loaded
1579  */
1580 unsigned int
1581 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
1582                                                  unsigned long long *out_dest,
1583                                                  unsigned long long *in_dest,
1584                                                  int dest_length)
1585 {
1586   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
1587   char * entry_in = NULL;
1588   char * entry_out = NULL;
1589   char * quota_out_str;
1590   char * quota_in_str;
1591   int c;
1592   int res;
1593
1594   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
1595   {
1596     in_dest[c] = 0;
1597     out_dest[c] = 0;
1598     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
1599     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
1600
1601     /* quota out */
1602     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
1603     {
1604       res = GNUNET_NO;
1605       if (0 == strcmp(quota_out_str, BIG_M_STRING))
1606       {
1607         out_dest[c] = GNUNET_ATS_MaxBandwidth;
1608         res = GNUNET_YES;
1609       }
1610       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
1611         res = GNUNET_YES;
1612       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
1613          res = GNUNET_YES;
1614
1615       if (GNUNET_NO == res)
1616       {
1617           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
1618               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
1619           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1620       }
1621       else
1622       {
1623           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
1624               network_str[c], out_dest[c]);
1625       }
1626       GNUNET_free (quota_out_str);
1627     }
1628     else
1629     {
1630       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
1631           network_str[c], GNUNET_ATS_DefaultBandwidth);
1632       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1633     }
1634
1635     /* quota in */
1636     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
1637     {
1638       res = GNUNET_NO;
1639       if (0 == strcmp(quota_in_str, BIG_M_STRING))
1640       {
1641         in_dest[c] = GNUNET_ATS_MaxBandwidth;
1642         res = GNUNET_YES;
1643       }
1644       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
1645         res = GNUNET_YES;
1646       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
1647          res = GNUNET_YES;
1648
1649       if (GNUNET_NO == res)
1650       {
1651           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
1652               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
1653           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
1654       }
1655       else
1656       {
1657           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
1658               network_str[c], in_dest[c]);
1659       }
1660       GNUNET_free (quota_in_str);
1661     }
1662     else
1663     {
1664       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
1665           network_str[c], GNUNET_ATS_DefaultBandwidth);
1666       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1667     }
1668     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]);
1669     GNUNET_free (entry_out);
1670     GNUNET_free (entry_in);
1671   }
1672   return GNUNET_ATS_NetworkTypeCount;
1673 }
1674
1675 /**
1676  * Information callback for the solver
1677  *
1678  * @param op the solver operation
1679  * @param stat status of the solver operation
1680  * @param add additional solver information
1681  */
1682 static void
1683 solver_info_cb (void *cls,
1684     enum GAS_Solver_Operation op,
1685     enum GAS_Solver_Status stat,
1686     enum GAS_Solver_Additional_Information add)
1687 {
1688   char *add_info;
1689   switch (add) {
1690     case GAS_INFO_NONE:
1691       add_info = "GAS_INFO_NONE";
1692       break;
1693     case GAS_INFO_FULL:
1694       add_info = "GAS_INFO_MLP_FULL";
1695       break;
1696     case GAS_INFO_UPDATED:
1697       add_info = "GAS_INFO_MLP_UPDATED";
1698       break;
1699     case GAS_INFO_PROP_ALL:
1700       add_info = "GAS_INFO_PROP_ALL";
1701       break;
1702     case GAS_INFO_PROP_SINGLE:
1703       add_info = "GAS_INFO_PROP_SINGLE";
1704       break;
1705     default:
1706       add_info = "INVALID";
1707       break;
1708   }
1709
1710   switch (op)
1711   {
1712     case GAS_OP_SOLVE_START:
1713       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1714           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
1715           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
1716       return;
1717     case GAS_OP_SOLVE_STOP:
1718       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1719           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
1720           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
1721       return;
1722
1723     case GAS_OP_SOLVE_SETUP_START:
1724       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1725           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
1726           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1727       return;
1728
1729     case GAS_OP_SOLVE_SETUP_STOP:
1730       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1731           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
1732           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1733       return;
1734
1735     case GAS_OP_SOLVE_MLP_LP_START:
1736       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1737           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
1738           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1739       return;
1740     case GAS_OP_SOLVE_MLP_LP_STOP:
1741       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1742           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
1743           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1744       return;
1745
1746     case GAS_OP_SOLVE_MLP_MLP_START:
1747       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1748           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
1749           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1750       return;
1751     case GAS_OP_SOLVE_MLP_MLP_STOP:
1752       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1753           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
1754           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1755       return;
1756     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
1757       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1758           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
1759           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1760       return;
1761     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
1762       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1763           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
1764           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1765       return;
1766     default:
1767       break;
1768     }
1769 }
1770
1771 static void
1772 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
1773 {
1774   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
1775        (0 == ntohl (address->assigned_bw_in.value__)) )
1776     return;
1777
1778   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1779               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
1780               GNUNET_i2s (&address->peer),
1781               address,
1782               (unsigned int) ntohl (address->assigned_bw_out.value__),
1783               (unsigned int) ntohl (address->assigned_bw_in.value__));
1784   /*if (GNUNET_YES == ph.bulk_running)
1785     GNUNET_break (0);*/
1786   return;
1787 }
1788
1789 const double *
1790 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
1791 {
1792   return GAS_normalization_get_preferences_by_peer (id);
1793 }
1794
1795
1796 const double *
1797 get_property_cb (void *cls, const struct ATS_Address *address)
1798 {
1799   return GAS_normalization_get_properties ((struct ATS_Address *) address);
1800 }
1801
1802 static void
1803 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
1804     uint32_t type, double prop_rel)
1805 {
1806   /* TODO */
1807 }
1808
1809
1810 struct GNUNET_ATS_TESTING_SolverHandle *
1811 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
1812 {
1813   struct GNUNET_ATS_TESTING_SolverHandle *sh;
1814   char * solver_str;
1815   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
1816   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
1817
1818   switch (type) {
1819     case GNUNET_ATS_SOLVER_PROPORTIONAL:
1820       solver_str = "proportional";
1821       break;
1822     case GNUNET_ATS_SOLVER_MLP:
1823       solver_str = "mlp";
1824       break;
1825     case GNUNET_ATS_SOLVER_RIL:
1826       solver_str = "ril";
1827       break;
1828     default:
1829       GNUNET_break (0);
1830       return NULL;
1831       break;
1832   }
1833
1834   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
1835   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
1836
1837   /* setup environment */
1838   sh->env.cfg = e->cfg;
1839   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
1840   sh->env.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1841   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
1842   sh->env.get_preferences = &get_preferences_cb;
1843   sh->env.get_property = &get_property_cb;
1844   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
1845   sh->env.info_cb = &solver_info_cb;
1846   sh->env.info_cb_cls = NULL;
1847
1848   /* start normalization */
1849   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
1850
1851   /* load quotas */
1852   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
1853       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
1854   {
1855     GNUNET_break(0);
1856     GNUNET_free (sh->plugin);
1857     GNUNET_free (sh);
1858     end_now ();
1859     return NULL;
1860   }
1861
1862   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
1863   if (NULL == sh->solver)
1864   {
1865     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
1866     GNUNET_break(0);
1867     GNUNET_free (sh->plugin);
1868     GNUNET_free (sh);
1869     end_now ();
1870     return NULL;
1871   }
1872
1873   sh->addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1874
1875   return sh;
1876 }
1877
1878 static void
1879 done ()
1880 {
1881   /* Clean up experiment */
1882   GNUNET_ATS_solvers_experimentation_stop (e);
1883   e = NULL;
1884
1885   /* Shutdown */
1886   end_now();
1887
1888 }
1889
1890 static void
1891 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
1892 {
1893   if (GNUNET_OK == success)
1894     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
1895         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
1896   else
1897     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
1898
1899   /* Stop logging */
1900   // GNUNET_ATS_TEST_logging_stop (l);
1901
1902   /* Stop traffic generation */
1903   // GNUNET_ATS_TEST_generate_traffic_stop_all();
1904
1905   /* Stop all preference generations */
1906   // GNUNET_ATS_TEST_generate_preferences_stop_all ();
1907
1908   /*
1909   evaluate (duration);
1910   if (opt_log)
1911     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
1912
1913   if (NULL != l)
1914   {
1915     GNUNET_ATS_TEST_logging_stop (l);
1916     GNUNET_ATS_TEST_logging_clean_up (l);
1917     l = NULL;
1918   }
1919   */
1920   GNUNET_SCHEDULER_add_now (&done, NULL);
1921 }
1922
1923 static void
1924 episode_done_cb (struct Episode *ep)
1925 {
1926   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
1927 }
1928
1929
1930
1931 /**
1932  * Do shutdown
1933  */
1934 static void
1935 end_now ()
1936 {
1937   if (NULL != e)
1938   {
1939     GNUNET_ATS_solvers_experimentation_stop (e);
1940     e = NULL;
1941   }
1942   if (NULL != sh)
1943   {
1944     GNUNET_ATS_solvers_solver_stop (sh);
1945     sh = NULL;
1946   }
1947 }
1948
1949 static void
1950 run (void *cls, char * const *args, const char *cfgfile,
1951     const struct GNUNET_CONFIGURATION_Handle *cfg)
1952 {
1953   enum GNUNET_ATS_Solvers solver;
1954
1955   if (NULL == opt_exp_file)
1956   {
1957     fprintf (stderr, "No experiment given ...\n");
1958     res = 1;
1959     end_now ();
1960     return;
1961   }
1962
1963   if (NULL == opt_solver)
1964   {
1965     fprintf (stderr, "No solver given ...\n");
1966     res = 1;
1967     end_now ();
1968     return;
1969   }
1970
1971   if (0 == strcmp(opt_solver, "mlp"))
1972   {
1973     solver = GNUNET_ATS_SOLVER_MLP;
1974   }
1975   else if (0 == strcmp(opt_solver, "proportional"))
1976   {
1977     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
1978   }
1979   else if (0 == strcmp(opt_solver, "ril"))
1980   {
1981     solver = GNUNET_ATS_SOLVER_RIL;
1982   }
1983   else
1984   {
1985     fprintf (stderr, "No solver given ...");
1986     res = 1;
1987     end_now ();
1988     return;
1989   }
1990
1991   /* load experiment */
1992   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
1993   if (NULL == e)
1994   {
1995     fprintf (stderr, "Failed to load experiment ...\n");
1996     res = 1;
1997     end_now ();
1998     return;
1999   }
2000
2001
2002   /* load solver */
2003   sh = GNUNET_ATS_solvers_solver_start (solver);
2004   if (NULL == sh)
2005   {
2006     fprintf (stderr, "Failed to start solver ...\n");
2007     end_now ();
2008     res = 1;
2009     return;
2010   }
2011
2012   /* start logging */
2013
2014
2015   /* run experiment */
2016   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
2017       experiment_done_cb);
2018
2019   /* WAIT */
2020 }
2021
2022
2023 /**
2024  * Main function of the benchmark
2025  *
2026  * @param argc argument count
2027  * @param argv argument values
2028  */
2029 int
2030 main (int argc, char *argv[])
2031 {
2032   opt_exp_file = NULL;
2033   opt_solver = NULL;
2034   opt_log = GNUNET_NO;
2035   opt_plot = GNUNET_NO;
2036
2037   res = 0;
2038
2039   static struct GNUNET_GETOPT_CommandLineOption options[] =
2040   {
2041     { 's', "solver", NULL,
2042         gettext_noop ("solver to use"),
2043         1, &GNUNET_GETOPT_set_string, &opt_solver},
2044     {  'e', "experiment", NULL,
2045       gettext_noop ("experiment to use"),
2046       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
2047     {  'e', "experiment", NULL,
2048       gettext_noop ("experiment to use"),
2049       1, &GNUNET_GETOPT_set_one, &opt_verbose},
2050     GNUNET_GETOPT_OPTION_END
2051   };
2052
2053   GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
2054
2055   return res;
2056 }
2057 /* end of file ats-testing-experiment.c*/
2058