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