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